X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/55342ce8a8e0e89892433948d7bb660682d13804..0b565f3d116f2ac987e69ef517b16776835afbcf:/src/proto-p10.c diff --git a/src/proto-p10.c b/src/proto-p10.c index 7e2246d..40b03a6 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -579,6 +579,7 @@ irc_burst(struct chanNode *chan) int pos, base_len, len; struct modeNode *mn; struct banNode *bn; + struct exemptNode *en; long last_mode=-1; unsigned int n; @@ -639,6 +640,33 @@ irc_burst(struct chanNode *chan) burst_line[pos++] = ' '; } } + if (chan->exemptlist.used) { + /* dump the exempt */ + if (pos+2+strlen(chan->exemptlist.list[0]->exempt) > 505) { + burst_line[pos-1] = 0; + putsock("%s", burst_line); + pos = base_len; + } else { + burst_line[pos++] = ' '; + } + + burst_line[pos++] = ' '; + burst_line[pos++] = '~'; + burst_line[pos++] = ' '; + base_len = pos; + for (n=0; nexemptlist.used; n++) { + en = chan->exemptlist.list[n]; + len = strlen(en->exempt); + if (pos+len+1 > 510) { + burst_line[pos-1] = 0; /* -1 to back up over the space or comma */ + putsock("%s", burst_line); + pos = base_len; + } + memcpy(burst_line+pos, en->exempt, len); + pos += len; + burst_line[pos++] = ' '; + } + } /* print the last line */ burst_line[pos] = 0; putsock("%s", burst_line); @@ -793,13 +821,11 @@ static CMD_FUNC(cmd_whois) } irc_numeric(from, RPL_WHOISUSER, "%s %s %s * :%s", who->nick, who->ident, who->hostname, who->info); if (his_servername && his_servercomment) - irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, his_servername, his_servercomment); + irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, his_servername, his_servercomment); else - irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, who->uplink->name, who->uplink->description); - - if (IsOper(who)) { + irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, who->uplink->name, who->uplink->description); + if (IsOper(who)) irc_numeric(from, RPL_WHOISOPERATOR, "%s :is a megalomaniacal power hungry tyrant", who->nick); - } irc_numeric(from, RPL_ENDOFWHOIS, "%s :End of /WHOIS list", who->nick); return 1; } @@ -811,7 +837,7 @@ static CMD_FUNC(cmd_server) if (argc < 8) return 0; - if (origin) { + if (self->uplink) { /* another server introduced us */ srv = AddServer(GetServerH(origin), argv[1], atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), argv[6], argv[argc-1]); if (!srv) @@ -944,7 +970,7 @@ create_helper(char *name, void *data) return; } - AddChannelUser(cd->user, AddChannel(name, cd->when, NULL, NULL)); + AddChannelUser(cd->user, AddChannel(name, cd->when, NULL, NULL, NULL)); } static CMD_FUNC(cmd_create) @@ -1041,44 +1067,89 @@ static CMD_FUNC(cmd_fakehost) static CMD_FUNC(cmd_burst) { extern int rel_age; - char modes[MAXLEN], *members = "", *banlist = NULL; + char modes[MAXLEN], *members = ""; + static char exemptlist[MAXLEN], banlist[MAXLEN]; unsigned int next = 3, res = 1; + int ctype = 0, echeck = 0, bcheck = 0; struct chanNode *cNode; struct userNode *un; struct modeNode *mNode; long mode; char *user, *end, sep; time_t in_timestamp; + char* parm = NULL; if (argc < 3) return 0; modes[0] = 0; + + exemptlist[0] = 0; + banlist[0] = 0; + while (next < argc) { switch (argv[next][0]) { case '+': { const char *pos; int n_modes; - for (pos=argv[next], n_modes = 1; *pos; pos++) { + for (pos=argv[next], n_modes = 1; *pos; pos++) if ((*pos == 'k') || (*pos == 'l')) n_modes++; - } unsplit_string(argv+next, n_modes, modes); next += n_modes; break; } - case '%': banlist = argv[next++]+1; break; - default: members = argv[next++]; break; + case '%': { + for(parm = mysep(&argv[next], " "); /* parm = first param */ + parm; /* While param is not null */ + parm = mysep(&argv[next], " ") /* parm = next param */ + ) + { + switch (parm[0]) { + case '%': { + ctype = 1; + break; + } + case '~': { + ctype = 2; + break; + } + default: { + break; + } + } + if (ctype == 1) { + if (bcheck == 0) { + /* strip % char off start of very first ban */ + strncat(banlist, strtok(parm, "%"), sizeof(banlist) - 1 - strlen(banlist)); + strncat(banlist, " ", sizeof(banlist) - 1 - strlen(banlist)); + bcheck = 1; + } else { + strncat(banlist, parm, sizeof(banlist) - 1 - strlen(banlist)); + strncat(banlist, " ", sizeof(banlist) - 1 - strlen(banlist)); + } + } else if (ctype == 2) { + if (echeck == 0) { + echeck = 1; + } else { + strncat(exemptlist, parm, sizeof(exemptlist) - 1 - strlen(exemptlist)); + strncat(exemptlist, " ", sizeof(exemptlist) - 1 - strlen(exemptlist)); + } + } + } + next++; + break; } + default: members = argv[next++]; break; + } } - in_timestamp = atoi(argv[2]); if ((cNode = dict_find(unbursted_channels, argv[1], NULL))) { cNode->timestamp = in_timestamp; dict_remove(unbursted_channels, cNode->name); irc_burst(cNode); } - cNode = AddChannel(argv[1], in_timestamp, modes, banlist); + cNode = AddChannel(argv[1], in_timestamp, modes, banlist, exemptlist); /* Burst channel members in now. */ for (user = members, sep = *members, mode = 0; sep; user = end) { @@ -1093,7 +1164,10 @@ static CMD_FUNC(cmd_burst) mode |= MODE_HALFOP; else if (sep == 'v') mode |= MODE_VOICE; - else + else if (isdigit(sep)) { + mode |= MODE_CHANOP; + while (isdigit(*end)) end++; + } else break; } if (rel_age < 0) @@ -1834,7 +1908,7 @@ void DelServer(struct server* serv, int announce, const char *message) } struct userNode * -AddService(const char *nick, const char *desc, const char *hostname) +AddService(const char *nick, const char *modes, const char *desc, const char *hostname) { char numeric[COMBO_NUMERIC_LEN+1]; int local_num = get_local_numeric(); @@ -1853,7 +1927,7 @@ AddService(const char *nick, const char *desc, const char *hostname) if (!hostname) hostname = self->name; make_numeric(self, local_num, numeric); - return AddUser(self, nick, nick, hostname, "+oik", numeric, desc, now, "AAAAAA"); + return AddUser(self, nick, nick, hostname, modes ? modes : "+oik", numeric, desc, now, "AAAAAA"); } struct userNode * @@ -2022,8 +2096,8 @@ void mod_usermode(struct userNode *user, const char *mode_change) { if (!user || !mode_change) return; - while (*word != ' ' && *word) word++;\ - while (*word == ' ') word++; \ + while (*word != ' ' && *word) word++; + while (*word == ' ') word++; while (1) { #define do_user_mode(FLAG) do { if (add) user->modes |= FLAG; else user->modes &= ~FLAG; } while (0) switch (*mode_change++) { @@ -2172,7 +2246,17 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un change->args[ch_arg].mode = MODE_BAN; if (!add) change->args[ch_arg].mode |= MODE_REMOVE; - change->args[ch_arg++].hostmask = modes[in_arg++]; + change->args[ch_arg++].u.hostmask = modes[in_arg++]; + break; + case 'e': + if (!(flags & MCP_ALLOW_OVB)) + goto error; + if (in_arg >= argc) + goto error; + change->args[ch_arg].mode = MODE_EXEMPT; + if (!add) + change->args[ch_arg].mode |= MODE_REMOVE; + change->args[ch_arg++].u.hostmask = modes[in_arg++]; break; case 'o': case 'h': case 'v': { @@ -2197,7 +2281,7 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un victim = GetUserH(modes[in_arg++]); if (!victim) continue; - if ((change->args[ch_arg].member = GetUserMode(channel, victim))) + if ((change->args[ch_arg].u.member = GetUserMode(channel, victim))) ch_arg++; break; } @@ -2306,15 +2390,18 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod chbuf.modes[chbuf.modes_used++] = mode = '-'; switch (change->args[arg].mode & ~MODE_REMOVE) { case MODE_BAN: - mod_chanmode_append(&chbuf, 'b', change->args[arg].hostmask); + mod_chanmode_append(&chbuf, 'b', change->args[arg].u.hostmask); + break; + case MODE_EXEMPT: + mod_chanmode_append(&chbuf, 'e', change->args[arg].u.hostmask); break; default: if (change->args[arg].mode & MODE_CHANOP) - mod_chanmode_append(&chbuf, 'o', change->args[arg].member->user->numeric); + mod_chanmode_append(&chbuf, 'o', change->args[arg].u.member->user->numeric); if (change->args[arg].mode & MODE_HALFOP) - mod_chanmode_append(&chbuf, 'h', change->args[arg].member->user->numeric); + mod_chanmode_append(&chbuf, 'h', change->args[arg].u.member->user->numeric); if (change->args[arg].mode & MODE_VOICE) - mod_chanmode_append(&chbuf, 'v', change->args[arg].member->user->numeric); + mod_chanmode_append(&chbuf, 'v', change->args[arg].u.member->user->numeric); break; } } @@ -2358,15 +2445,18 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod chbuf.modes[chbuf.modes_used++] = mode = '+'; switch (change->args[arg].mode) { case MODE_BAN: - mod_chanmode_append(&chbuf, 'b', change->args[arg].hostmask); + mod_chanmode_append(&chbuf, 'b', change->args[arg].u.hostmask); + break; + case MODE_EXEMPT: + mod_chanmode_append(&chbuf, 'e', change->args[arg].u.hostmask); break; default: if (change->args[arg].mode & MODE_CHANOP) - mod_chanmode_append(&chbuf, 'o', change->args[arg].member->user->numeric); + mod_chanmode_append(&chbuf, 'o', change->args[arg].u.member->user->numeric); if (change->args[arg].mode & MODE_HALFOP) - mod_chanmode_append(&chbuf, 'h', change->args[arg].member->user->numeric); + mod_chanmode_append(&chbuf, 'h', change->args[arg].u.member->user->numeric); if (change->args[arg].mode & MODE_VOICE) - mod_chanmode_append(&chbuf, 'v', change->args[arg].member->user->numeric); + mod_chanmode_append(&chbuf, 'v', change->args[arg].u.member->user->numeric); break; } } @@ -2473,6 +2563,7 @@ clear_chanmode(struct chanNode *channel, const char *modes) channel->limit = 0; break; case 'b': remove |= MODE_BAN; break; + case 'e': remove |= MODE_EXEMPT; break; case 'D': remove |= MODE_DELAYJOINS; break; case 'r': remove |= MODE_REGONLY; break; case 'c': remove |= MODE_NOCOLORS; @@ -2500,6 +2591,14 @@ clear_chanmode(struct chanNode *channel, const char *modes) channel->banlist.used = 0; } + /* If removing exempts, kill 'em all. */ + if ((remove & MODE_EXEMPT) && channel->exemptlist.used) { + unsigned int i; + for (i=0; iexemptlist.used; i++) + free(channel->exemptlist.list[i]); + channel->exemptlist.used = 0; + } + /* Remove member modes. */ if ((remove & (MODE_CHANOP | MODE_HALFOP | MODE_VOICE)) && channel->members.used) { int mask = ~(remove & (MODE_CHANOP | MODE_HALFOP | MODE_VOICE));