📄 irc-event-1.c
字号:
/* * irc-event-1.c - IRC events -- Connection Registration * * Copyright (C) 2000 Stefan Jahn <stefan@lkcc.org> * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: irc-event-1.c,v 1.19 2001/05/19 23:04:57 ela Exp $ * */#if HAVE_CONFIG_H# include <config.h>#endif#if ENABLE_IRC_PROTO#define _GNU_SOURCE#include <string.h>#include <stdlib.h>#include <errno.h>#include <sys/stat.h>#if HAVE_UNISTD_H# include <unistd.h>#endif#ifdef __MINGW32__# include <winsock2.h>#endif#include "libserveez.h"#include "irc-core/irc-core.h"#include "irc-proto.h"#include "irc-crypt.h"#include "irc-event.h"#include "irc-config.h"/* * Command: QUIT * Parameters: [<Quit message>] */intirc_quit_callback (svz_socket_t *sock, irc_client_t *client, irc_request_t *request){ /* delete the client */ irc_leave_all_channels (sock->cfg, client, request->para[0]); return -1;}/* * Command: PASS * Parameters: <password> * Numeric Replies: ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED */intirc_pass_callback (svz_socket_t *sock, irc_client_t *client, irc_request_t *request){ irc_config_t *cfg = sock->cfg; /* enough paras ? reject the client if not given */ if (irc_check_args (sock, client, cfg, request, 1)) return -1; if (client->pass) svz_free (client->pass); client->pass = svz_strdup (request->para[0]); client->key = irc_gen_key (client->pass); client->flag |= UMODE_PASS; /* check it ! */ if (cfg->pass) {#if ENABLE_CRYPT && HAVE_CRYPT if (strcmp (crypt (request->para[0], cfg->pass), cfg->pass))#else if (strcmp (request->para[0], cfg->pass))#endif { irc_delete_client (cfg, client); return -1; } } return 0;}/* * Send the initial messages to a new IRC client. */static voidirc_send_init_block (svz_socket_t *sock, irc_client_t *client){ irc_config_t *cfg = sock->cfg; /* send initial messages */ irc_printf (sock, ":%s %03d %s :" RPL_WELCOME_TEXT "\n", cfg->host, RPL_WELCOME, client->nick, client->nick); irc_printf (sock, ":%s %03d %s :" RPL_YOURHOST_TEXT "\n", cfg->host, RPL_YOURHOST, client->nick, cfg->host, svz_library, svz_version); irc_printf (sock, "NOTICE %s :*** " RPL_YOURHOST_TEXT "\n", client->nick, cfg->host, svz_library, svz_version); irc_printf (sock, ":%s %03d %s :" RPL_CREATED_TEXT "\n", cfg->host, RPL_CREATED, client->nick, svz_build); irc_printf (sock, ":%s %03d %s " RPL_MYINFO_TEXT "\n", cfg->host, RPL_MYINFO, client->nick, cfg->host, svz_library, svz_version, USER_MODES, CHANNEL_MODES); /* send LUSER* replies */ irc_lusers_callback (sock, client, NULL); /* send the "Message of the Day" */ irc_motd_callback (sock, client, NULL);}/* * If a client has been fully registered and identified it gets * validated by the config lines. */intirc_register_client (svz_socket_t *sock, irc_client_t *client, irc_config_t *cfg){ if ((client->flag & UMODE_REGISTERED) == UMODE_REGISTERED) { if (!irc_client_valid (client, cfg)) return -1; irc_add_client (cfg, client); irc_send_init_block (sock, client); client->registered = 1; } return 0;}/* * This function extracts a valid nick of a given text. It returns * the length of it, otherwise zero. */static intirc_get_nick (char *nick){ char *p; int n; p = nick; if ((*p >= '0' && *p <= '9') || *p == '-') return 0; for (n = 0; *p && n < MAX_NICK_LEN; n++, p++) if (!((*p >= 'A' && *p <= '~') || (*p >= '0' && *p <= '9') || (*p == '_') || (*p == '-'))) break; *p = 0; return p - nick;}/* * Command: NICK * Parameters: <nickname> [ <hopcount> ] * Numeric Replies: ERR_NONICKNAMEGIVEN ERR_ERRONEUSNICKNAME * ERR_NICKNAMEINUSE ERR_NICKCOLLISION */intirc_nick_callback (svz_socket_t *sock, irc_client_t *client, irc_request_t *request){ irc_config_t *cfg = sock->cfg; irc_client_t *cl; irc_channel_t *channel; svz_socket_t *xsock; char *nick; int n, i; /* enough para's ? */ if (request->paras < 1) { irc_printf (sock, ":%s %03d " ERR_NONICKNAMEGIVEN_TEXT "\n", cfg->host, ERR_NONICKNAMEGIVEN); return 0; } /* is the given nick valid ? */ nick = request->para[0]; if (!irc_get_nick (nick)) { irc_printf (sock, ":%s %03d * " ERR_ERRONEUSNICKNAME_TEXT "\n", cfg->host, ERR_ERRONEUSNICKNAME, nick); return 0; } /* nick already in use ? */ if ((cl = irc_find_nick (cfg, nick)) != NULL) { /* did the client tried to change to equal nicks ? then ignore */ if (cl == client) return 0;#if ENABLE_DEBUG svz_log (LOG_DEBUG, "irc: nick %s is already in use\n", cl->nick);#endif irc_printf (sock, ":%s %03d * " ERR_NICKNAMEINUSE_TEXT "\n", cfg->host, ERR_NICKNAMEINUSE, cl->nick); return 0; } /* do you have already specified a valid nick ? */ if (client->flag & UMODE_NICK) {#if ENABLE_DEBUG svz_log (LOG_DEBUG, "irc: %s changed nick to %s\n", client->nick, nick);#endif /* is the client fully registered ? */ if (client->registered) { /* go through all channels this client is in */ for (n = 0; n < client->channels; n++) { /* propagate this to all clients in channel */ channel = client->channel[n]; for (i = 0; i < channel->clients; i++) { cl = channel->client[i]; xsock = cl->sock; irc_printf (xsock, ":%s!%s@%s NICK :%s\n", client->nick, client->user, client->host, nick); } } /* replace nick in client hash */ if (svz_hash_delete (cfg->clients, client->nick) != client) { svz_log (LOG_ERROR, "irc: client hash inconsistence\n"); } svz_hash_put (cfg->clients, nick, client); } svz_free (client->nick); } /* this is the first nick you specified ! */ client->nick = svz_strdup (nick); client->flag |= UMODE_NICK; return 0;}/* * Command: USER * Parameters: <username> <hostname> <servername> <realname> * Numeric Replies: ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED */intirc_user_callback (svz_socket_t *sock, irc_client_t *client, irc_request_t *request){ irc_config_t *cfg = sock->cfg; /* complete parameter list ? */ if (irc_check_args (sock, client, cfg, request, 4)) return 0; /* is this client already fully registered ? */ if (client->flag & UMODE_USER) { irc_printf (sock, ":%s %03d %s " ERR_ALREADYREGISTRED_TEXT "\n", cfg->host, ERR_ALREADYREGISTRED, client->nick); return 0; } /* store paras in client structure if not done by AUTH-callbacks */ if (!client->user) { client->user = svz_malloc (strlen (request->para[0]) + 2); sprintf (client->user, "~%s", request->para[0]); } if (!client->host) client->host = svz_strdup (request->para[1]); if (!client->server) client->server = svz_strdup (request->para[2]); if (!client->real) client->real = svz_strdup (request->para[3]); client->flag |= UMODE_USER; return 0;}/* * Command: MOTD * Parameters: * Numeric Replies: ERR_NOMOTD RPL_MOTDSTART * RPL_ENDOFMOTD RPL_MOTD */intirc_motd_callback (svz_socket_t *sock, irc_client_t *client, irc_request_t *request){ irc_config_t *cfg = sock->cfg; FILE *f; struct stat buf; int n; /* try requesting the file */ if (stat (cfg->MOTD_file, &buf) == -1) { svz_log (LOG_ERROR, "irc: /MOTD error: %s (%s)\n", SYS_ERROR, cfg->MOTD_file); irc_printf (sock, ":%s %03d %s " ERR_NOMOTD_TEXT "\n", cfg->host, ERR_NOMOTD, client->nick); return 0; } /* has the file been changed ? then read it */ if (cfg->MOTD_lastModified < buf.st_mtime) { cfg->MOTD_lastModified = buf.st_mtime; if ((f = fopen (cfg->MOTD_file, "r")) == NULL) { svz_log (LOG_ERROR, "irc: /MOTD error: %s\n", SYS_ERROR); return 0; } /* free the previous MOTD content */ for (n = 0; n < cfg->MOTDs; n++) svz_free (cfg->MOTD[n]); /* read every line (restrict line length) */ n = 0; cfg->MOTD[n] = svz_malloc (MOTD_LINE_LEN); while (fgets (cfg->MOTD[n], MOTD_LINE_LEN, f) && n < MAX_MOTD_LINES) { cfg->MOTD[n][strlen (cfg->MOTD[n]) - 1] = '\0'; n++; cfg->MOTD[n] = svz_malloc (MOTD_LINE_LEN); } svz_free (cfg->MOTD[n]); cfg->MOTDs = n; fclose (f); } /* send the "Message of the Day" if necessary */ if (cfg->MOTDs) { /* start */ irc_printf (sock, "NOTICE %s :*** The MOTD file was last modified at %s\n", client->nick, svz_time (cfg->MOTD_lastModified)); irc_printf (sock, ":%s %03d %s " RPL_MOTDSTART_TEXT "\n", cfg->host, RPL_MOTDSTART, client->nick, cfg->host); /* go through all lines */ for (n = 0; n < cfg->MOTDs; n++) { irc_printf (sock, ":%s %03d %s " RPL_MOTD_TEXT "\n", cfg->host, RPL_MOTD, client->nick, cfg->MOTD[n]); } /* end */ irc_printf (sock, ":%s %03d %s " RPL_ENDOFMOTD_TEXT "\n", cfg->host, RPL_ENDOFMOTD, client->nick, cfg->host); } return 0;}/* * Command: OPER * Parameters: <user> <password> * Numeric Replies: ERR_NEEDMOREPARAMS RPL_YOUREOPER * ERR_NOOPERHOST ERR_PASSWDMISMATCH */intirc_oper_callback (svz_socket_t *sock, irc_client_t *client, irc_request_t *request){ irc_config_t *cfg = sock->cfg; /* did the client send a complete parameter list ? */ if (irc_check_args (sock, client, cfg, request, 2)) return 0; /* copy both parameters into client structure */ strcpy (client->pass, request->para[1]); if (!client->user[0]) strcpy (client->user, request->para[0]); /* check if this client may be an IRC operator */ if (irc_oper_valid (client, cfg)) { cfg->operators++; client->flag |= UMODE_OPERATOR; irc_printf (sock, ":%s %03d %s " RPL_YOUREOPER_TEXT "\n", cfg->host, RPL_YOUREOPER, client->nick); } else { irc_printf (sock, ":%s %03d %s " ERR_NOOPERHOST_TEXT "\n", cfg->host, ERR_NOOPERHOST, client->nick); } return 0;}#else /* not ENABLE_IRC_PROTO */int irc_event_1_dummy; /* Shut up compiler warnings. */#endif /* not ENABLE_IRC_PROTO */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -