X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fproto-p10.c;h=37eb33445040081cdd174fd3bed899005419d21a;hb=35ffb2ad774fac945c200d06a30174fe676d94bb;hp=ec95c4a776d59cfc8ad3713e764e980a9283c5e4;hpb=3347e61580d203fba631f8664de8d1f46294ae22;p=srvx.git diff --git a/src/proto-p10.c b/src/proto-p10.c index ec95c4a..37eb334 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -39,6 +39,7 @@ #define CMD_EOB "END_OF_BURST" #define CMD_EOB_ACK "EOB_ACK" #define CMD_ERROR "ERROR" +#define CMD_FAKEHOST "FAKE" #define CMD_GET "GET" #define CMD_GLINE "GLINE" #define CMD_HASH "HASH" @@ -120,6 +121,7 @@ #define TOK_EOB "EB" #define TOK_EOB_ACK "EA" #define TOK_ERROR "Y" +#define TOK_FAKEHOST "FA" #define TOK_GET "GET" #define TOK_GLINE "GL" #define TOK_HASH "HASH" @@ -212,6 +214,7 @@ #define P10_EOB TYPE(EOB) #define P10_EOB_ACK TYPE(EOB_ACK) #define P10_ERROR TYPE(ERROR) +#define P10_FAKEHOST TYPE(FAKEHOST) #define P10_GET TYPE(GET) #define P10_GLINE TYPE(GLINE) #define P10_HASH TYPE(HASH) @@ -286,9 +289,13 @@ static unsigned int num_privmsg_funcs; static privmsg_func_t *notice_funcs; static unsigned int num_notice_funcs; static struct dict *unbursted_channels; +static char *his_servername; +static char *his_servercomment; static struct userNode *AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *numeric, const char *userinfo, time_t timestamp, const char *realip); +extern int off_channel; + /* Numerics can be XYY, XYYY, or XXYYY; with X's identifying the * server and Y's indentifying the client on that server. */ struct server* @@ -414,6 +421,12 @@ irc_account(struct userNode *user, const char *stamp) putsock("%s " P10_ACCOUNT " %s %s", self->numeric, user->numeric, stamp); } +void +irc_fakehost(struct userNode *user, const char *host) +{ + putsock("%s " P10_FAKEHOST " %s %s", self->numeric, user->numeric, host); +} + void irc_regnick(UNUSED_ARG(struct userNode *user)) { @@ -560,8 +573,6 @@ irc_burst(struct chanNode *chan) long last_mode=-1; unsigned int n; - if (!chan->members.used) - return; base_len = sprintf(burst_line, "%s " P10_BURST " %s " FMT_TIME_T " ", self->numeric, chan->name, chan->timestamp); len = irc_make_chanmode(chan, burst_line+base_len); @@ -680,7 +691,7 @@ irc_kick(struct userNode *who, struct userNode *target, struct chanNode *channel { const char *numeric; struct modeNode *mn = GetUserMode(channel, who); - numeric = (mn && (mn->modes & MODE_CHANOP)) ? who->numeric : self->numeric; + numeric = ((mn && (mn->modes & MODE_CHANOP)) || off_channel) ? who->numeric : self->numeric; putsock("%s " P10_KICK " %s %s :%s", numeric, channel->name, target->numeric, msg); } @@ -750,6 +761,36 @@ change_nicklen(int new_nicklen) } } +static CMD_FUNC(cmd_whois) +{ + struct userNode *from; + struct userNode *who; + + if (argc < 3) + return 0; + if (!(from = GetUserH(origin))) { + log_module(MAIN_LOG, LOG_ERROR, "Could not find WHOIS origin user %s", origin); + return 0; + } + if(!(who = GetUserH(argv[2]))) { + irc_numeric(from, ERR_NOSUCHNICK, "%s@%s :No such nick", argv[2], self->name); + return 1; + } + if (IsHiddenHost(who) && !IsOper(from)) { + /* Just stay quiet. */ + return 1; + } + 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); + else + 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; +} + static CMD_FUNC(cmd_server) { struct server *srv; @@ -757,7 +798,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) @@ -972,6 +1013,18 @@ static CMD_FUNC(cmd_account) return 1; } +static CMD_FUNC(cmd_fakehost) +{ + struct userNode *user; + + if ((argc < 3) || !origin || !GetServerH(origin)) + return 0; + if (!(user = GetUserN(argv[1]))) + return 1; + assign_fakehost(user, argv[2], 0); + return 1; +} + static CMD_FUNC(cmd_burst) { extern int rel_age; @@ -1023,7 +1076,10 @@ static CMD_FUNC(cmd_burst) mode |= MODE_CHANOP; 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) @@ -1150,7 +1206,7 @@ static CMD_FUNC(cmd_topic) static CMD_FUNC(cmd_num_topic) { - static struct chanNode *cn; + struct chanNode *cn; if (!argv[0]) return 0; /* huh? */ @@ -1405,6 +1461,12 @@ init_parse(void) inttobase64(numer, (numnick << 12) + (usermask & 0x00fff), 3); else inttobase64(numer, (numnick << 18) + (usermask & 0x3ffff), 5); + + str = conf_get_data("server/his_servername", RECDB_QSTRING); + his_servername = str ? strdup(str) : NULL; + str = conf_get_data("server/his_servercomment", RECDB_QSTRING); + his_servercomment = str ? strdup(str) : NULL; + str = conf_get_data("server/hostname", RECDB_QSTRING); desc = conf_get_data("server/description", RECDB_QSTRING); if (!str || !desc) { @@ -1429,6 +1491,8 @@ init_parse(void) dict_insert(irc_func_dict, TOK_NICK, cmd_nick); dict_insert(irc_func_dict, CMD_ACCOUNT, cmd_account); dict_insert(irc_func_dict, TOK_ACCOUNT, cmd_account); + dict_insert(irc_func_dict, CMD_FAKEHOST, cmd_fakehost); + dict_insert(irc_func_dict, TOK_FAKEHOST, cmd_fakehost); dict_insert(irc_func_dict, CMD_PASS, cmd_pass); dict_insert(irc_func_dict, TOK_PASS, cmd_pass); dict_insert(irc_func_dict, CMD_PING, cmd_ping); @@ -1505,6 +1569,7 @@ init_parse(void) dict_insert(irc_func_dict, "331", cmd_num_topic); dict_insert(irc_func_dict, "332", cmd_num_topic); dict_insert(irc_func_dict, "333", cmd_num_topic); + dict_insert(irc_func_dict, "345", cmd_dummy); /* blah has been invited to blah */ dict_insert(irc_func_dict, "432", cmd_error_nick); /* Erroneus [sic] nickname */ /* ban list resetting */ /* "stats g" responses */ @@ -1737,7 +1802,7 @@ void DelServer(struct server* serv, int announce, const char *message) } struct userNode * -AddService(const char *nick, const char *desc) +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(); @@ -1753,8 +1818,10 @@ AddService(const char *nick, const char *desc) log_module(MAIN_LOG, LOG_ERROR, "Unable to allocate numnick for service %s", nick); return 0; } + if (!hostname) + hostname = self->name; make_numeric(self, local_num, numeric); - return AddUser(self, nick, nick, self->name, "+oik", numeric, desc, now, "AAAAAA"); + return AddUser(self, nick, nick, hostname, modes ? modes : "+oik", numeric, desc, now, "AAAAAA"); } struct userNode * @@ -1923,8 +1990,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++) { @@ -1966,6 +2033,18 @@ void mod_usermode(struct userNode *user, const char *mode_change) { call_account_func(user, tag); } break; + case 'f': + if (*word) { + char host[MAXLEN]; + unsigned int ii; + for (ii=0; (*word != ' ') && (*word != '\0'); ) + host[ii++] = *word++; + host[ii] = 0; + while (*word == ' ') + word++; + assign_fakehost(user, host, 0); + } + break; } #undef do_user_mode } @@ -2038,7 +2117,7 @@ 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 'o': case 'v': { @@ -2056,7 +2135,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; } @@ -2124,7 +2203,9 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod chbuf.channel = channel; chbuf.actor = who; chbuf.chname_len = strlen(channel->name); - if ((mn = GetUserMode(channel, who)) && (mn->modes & MODE_CHANOP)) + + mn = GetUserMode(channel, who); + if ((mn && (mn->modes & MODE_CHANOP)) || off_channel) chbuf.is_chanop = 1; /* First remove modes */ @@ -2155,13 +2236,13 @@ 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; 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_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; } } @@ -2197,13 +2278,13 @@ 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; 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_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; } } @@ -2295,7 +2376,7 @@ clear_chanmode(struct chanNode *channel, const char *modes) case 'b': remove |= MODE_BAN; break; case 'D': remove |= MODE_DELAYJOINS; break; case 'r': remove |= MODE_REGONLY; break; - case 'c': remove |= MODE_NOCOLORS; + case 'c': remove |= MODE_NOCOLORS; break; case 'C': remove |= MODE_NOCTCPS; break; } } @@ -2341,6 +2422,24 @@ reg_privmsg_func(struct userNode *user, privmsg_func_t handler) privmsg_funcs[numeric] = handler; } +void +unreg_privmsg_func(struct userNode *user, privmsg_func_t handler) +{ + unsigned int x; + + if (!user || handler) + return; /* this really only works with users */ + + memset(privmsg_funcs+user->num_local, 0, sizeof(privmsg_func_t)); + + for (x = user->num_local+1; x < num_privmsg_funcs; x++) + memmove(privmsg_funcs+x-1, privmsg_funcs+x, sizeof(privmsg_func_t)); + + privmsg_funcs = realloc(privmsg_funcs, num_privmsg_funcs*sizeof(privmsg_func_t)); + num_privmsg_funcs--; +} + + void reg_notice_func(struct userNode *user, privmsg_func_t handler) { @@ -2356,6 +2455,24 @@ reg_notice_func(struct userNode *user, privmsg_func_t handler) notice_funcs[numeric] = handler; } +void +unreg_notice_func(struct userNode *user, privmsg_func_t handler) +{ + unsigned int x; + + if (!user || handler) + return; /* this really only works with users */ + + memset(notice_funcs+user->num_local, 0, sizeof(privmsg_func_t)); + + for (x = user->num_local+1; x < num_notice_funcs; x++) + memmove(notice_funcs+x-1, notice_funcs+x, sizeof(privmsg_func_t)); + + memset(notice_funcs+user->num_local, 0, sizeof(privmsg_func_t)); + notice_funcs = realloc(notice_funcs, num_notice_funcs*sizeof(privmsg_func_t)); + num_notice_funcs--; +} + void reg_oper_func(oper_func_t handler) {