📄 irc-event-2.c
字号:
/* * Set or unset a channel flag. */static intirc_channel_flag (irc_client_t *client, /* client changing the flag */ svz_socket_t *sock, /* this clients connection */ int cflag, /* this clients flags */ 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 n; unsigned l; 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; if (set) channel->flag |= flag; else channel->flag &= ~flag; /* 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\n", client->nick, client->user, client->host, channel->name, set ? '+' : '-', Mode); } return 0;}/* * Destroy and svz_free() a given ban entry. */voidirc_destroy_ban (irc_ban_t *ban){ if (ban->nick) svz_free (ban->nick); if (ban->user) svz_free (ban->user); svz_free (ban->host); svz_free (ban->by); svz_free (ban);}/* * This function creates a ban entry. */static irc_ban_t *irc_create_ban (irc_client_t *client, char *request, int len){ irc_ban_t *ban; char *p, *tmp; int n, size = 0; /* reserve and initialize buffer space */ ban = svz_malloc (sizeof (irc_ban_t)); memset (ban, 0, sizeof (irc_ban_t)); tmp = svz_malloc (MAX_MSG_LEN); memset (tmp, 0, MAX_MSG_LEN); ban->since = time (NULL); sprintf (tmp, "%s!%s@%s", client->nick, client->user, client->host); ban->by = svz_strdup (tmp); p = request; n = 0; while (size < len && *p != '!' && *p != '@') { tmp[n++] = *p++; size++; } /* nick has been parsed */ if (*p == '!') { tmp[n] = '\0'; ban->nick = svz_strdup (tmp); p++; size++; n = 0; while (size < len && *p != '@') { tmp[n++] = *p++; size++; } /* user parsed */ if (*p == '@') { tmp[n] = '\0'; ban->user = svz_strdup (tmp); p++; size++; n = 0; while (size < len) { tmp[n++] = *p++; size++; } tmp[n] = '\0'; ban->host = svz_strdup (tmp); } } /* here user parsed without nick */ else if (*p == '@') { tmp[n] = '\0'; ban->user = svz_strdup (tmp); p++; size++; n = 0; while (size < len) { tmp[n++] = *p++; size++; } tmp[n] = '\0'; ban->host = svz_strdup (tmp); } /* parsed just a host without user and nick */ else { tmp[n] = '\0'; ban->host = svz_strdup (tmp); } svz_free (tmp); return ban;}/* * Set or unset a channel specific flag to a given argument. */static intirc_channel_arg (irc_client_t *client, /* client changing the flag */ svz_socket_t *sock, /* this clients connection */ int cflag, /* this clients flags */ irc_channel_t *channel, /* mode change for this channel */ int flag, /* flag to be set / unset */ char *arg, /* the arg */ char set) /* set / unset */{ irc_config_t *cfg = sock->cfg; irc_client_t *cl; svz_socket_t *xsock; int n; unsigned l; char *Modes = CHANNEL_MODES; char Mode = ' '; /* enough paras ? */ if (set && arg[0] == 0) { irc_printf (sock, ":%s %03d %s " ERR_NEEDMOREPARAMS_TEXT "\n", cfg->host, ERR_NEEDMOREPARAMS, client->nick, "MODE"); return 0; } /* 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; /* set / unset the actual flag */ if (set) { switch (flag) { case MODE_KEY: /* key is set before... */ if (channel->flag & flag) { irc_printf (sock, ":%s %03d %s " ERR_KEYSET_TEXT "\n", cfg->host, ERR_KEYSET, client->nick, channel->name); return 0; } if (channel->key) svz_free (channel->key); channel->key = svz_strdup (arg); channel->flag |= flag; break; case MODE_ULIMIT: channel->users = atoi (arg); channel->flag |= flag; break; case MODE_BAN: n = channel->bans; channel->ban = svz_realloc (channel->ban, sizeof (irc_ban_t *) * (n + 1)); channel->ban[n] = irc_create_ban (client, arg, strlen (arg)); channel->bans++; break; } } /* unset flag */ else { /* look if you can delete a ban */ if (flag & MODE_BAN) { for (n = 0; n < channel->bans; n++) { if (!strcmp (arg, irc_ban_string (channel->ban[n]))) { irc_destroy_ban (channel->ban[n]); if (--channel->bans != 0) { channel->ban[n] = channel->ban[channel->bans]; channel->ban = svz_realloc (channel->ban, sizeof (irc_ban_t *) * channel->bans); } else { svz_free (channel->ban); channel->ban = NULL; } break; } } } else { channel->flag &= ~flag; } } /* 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%s\n", client->nick, client->user, client->host, channel->name, set ? '+' : '-', Mode, set ? " " : "", set ? arg : ""); } return 0;}/* * Get a mode string by user modes. */char *irc_client_flag_string (irc_client_t *client){ static char Mode[MAX_MSG_LEN]; static char *Modes = USER_MODES; unsigned n, i; memset (Mode, 0, MAX_MSG_LEN); Mode[0] = '+'; for (i = n = 0; n < strlen (Modes); n++) { if (client->flag & (1 << n)) Mode[++i] = Modes[n]; } return Mode;}/* * Get a flag string by a channels modes. */char *irc_channel_flag_string (irc_channel_t *channel){ static char Mode[MAX_MODE_LEN]; static char arg[MAX_MODE_LEN]; static char *Modes = CHANNEL_MODES; unsigned n, i; memset (Mode, 0, MAX_MODE_LEN); Mode[0] = '+'; /* go through all possible Mode flags (characters) */ for (i = n = 0; n < strlen (Modes); n++) { if (channel->flag & (1 << n)) Mode[++i] = Modes[n]; } /* add flag para if necessary */ if (channel->flag & MODE_ULIMIT) { sprintf (arg, " %d", channel->users); strcat (Mode, arg); } return Mode;}/* * Command: MODE * Channel modes: * Parameters: <channel> {[+|-]|o|p|s|i|t|n|b|v} [<limit>] [<user>] * [<ban mask>] * User modes: * Parameters: <nickname> {[+|-]|i|w|s|o} * Numeric Replies: ERR_NEEDMOREPARAMS RPL_CHANNELMODEIS * ERR_CHANOPRIVSNEEDED ERR_NOSUCHNICK * ERR_NOTONCHANNEL ERR_KEYSET * RPL_BANLIST RPL_ENDOFBANLIST * ERR_UNKNOWNMODE ERR_NOSUCHCHANNEL * ERR_USERSDONTMATCH RPL_UMODEIS * ERR_UMODEUNKNOWNFLAG */#define FLAG_SET 1#define FLAG_UNSET 0intirc_mode_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; char *chan, *nick, *req; char flag; int cflag; int n, para; /* enough paras, but at least one ? */ if (irc_check_args (sock, client, cfg, request, 1)) return 0; chan = nick = request->para[0]; /* is target channel ? */ if ((channel = irc_find_channel (cfg, chan)) != NULL) { /* this is a request only ? */ if (request->paras < 2) { irc_printf (sock, ":%s %03d %s " RPL_CHANNELMODEIS_TEXT "\n", cfg->host, RPL_CHANNELMODEIS, client->nick, channel->name, irc_channel_flag_string (channel)); return 0; } /* find client in the channel first */ if ((n = irc_client_in_channel (sock, client, channel)) == -1) return 0; cflag = channel->cflag[n]; /* go through all the Mode string and current arg is # 2 */ req = request->para[1]; para = 2; flag = FLAG_SET; while (*req) { switch (*req) { case '+': flag = FLAG_SET; break; case '-': flag = FLAG_UNSET; break; /* set or get ban Mask */ case 'b': /* if no args, then reply the bans */ if (para >= request->paras) { for (n = 0; n < channel->bans; n++) { irc_printf (sock, ":%s %03d %s " RPL_BANLIST_TEXT "\n", cfg->host, RPL_BANLIST, client->nick, channel->name, irc_ban_string (channel->ban[n]), channel->ban[n]->by, channel->ban[n]->since); } irc_printf (sock, ":%s %03d %s " RPL_ENDOFBANLIST_TEXT "\n", cfg->host, RPL_ENDOFBANLIST, client->nick, channel->name); } /* yes there are args, so set or unset the ban */ else { irc_channel_arg (client, sock, cflag, channel, MODE_BAN, request->para[para], flag); para++; } break; /* channel operator flag */ case 'o': irc_client_flag (client, sock, cflag, request->para[para], channel, MODE_OPERATOR, flag); para++; break; /* voice flag for this channel */ case 'v': irc_client_flag (client, sock, cflag, request->para[para], channel, MODE_VOICE, flag); para++; break; /* private flag of this channel */ case 'p': irc_channel_flag (client, sock, cflag, channel, MODE_PRIVATE, flag); break; /* secret flag */ case 's': irc_channel_flag (client, sock, cflag, channel, MODE_SECRET, flag); break; /* invite only flag */ case 'i': irc_channel_flag (client, sock, cflag, channel, MODE_INVITE, flag); break; /* topic setable by operator only */ case 't': irc_channel_flag (client, sock, cflag, channel, MODE_TOPIC, flag); break; /* no Message of outside flag */ case 'n': irc_channel_flag (client, sock, cflag, channel, MODE_MESSAGE, flag); break; /* Moderated channel */ case 'm': irc_channel_flag (client, sock, cflag, channel, MODE_MODERATE, flag); break; /* set the users limitation flag (taking one arg) */ case 'l': irc_channel_arg (client, sock, cflag, channel, MODE_ULIMIT, request->para[para], flag); if (flag) para++; break; /* set a key for this channel */ case 'k': irc_channel_arg (client, sock, cflag, channel, MODE_KEY, request->para[para], flag); if (flag) para++; break; /* unknown Mode flag */ default: irc_printf (sock, ":%s %03d %s " ERR_UNKNOWNMODE_TEXT "\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -