📄 irc-event-2.c
字号:
/* * irc-event-2.c - IRC events -- Channel operations * * 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-2.c,v 1.16 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>#ifdef __MINGW32__# include <winsock2.h>#endif#include <libserveez.h>#include "irc-core/irc-core.h"#include "irc-proto.h"#include "irc-event.h"/* * Command: PART * Parameters: <channel>{,<channel>} * Numeric Replies: ERR_NEEDMOREPARAMS ERR_NOSUCHCHANNEL * ERR_NOTONCHANNEL */intirc_part_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; int n; /* do you have enough paras ? */ if (irc_check_args (sock, client, cfg, request, 1)) return 0; /* go through all targets in the first para */ for (n = 0; n < request->targets; n++) { /* does the channel exist ? */ if ((channel = irc_find_channel (cfg, request->target[n].channel)) == NULL) { irc_printf (sock, ":%s %03d %s " ERR_NOSUCHCHANNEL_TEXT "\n", cfg->host, ERR_NOSUCHCHANNEL, client->nick, request->target[n].channel); return 0; } /* yes, look if the client is in it */ if (irc_client_in_channel (sock, client, channel) == -1) return 0; /* send back the PART to all channel clients */ for (n = 0; n < channel->clients; n++) { cl = channel->client[n]; xsock = cl->sock; irc_printf (xsock, ":%s!%s@%s PART %s :%s\n", client->nick, client->user, client->host, channel->name, request->para[1]); } irc_leave_channel (cfg, client, channel); } return 0;}/* * This function returns no zero value if a given client matches * a given channel ban entry. */static intirc_client_banned (irc_client_t *client, irc_ban_t *ban){ /* does the nick Match ? */ if (!irc_string_regex (client->nick, ban->nick)) return 0; /* does the user Match ? */ if (!irc_string_regex (client->user, ban->user)) return 0; /* does the host Match ? */ if (!irc_string_regex (client->host, ban->host)) return 0; return -1;}/* * Send the channel topic to an IRC client. */static voidirc_channel_topic (svz_socket_t *sock, irc_client_t *client, irc_channel_t *channel){ irc_config_t *cfg = sock->cfg; /* send topic if there is one */ if (channel->topic) { irc_printf (sock, ":%s %03d %s " RPL_TOPIC_TEXT "\n", cfg->host, RPL_TOPIC, client->nick, channel->name, channel->topic); /* send topic date and nick (this is not part of the RFC) */ irc_printf (sock, ":%s %03d %s " RPL_TOPICSET_TEXT "\n", cfg->host, RPL_TOPICSET, client->nick, channel->name, channel->topic_by, channel->topic_since); } /* no topic set yet */ else { irc_printf (sock, ":%s %03d %s " RPL_NOTOPIC_TEXT "\n", cfg->host, RPL_NOTOPIC, client->nick, channel->name); }}/* * Send a channels users to a specified client. */static voidirc_channel_users (svz_socket_t *sock, irc_client_t *client, irc_channel_t *channel){ irc_config_t *cfg = sock->cfg; char nicklist[MAX_MSG_LEN]; irc_client_t *cl; int n; /* prebuild the nicklist */ for (nicklist[0] = 0, n = 0; n < channel->clients; n++) { /* check if the client is visible or not */ cl = channel->client[n]; if (!(cl->flag & UMODE_INVISIBLE) && irc_client_in_channel (NULL, client, channel) != -1) { if (channel->cflag[n] & MODE_OPERATOR) strcat (nicklist, "@"); else if (channel->cflag[n] & MODE_VOICE) strcat (nicklist, "+"); strcat (nicklist, channel->client[n]->nick); strcat (nicklist, " "); } } /* send channel info */ irc_printf (sock, ":%s %03d %s " RPL_NAMREPLY_TEXT "\n", cfg->host, RPL_NAMREPLY, client->nick, channel->flag & (MODE_PRIVATE | MODE_SECRET) ? '*' : '=', channel->name, nicklist);}/* * Command: JOIN * Parameters: <channel>{,<channel>} [<key>{,<key>}] * Numeric Replies: ERR_NEEDMOREPARAMS ERR_BANNEDFROMCHAN * ERR_INVITEONLYCHAN ERR_BADCHANNELKEY * ERR_CHANNELISFULL ERR_BADCHANMASK * ERR_NOSUCHCHANNEL ERR_TOOMANYCHANNELS * RPL_TOPIC */intirc_join_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 *chan; int n, i; /* do you have enough paras ? */ if (irc_check_args (sock, client, cfg, request, 1)) return 0; /* go through all targets in the first para */ for (n = 0; n < request->targets; n++) { chan = request->target[n].channel; /* does the channel already exists ? */ if ((channel = irc_find_channel (cfg, chan)) != NULL) { /* is a key set for this channel and is the given one ok ? */ if (channel->flag & MODE_KEY && strcmp (irc_get_target (request->para[1], n), channel->key)) { irc_printf (sock, ":%s %03d %s " ERR_BADCHANNELKEY_TEXT "\n", cfg->host, ERR_BADCHANNELKEY, client->nick, channel->name); return 0; } /* invite only ? */ if (channel->flag & MODE_INVITE) { /* find the nick in the invite list of the channel */ for (i = 0; i < channel->invites; i++) if (channel->invite[i] == client) break; /* not in this list ! */ if (i == channel->invites) { irc_printf (sock, ":%s %03d %s " ERR_INVITEONLYCHAN_TEXT "\n", cfg->host, ERR_INVITEONLYCHAN, client->nick, channel->name); return 0; } /* clear this invite entry */ else { if (--channel->invites != 0) { channel->invite[i] = channel->invite[channel->invites]; channel->invite = svz_realloc (channel->invite, sizeof (irc_client_t *) * channel->invites); } else { svz_free (channel->invite); channel->invite = NULL; } } } /* is channel full ? */ if (channel->flag & MODE_ULIMIT && channel->clients >= channel->users) { irc_printf (sock, ":%s %03d %s " ERR_CHANNELISFULL_TEXT "\n", cfg->host, ERR_CHANNELISFULL, client->nick, channel->name); return 0; } /* is this client banned ? */ for (i = 0; i < channel->bans; i++) { if (irc_client_banned (client, channel->ban[i])) { irc_printf (sock, ":%s %03d %s " ERR_BANNEDFROMCHAN_TEXT "\n", cfg->host, ERR_BANNEDFROMCHAN, client->nick, channel->name); return 0; } } } /* done, do not deny this channel ! */ irc_join_channel (cfg, client, chan); if ((channel = irc_find_channel (cfg, chan)) == NULL) continue; /* send back the JOIN to all channel clients */ for (i = 0; i < channel->clients; i++) { cl = channel->client[i]; xsock = cl->sock; irc_printf (xsock, ":%s!%s@%s JOIN :%s\n", client->nick, client->user, client->host, chan); } /* send topic */ irc_channel_topic (sock, client, channel); /* send creation date and nick (this is not part of the RFC) */ irc_printf (sock, ":%s %03d %s " RPL_CHANCREATED_TEXT "\n", cfg->host, RPL_CHANCREATED, client->nick, channel->name, channel->since); /* send nick list */ irc_channel_users (sock, client, channel); irc_printf (sock, ":%s %03d %s " RPL_ENDOFNAMES_TEXT "\n", cfg->host, RPL_ENDOFNAMES, client->nick, channel->name); } return 0;}/* * Create a ban mask string by a channels ban entry. */static char *irc_ban_string (irc_ban_t *ban){ static char text[MAX_MSG_LEN] = ""; if (ban->nick) { strcat (text, ban->nick); strcat (text, "!"); } if (ban->user) { strcat (text, ban->user); strcat (text, "@"); } strcat (text, ban->host); return text;}/* * Check if a given client is channel operator in its channel and * send an error about this if necessary. The function returns a non * zero value if the client is an operator otherwise zero. */static intirc_client_oper (svz_socket_t *sock, irc_client_t *client, irc_channel_t *channel, int flag){ irc_config_t *cfg = sock->cfg; if (!(flag & MODE_OPERATOR)) { irc_printf (sock, ":%s %03d %s " ERR_CHANOPRIVSNEEDED_TEXT "\n", cfg->host, ERR_CHANOPRIVSNEEDED, client->nick, channel->name); return 0; } return -1;}/* * Set or unset a channel flag for a user in the channel. */static intirc_client_flag (irc_client_t *client, /* client changing the flag */ svz_socket_t *sock, /* this clients connection */ int cflag, /* this clients flags */ char *nick, /* the nick the mode is for */ irc_channel_t *channel, /* mode change for this channel */ int flag, /* flag to be set / unset */ char set) /* set / unset */{ irc_client_t *cl; svz_socket_t *xsock; int i, n; unsigned l; static char *Modes = CHANNEL_MODES; char Mode = ' '; /* find Mode character */ for (l = 0; l < strlen (Modes); l++) if (flag & (1 << l)) { Mode = Modes[l]; break; } if (!irc_client_oper (sock, client, channel, cflag)) return 0; /* find nick in channel */ for (i = 0; i < channel->clients; i++) if (!strcmp (channel->client[i]->nick, nick)) { if (set) channel->cflag[i] |= flag; else channel->cflag[i] &= ~flag; break; } /* no such nick in channel ! */ if (i == channel->clients) { irc_printf (sock, "%03d " ERR_NOSUCHNICK_TEXT "\n", ERR_NOSUCHNICK, nick); return 0; } /* propagate Mode change to channel users */ for (n = 0; n < channel->clients; n++) { cl = channel->client[n]; xsock = cl->sock; irc_printf (xsock, ":%s!%s@%s MODE %s %c%c %s\n", client->nick, client->user, client->host, channel->name, set ? '+' : '-', Mode, channel->client[i]->nick); } return 0;}/* * Set or unset a flag for a user by itself. */static intirc_user_flag (irc_client_t *client, /* client changing the flag */ svz_socket_t *sock, /* this clients connection */ int flag, /* flag to be set / unset */ char set) /* set / unset */{ irc_config_t *cfg = sock->cfg; unsigned l; static char *Modes = USER_MODES; char Mode = ' '; /* find Mode character */ for (l = 0; l < strlen (Modes); l++) if (flag & (1 << l)) { Mode = Modes[l]; break; } /* is this client able to change the flag */ if (set) { if (flag & UMODE_INVISIBLE && !(client->flag & UMODE_INVISIBLE)) cfg->invisibles++; /* this flag cannot be set by anyone ! */ if (!(flag & UMODE_OPERATOR)) client->flag |= flag; else return 0; } else { if (flag & UMODE_INVISIBLE && client->flag & UMODE_INVISIBLE) cfg->invisibles--; client->flag &= ~flag; } /* propagate Mode change to this users */ irc_printf (sock, ":%s!%s@%s MODE %s %c%c\n", client->nick, client->user, client->host, client->nick, set ? '+' : '-', Mode); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -