X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/dd0194524f965768ce542eda2af0587d95131267..0e859bd9eaa372c09645cbf04193d784d1b629d7:/src/proto-p10.c diff --git a/src/proto-p10.c b/src/proto-p10.c index 05c92a0..d9944d7 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -5,7 +5,7 @@ * * x3 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 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -29,6 +29,7 @@ /* Full commands. */ #define CMD_ACCOUNT "ACCOUNT" #define CMD_ADMIN "ADMIN" +#define CMD_ALIST "ALIST" #define CMD_ASLL "ASLL" #define CMD_AWAY "AWAY" #define CMD_BURST "BURST" @@ -88,14 +89,19 @@ #define CMD_SERVSET "SERVSET" #define CMD_SET "SET" #define CMD_SETTIME "SETTIME" +#define CMD_SGLINE "SGLINE" #define CMD_SHUN "SHUN" #define CMD_SILENCE "SILENCE" +#define CMD_SMO "SMO" +#define CMD_SNO "SNO" +#define CMD_SSHUN "SSHUN" #define CMD_SQUERY "SQUERY" #define CMD_SQUIT "SQUIT" #define CMD_STATS "STATS" #define CMD_SVSJOIN "SVSJOIN" #define CMD_SVSNICK "SVSNICK" #define CMD_SVSPART "SVSPART" +#define CMD_SVSQUIT "SVSQUIT" #define CMD_SWHOIS "SWHOIS" #define CMD_TIME "TIME" #define CMD_TOPIC "TOPIC" @@ -118,6 +124,7 @@ /* Tokenized commands. */ #define TOK_ACCOUNT "AC" #define TOK_ADMIN "AD" +#define TOK_ALIST "AL" #define TOK_ASLL "LL" #define TOK_AWAY "A" #define TOK_BURST "B" @@ -178,14 +185,19 @@ #define TOK_SERVSET "SERVSET" #define TOK_SET "SET" #define TOK_SETTIME "SE" +#define TOK_SGLINE "SGL" #define TOK_SHUN "SU" #define TOK_SILENCE "U" +#define TOK_SMO "SMO" +#define TOK_SNO "SNO" +#define TOK_SSHUN "SSU" #define TOK_SQUERY "SQUERY" #define TOK_SQUIT "SQ" #define TOK_STATS "R" #define TOK_SVSJOIN "SJ" #define TOK_SVSNICK "SN" #define TOK_SVSPART "SP" +#define TOK_SVSQUIT "SX" #define TOK_SWHOIS "SW" #define TOK_TIME "TI" #define TOK_TOPIC "T" @@ -278,14 +290,19 @@ #define P10_SERVSET TYPE(SERVSET) #define P10_SET TYPE(SET) #define P10_SETTIME TYPE(SETTIME) +#define P10_SGLINE TYPE(SGLINE) #define P10_SHUN TYPE(SHUN) #define P10_SILENCE TYPE(SILENCE) +#define P10_SMO TYPE(SMO) +#define P10_SNO TYPE(SNO) +#define P10_SSHUN TYPE(SSHUN) #define P10_SQUERY TYPE(SQUERY) #define P10_SQUIT TYPE(SQUIT) #define P10_STATS TYPE(STATS) #define P10_SVSJOIN TYPE(SVSJOIN) #define P10_SVSNICK TYPE(SVSNICK) #define P10_SVSPART TYPE(SVSPART) +#define P10_SVSQUIT TYPE(SVSQUIT) #define P10_SWHOIS TYPE(SWHOIS) #define P10_TIME TYPE(TIME) #define P10_TOPIC TYPE(TOPIC) @@ -380,6 +397,32 @@ GetUserN(const char *numeric) /* using numeric */ return un; } +extern struct userNode *opserv; +static void +check_ctcp(struct userNode *user, struct userNode *bot, char *text, UNUSED_ARG(int server_qualified)) +{ + char *cmd; + /* if its a version reply, do an alert check (only alerts with version=something) */ + if(bot == opserv) { + if(text[0] == '\001') { + text++; + cmd = mysep(&text, " "); + if(!irccasecmp(cmd, "VERSION")) { + char *version = mysep(&text, "\n"); + if(!version) + version = ""; + /* opserv_debug("Opserv got CTCP VERSION Notice from %s: %s", user->nick, version); */ + /* TODO: setup a ctcp_funcs thing to handle this and other CTCPS properly */ + user->version_reply = strdup(version); + /* TODO: put this in the db */ + if(match_ircglob(version, "WebTV;*")) + user->no_notice = true; /* webbies cant see notices */ + } + } + } +} + + static void privmsg_user_helper(struct userNode *un, void *data) { @@ -391,6 +434,7 @@ privmsg_user_helper(struct userNode *un, void *data) } } else { if ((num < num_notice_funcs) && notice_funcs[num]) { + check_ctcp(pd->user, un, pd->text, pd->is_qualified); notice_funcs[num](pd->user, un, pd->text, pd->is_qualified); } } @@ -448,7 +492,7 @@ irc_server(struct server *srv) } } -static void +void irc_p10_pton(irc_in_addr_t *ip, const char *input) { if (strlen(input) == 6) { @@ -475,7 +519,7 @@ irc_p10_pton(irc_in_addr_t *ip, const char *input) } } -static void +void irc_p10_ntop(char *output, const irc_in_addr_t *ip) { if (!irc_in_addr_is_valid(*ip)) { @@ -557,6 +601,15 @@ irc_user(struct userNode *user) modes[modelen++] = 'f'; if (IsHiddenHost(user)) modes[modelen++] = 'x'; + if (IsBotM(user)) + modes[modelen++] = 'B'; + if (IsHideChans(user)) + modes[modelen++] = 'n'; + if (IsHideIdle(user)) + modes[modelen++] = 'I'; + if (IsXtraOp(user)) + modes[modelen++] = 'X'; + modes[modelen] = 0; /* we don't need to put the + in modes because it's in the format string. */ @@ -662,6 +715,7 @@ irc_wallops(const char *format, ...) putsock("%s " P10_WALLOPS " :%s", self->numeric, buffer); } + void irc_notice(struct userNode *from, const char *to, const char *message) { @@ -680,6 +734,18 @@ irc_privmsg(struct userNode *from, const char *to, const char *message) putsock("%s " P10_PRIVMSG " %s :%s", from->numeric, to, message); } +void +irc_privmsg_user(struct userNode *from, struct userNode *to, const char *message) +{ + putsock("%s " P10_PRIVMSG " %s :%s", from->numeric, to->numeric, message); +} + +void +irc_version_user(struct userNode *from, struct userNode *to) +{ + irc_privmsg_user(from, to, "\001VERSION\001"); +} + void irc_eob(void) { @@ -704,6 +770,12 @@ irc_eob_ack(void) } } +void +irc_rpong(const char *from1, const char *from2, const char *pingtime, const char *clientinfo) +{ + putsock("%s " P10_RPONG " %s %s %s :%s", self->numeric, from1, from2, pingtime, clientinfo); +} + void irc_ping(const char *payload) { @@ -752,8 +824,8 @@ irc_introduce(const char *passwd) void irc_gline(struct server *srv, struct gline *gline, int silent) { - putsock("%s " P10_GLINE " %s +%s %ld :%s<%s> %s", - self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, silent ? "AUTO " : "", gline->issuer, gline->reason); + putsock("%s " P10_GLINE " %s +%s %ld %ld :%s<%s> %s", + self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, now, silent ? "AUTO " : "", gline->issuer, gline->reason); } void @@ -813,6 +885,7 @@ irc_burst(struct chanNode *chan) pos = base_len; last_mode = -1; } + memcpy(burst_line+pos, mn->user->numeric, strlen(mn->user->numeric)); pos += strlen(mn->user->numeric); if (mn->modes && (mn->modes != last_mode)) { @@ -962,6 +1035,18 @@ irc_svsjoin(struct userNode *from, struct userNode *who, struct chanNode *to) putsock("%s " P10_SVSJOIN " %s %s "FMT_TIME_T, from->uplink->numeric, who->numeric, to->name, now); } +void +irc_svspart(struct userNode *from, struct userNode *who, struct chanNode *to) +{ + putsock("%s " P10_SVSPART " %s %s", from->uplink->numeric, who->numeric, to->name); +} + +void +irc_svsquit(struct userNode *from, struct userNode *who, char *reason) +{ + putsock("%s " P10_SVSQUIT " %s :%s", from->uplink->numeric, who->numeric, reason); +} + void irc_kick(struct userNode *who, struct userNode *target, struct chanNode *channel, const char *msg) { @@ -1065,6 +1150,48 @@ irc_numeric(struct userNode *user, unsigned int num, const char *format, ...) putsock(":%s %03d %s %s", self->name, num, user->nick, buffer); } +void +irc_mark(struct userNode *user, char *mark) +{ + char *host = user->hostname; + + /* TODO: Allow mark overwrite. If they are marked, and their fakehost is oldmark.hostname, update it to newmark.hostname so mark can be called multiple times. Probably requires ircd modification also */ + if(user->mark) + return; + + /* if the mark will put us over the host length, clip some off the left hand side + * to make room... + */ + if(strlen(host) + 1 + strlen(mark) > HOSTLEN) + host += 1 + ( (strlen(host) + 1 + strlen(mark)) - HOSTLEN ); + putsock("%s " CMD_MARK " %s DNSBL +m %s.%s", self->numeric, user->nick, mark, host); + putsock("%s " CMD_MARK " %s DNSBL_DATA %s", self->numeric, user->nick, mark); + + /* Save it in the user */ + user->mark = strdup(mark); + + /* If they are not otherwise marked, mark their host with fakehost */ + if(!IsFakeHost(user) && !IsSetHost(user) && !(IsHiddenHost(user) && user->handle_info) ) + { + struct modeNode *mn = NULL; + char fakehost[HOSTLEN]; + unsigned int count = 0; + unsigned int n = 0; + + putsock("%s " CMD_FAKEHOST " %s %s.%s", self->numeric, user->numeric, mark, host); + putsock("%s " CMD_MODE " %s +x", self->numeric, user->nick); + + snprintf(fakehost, sizeof(fakehost), "%s.%s", mark, host); + safestrncpy(user->fakehost, fakehost, sizeof(user->fakehost)); + + for (n=count=0; nchannels.used; n++) { + mn = user->channels.list[n]; + if (strlen(mn->channel->name) >= 1) /* Sanity */ + check_bans(user, mn->channel->name); + } + } +} + static void send_burst(void); static void @@ -1188,7 +1315,8 @@ static CMD_FUNC(cmd_eob) /* now that we know who our uplink is, * we can center the routing map and activate auto-routing. */ - activate_routing(NULL, NULL, NULL); + //activate_routing(NULL, NULL, NULL); + routing_init(); } sender->self_burst = 0; recalc_bursts(sender); @@ -1214,6 +1342,19 @@ static CMD_FUNC(cmd_eob_ack) return 1; } +static CMD_FUNC(cmd_rping) +{ + struct server *dest; + + if (!(dest = GetServerN(argv[1]))) + return 1; /* if its a jupe or something, return 1 so its silently ignored */ + + if (dest == self) + irc_rpong(argv[2], argv[3], argv[4], argv[5]); + + return 1; +} + static CMD_FUNC(cmd_ping) { struct server *srv; @@ -1371,7 +1512,22 @@ static CMD_FUNC(cmd_account) if(!strcmp(argv[2],"C")) { - if((hi = loc_auth(argv[4], argv[5]))) + if((hi = loc_auth(argv[4], argv[5], NULL))) + { + /* Return a AC A */ + putsock("%s " P10_ACCOUNT " %s A %s %lu", self->numeric, server->numeric , argv[3], hi->registered); + + } + else + { + /* Return a AC D */ + putsock("%s " P10_ACCOUNT " %s D %s", self->numeric, server->numeric , argv[3]); + } + return 1; + } + else if(!strcmp(argv[2],"H")) /* New enhanced (host) version of C */ + { + if((hi = loc_auth(argv[5], argv[6], argv[4] ))) { /* Return a AC A */ putsock("%s " P10_ACCOUNT " %s A %s %lu", self->numeric, server->numeric , argv[3], hi->registered); @@ -1416,7 +1572,9 @@ static struct { P(BADCHAN), P(LOCAL_BADCHAN), P(SEE_CHAN), P(PROPAGATE), P(DISPLAY), P(SEE_OPERS), P(WIDE_GLINE), P(FORCE_OPMODE), P(FORCE_LOCAL_OPMODE), P(REMOTEREHASH), P(CHECK), P(SEE_SECRET_CHAN), - P(SHUN), P(LOCAL_SHUN), P(WIDE_SHUN), + P(SHUN), P(LOCAL_SHUN), P(WIDE_SHUN), P(ZLINE), + P(LOCAL_ZLINE), P(WIDE_ZLINE), P(LIST_CHAN), P(WHOIS_NOTICE), + P(HIDE_IDLE), P(XTRAOP), P(HIDE_CHANNELS), #undef P { 0, 0 } }; @@ -1522,6 +1680,7 @@ static CMD_FUNC(cmd_burst) static char exemptlist[MAXLEN], banlist[MAXLEN]; unsigned int next = 3, res = 1; int ctype = 0, echeck = 0, bcheck = 0; + struct chanData *cData; struct chanNode *cNode; struct userNode *un; struct modeNode *mNode; @@ -1605,6 +1764,15 @@ static CMD_FUNC(cmd_burst) irc_burst(cNode); } cNode = AddChannel(argv[1], in_timestamp, modes, banlist, exemptlist); + cData = cNode->channel_info; + + if (!cData) { + if (cNode->modes & MODE_REGISTERED) { + irc_join(opserv, cNode); + irc_mode(opserv, cNode, "-z"); + irc_part(opserv, cNode, ""); + } + } /* Burst channel members in now. */ for (user = members, sep = *members, mode = 0; sep; user = end) { @@ -1648,6 +1816,57 @@ static CMD_FUNC(cmd_burst) return res; } +/* TODO: + * This is a stub that doesn't actually do anything. It should be completed + * so that bans on *!*@markname.* match users as it does in nefarious + */ +static CMD_FUNC(cmd_mark) +{ + struct userNode *target; + /* + * log_module(MAIN_LOG, LOG_ERROR, "DEBUG: mark, user %s, type %s, arg %s", argv[1], argv[2], argv[3]); + */ + + if(argc < 4) + return 0; + if(!strcasecmp(argv[2], "DNSBL")) { + /* DNSBL */ + return 1; + } + else if(!strcasecmp(argv[2], "DNSBL_DATA")) { + /* DNSBL_DATA name */ + target = GetUserH(argv[1]); + if(!target) { + log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose dnsbl mark is changing.", argv[1]); + return 0; + } + target->mark = strdup(argv[3]); + return 1; + + } + else if(!strcasecmp(argv[2], "CVERSION")) { + /* DNSBL_DATA name */ + target = GetUserH(argv[1]); + if(!target) { + log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose version mark is changing.", argv[1]); + return 0; + } + + char *version = unsplit_string(argv + 3, argc - 3, NULL); + if(!version) + version = ""; + + target->version_reply = strdup(version); + + if(match_ircglob(version, "WebTV;*")) + target->no_notice = true; /* webbies cant see notices */ + + return 1; + } + /* unknown type of mark */ + return 1; +} + static CMD_FUNC(cmd_mode) { struct chanNode *cn; @@ -1833,17 +2052,29 @@ static CMD_FUNC(cmd_num_topic) static CMD_FUNC(cmd_num_gline) { - if (argc < 6) - return 0; - gline_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0, 0); + if (argc < 7) { + if (argc < 6) + return 0; + else + gline_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0, 0); + } else { + if (argv[5] == "+") + gline_add(origin, argv[3], atoi(argv[4])-now, argv[6], now, 0, 0); + } return 1; } static CMD_FUNC(cmd_num_shun) { - if (argc < 6) - return 0; - shun_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0); + if (argc < 7) { + if (argc < 6) + return 0; + else + shun_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0); + } else { + if (argv[5] == "+") + shun_add(origin, argv[3], atoi(argv[4])-now, argv[6], now, 0); + } return 1; } @@ -1904,7 +2135,7 @@ static CMD_FUNC(cmd_svspart) if (argc < 3) return 0; - user = GetUserH(argv[1]); + user = GetUserN(argv[1]); if (!user) return 0; parse_foreach(argv[2], part_helper, NULL, NULL, NULL, user); @@ -2013,6 +2244,7 @@ static CMD_FUNC(cmd_privmsg) pd.is_notice = 0; pd.text = argv[2]; parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd); + return 1; } @@ -2092,6 +2324,34 @@ static CMD_FUNC(cmd_gline) return 0; } +static CMD_FUNC(cmd_sgline) +{ + struct server *sender; + + if (argc < 4) + return 0; + + if (!(sender = GetServerH(origin))) + return 0; + + gline_add(origin, argv[1], strtoul(argv[2], NULL, 0), argv[argc-1], now, 1, 0); + return 1; +} + +static CMD_FUNC(cmd_sshun) +{ + struct server *sender; + + if (argc < 4) + return 0; + + if (!(sender = GetServerH(origin))) + return 0; + + shun_add(origin, argv[1], strtoul(argv[2], NULL, 0), argv[argc-1], now, 1); + return 1; +} + static CMD_FUNC(cmd_shun) { if (argc < 3) @@ -2211,6 +2471,8 @@ init_parse(void) dict_insert(irc_func_dict, TOK_EOB_ACK, cmd_eob_ack); dict_insert(irc_func_dict, CMD_MODE, cmd_mode); dict_insert(irc_func_dict, TOK_MODE, cmd_mode); + dict_insert(irc_func_dict, CMD_MARK, cmd_mark); + dict_insert(irc_func_dict, TOK_MARK, cmd_mark); dict_insert(irc_func_dict, CMD_NICK, cmd_nick); dict_insert(irc_func_dict, TOK_NICK, cmd_nick); dict_insert(irc_func_dict, CMD_ACCOUNT, cmd_account); @@ -2263,8 +2525,12 @@ init_parse(void) dict_insert(irc_func_dict, TOK_WHOIS, cmd_whois); dict_insert(irc_func_dict, CMD_GLINE, cmd_gline); dict_insert(irc_func_dict, TOK_GLINE, cmd_gline); + dict_insert(irc_func_dict, CMD_SGLINE, cmd_sgline); + dict_insert(irc_func_dict, TOK_SGLINE, cmd_sgline); dict_insert(irc_func_dict, CMD_SHUN, cmd_shun); dict_insert(irc_func_dict, TOK_SHUN, cmd_shun); + dict_insert(irc_func_dict, CMD_SSHUN, cmd_sshun); + dict_insert(irc_func_dict, TOK_SSHUN, cmd_sshun); dict_insert(irc_func_dict, CMD_OPMODE, cmd_opmode); dict_insert(irc_func_dict, TOK_OPMODE, cmd_opmode); dict_insert(irc_func_dict, CMD_CLEARMODE, cmd_clearmode); @@ -2273,6 +2539,15 @@ init_parse(void) dict_insert(irc_func_dict, TOK_VERSION, cmd_version); dict_insert(irc_func_dict, CMD_ADMIN, cmd_admin); dict_insert(irc_func_dict, TOK_ADMIN, cmd_admin); + dict_insert(irc_func_dict, CMD_SMO, cmd_dummy); + dict_insert(irc_func_dict, TOK_SMO, cmd_dummy); + dict_insert(irc_func_dict, CMD_SNO, cmd_dummy); + dict_insert(irc_func_dict, TOK_SNO, cmd_dummy); + + dict_insert(irc_func_dict, CMD_RPING, cmd_rping); + dict_insert(irc_func_dict, TOK_RPING, cmd_rping); + dict_insert(irc_func_dict, CMD_RPONG, cmd_dummy); + dict_insert(irc_func_dict, TOK_RPONG, cmd_dummy); /* In P10, DESTRUCT doesn't do anything except be broadcast to servers. * Apparently to obliterate channels from any servers that think they @@ -2301,9 +2576,11 @@ init_parse(void) dict_insert(irc_func_dict, TOK_WALLUSERS, cmd_dummy); /* Ignore dnsbl exemptions */ dict_insert(irc_func_dict, TOK_EXEMPT, cmd_dummy); - dict_insert(irc_func_dict, TOK_MARK, cmd_dummy); dict_insert(irc_func_dict, CMD_PRIVS, cmd_privs); dict_insert(irc_func_dict, TOK_PRIVS, cmd_privs); + /* ignore ALIST for now */ + dict_insert(irc_func_dict, TOK_ALIST, cmd_dummy); + dict_insert(irc_func_dict, CMD_ALIST, cmd_dummy); /* Ignore remote luser */ dict_insert(irc_func_dict, TOK_LUSERS, cmd_dummy); /* We have reliable clock! Always! Wraaa! */ @@ -2313,6 +2590,7 @@ init_parse(void) /* ignore /trace and /motd commands targetted at us */ dict_insert(irc_func_dict, TOK_TRACE, cmd_dummy); dict_insert(irc_func_dict, TOK_MOTD, cmd_dummy); + dict_insert(irc_func_dict, TOK_UPING, cmd_dummy); /* handle topics */ dict_insert(irc_func_dict, "331", cmd_num_topic); @@ -2347,6 +2625,7 @@ init_parse(void) userList_init(&dead_users); reg_del_channel_func(remove_unbursted_channel); reg_exit_func(parse_cleanup); + // reg_notice_func(opserv, check_ctcp); } int @@ -2620,6 +2899,8 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char * { struct userNode *oldUser, *uNode; unsigned int n, ignore_user; + char *tstr; + int type; if ((strlen(numeric) < 3) || (strlen(numeric) > 5)) { log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): numeric %s wrong length!", uplink, nick, numeric); @@ -2668,11 +2949,15 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char * safestrncpy(uNode->numeric, numeric, sizeof(uNode->numeric)); irc_p10_pton(&uNode->ip, realip); - if (irc_in_addr_is_ipv4(uNode->ip)) { - make_virtip((char*)irc_ntoa(&uNode->ip), (char*)irc_ntoa(&uNode->ip), uNode->cryptip); - make_virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost); - } else if (irc_in_addr_is_ipv6(uNode->ip)) { - make_ipv6virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost); + tstr = conf_get_data("server/type", RECDB_QSTRING); + type = atoi(tstr); + if (type > 6) { + if (irc_in_addr_is_ipv4(uNode->ip)) { + make_virtip((char*)irc_ntoa(&uNode->ip), (char*)irc_ntoa(&uNode->ip), uNode->cryptip); + make_virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost); + } else if (irc_in_addr_is_ipv6(uNode->ip)) { + make_ipv6virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost); + } } if (!uNode->crypthost && uNode->cryptip) @@ -2752,6 +3037,25 @@ DelUser(struct userNode* user, struct userNode *killer, int announce, const char } modeList_clean(&user->channels); + + /* Clean up version data */ + if(user->version_reply) { + free(user->version_reply); + user->version_reply = NULL; + } + + /* clean up mark */ + if(user->mark) { + free(user->mark); + user->mark = NULL; + } + + /* clean up geoip data if any */ + if(user->country_code) free(user->country_code); + if(user->city) free(user->city); + if(user->region) free(user->region); + if(user->postal_code) free(user->postal_code); + /* We don't free them, in case we try to privmsg them or something * (like when a stupid oper kills themself). We just put them onto * a list of clients that get freed after processing each line. @@ -2804,6 +3108,34 @@ void mod_usermode(struct userNode *user, const char *mode_change) { case 'd': do_user_mode(FLAGS_DEAF); break; case 'k': do_user_mode(FLAGS_SERVICE); break; case 'g': do_user_mode(FLAGS_GLOBAL); break; + case 'B': do_user_mode(FLAGS_BOT); break; + case 'n': do_user_mode(FLAGS_HIDECHANS); break; + case 'I': do_user_mode(FLAGS_HIDEIDLE); break; + case 'X': do_user_mode(FLAGS_XTRAOP); break; + case 'C': do_user_mode(FLAGS_CLOAKHOST); + if (*word) { + char cloakhost[MAXLEN]; + unsigned int ii; + for (ii=0; (*word != ' ') && (*word != '\0'); ) + cloakhost[ii++] = *word++; + cloakhost[ii] = 0; + while (*word == ' ') + word++; + safestrncpy(user->crypthost, cloakhost, sizeof(user->crypthost)); + } + break; + case 'c': do_user_mode(FLAGS_CLOAKIP); + if (*word) { + char cloakip[MAXLEN]; + unsigned int ii; + for (ii=0; (*word != ' ') && (*word != '\0'); ) + cloakip[ii++] = *word++; + cloakip[ii] = 0; + while (*word == ' ') + word++; + safestrncpy(user->cryptip, cloakip, sizeof(user->cryptip)); + } + break; // sethost - reed/apples // case 'h': do_user_mode(FLAGS_HELPER); break; // I check if there's an 'h' in the first part, and if there,