From e28a0a023fe077fbec2343f8eb494371138fcd44 Mon Sep 17 00:00:00 2001 From: Geo Date: Thu, 9 May 2024 15:12:14 -0400 Subject: [PATCH 1/2] Add IRCv3 standard-replies --- src/mod/server.mod/servmsg.c | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/mod/server.mod/servmsg.c b/src/mod/server.mod/servmsg.c index 85baed7cf..952ff70bf 100644 --- a/src/mod/server.mod/servmsg.c +++ b/src/mod/server.mod/servmsg.c @@ -2001,6 +2001,54 @@ static int got730or1(char *from, char *msg, int code) return 0; } +/* Got IRCv3 standard-reply + * [...] + */ +static int gotstdreply(char *from, char *msgtype, char *msg) +{ + char *cmd, *code, *text; + char context[MSGMAX] = ""; + int len; + + cmd = newsplit(&msg); + code = newsplit(&msg); +/* TODO: Once this feature is better implemented, consider how to handle + * one-word descriptions that aren't technically required to have a : + */ + text = strstr(msg, " :"); + if (text) { + text++; + if (text != msg) { + len = text - msg; + snprintf(context, sizeof context, "%.*s", len, msg); + } + fixcolon(text); + } + putlog(LOG_SERV, "*", "%s: %s: Received a %s message from %s: %s", cmd, code, msgtype, from, text); + return 0; +} + +/* Got IRCv3 FAIL standard-reply */ +static int gotstdfail(char *from, char *msg) +{ + gotstdreply(from, "FAIL", msg); + return 0; +} + +/* Got IRCv3 NOTE standard-reply */ +static int gotstdnote(char *from, char *msg) +{ + gotstdreply(from, "NOTE", msg); + return 0; +} + +/* Got IRCv3 WARN standard-reply */ +static int gotstdwarn(char *from, char *msg) +{ + gotstdreply(from, "WARN", msg); + return 0; +} + /* Got 730/RPL_MONONLINE * : 730 :target[!user@host][,target[!user@host]]* */ @@ -2097,6 +2145,9 @@ static cmd_t my_raw_binds[] = { {"PING", "", (IntFunc) gotping, NULL}, {"PONG", "", (IntFunc) gotpong, NULL}, {"WALLOPS", "", (IntFunc) gotwall, NULL}, + {"FAIL", "", (IntFunc) gotstdfail, NULL}, + {"NOTE", "", (IntFunc) gotstdnote, NULL}, + {"WARN", "", (IntFunc) gotstdwarn, NULL}, {"001", "", (IntFunc) got001, NULL}, {"005", "", (IntFunc) got005, NULL}, {"303", "", (IntFunc) got303, NULL}, From 39a582cda2e587d2aa6f95028d078ab4f739ecbe Mon Sep 17 00:00:00 2001 From: Geo Date: Sat, 25 May 2024 11:46:05 -0400 Subject: [PATCH 2/2] Full account tacking (#1585) Patch by: Geo, thommey Closes: #1369 --- doc/sphinx_source/using/tcl-commands.rst | 2 +- src/chan.h | 3 +- src/chanprog.c | 45 +------ src/mod/channels.mod/userchan.c | 7 +- src/mod/irc.mod/chan.c | 151 ++++++++++++----------- src/mod/irc.mod/cmdsirc.c | 68 ++++------ src/mod/irc.mod/irc.c | 40 +++--- src/mod/irc.mod/mode.c | 31 ++--- src/mod/irc.mod/msgcmds.c | 7 +- src/mod/irc.mod/tclirc.c | 48 +++---- src/mod/module.h | 3 +- src/mod/notes.mod/notes.c | 4 +- src/mod/seen.mod/seen.c | 10 +- src/modules.c | 4 +- src/userrec.c | 61 ++++----- src/users.h | 1 + src/version.h | 4 +- 17 files changed, 200 insertions(+), 289 deletions(-) diff --git a/doc/sphinx_source/using/tcl-commands.rst b/doc/sphinx_source/using/tcl-commands.rst index 7953dccbd..6a662052c 100644 --- a/doc/sphinx_source/using/tcl-commands.rst +++ b/doc/sphinx_source/using/tcl-commands.rst @@ -1136,7 +1136,7 @@ nick2hand [channel] Module: irc ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -account2nicks [channel] +account2nicks [channel] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Returns: a de-duplicated Tcl list of the nickname(s) on the specified channel (if one is specified) whose nickname matches the given account; "" is returned if no match is found. This command will only work if a server supports (and Eggdrop has enabled) the account-notify and extended-join capabilities, and the server understands WHOX requests (also known as raw 354 responses). If no channel is specified, all channels are checked. diff --git a/src/chan.h b/src/chan.h index 19a56e5a1..d5f11257d 100644 --- a/src/chan.h +++ b/src/chan.h @@ -50,8 +50,7 @@ typedef struct memstruct { time_t split; /* in case they were just netsplit */ time_t last; /* for measuring idle time */ time_t delay; /* for delayed autoop */ - struct userrec *user; - int tried_getuser; + int tried_getuser; // TODO: use it to invalidate user cache struct memstruct *next; } memberlist; diff --git a/src/chanprog.c b/src/chanprog.c index e8205f17b..37e03d61a 100644 --- a/src/chanprog.c +++ b/src/chanprog.c @@ -116,30 +116,6 @@ struct chanset_t *findchan_by_dname(const char *name) return NULL; } - -/* - * "caching" functions - */ - -/* Shortcut for get_user_by_host -- might have user record in one - * of the channel caches. - */ -struct userrec *check_chanlist(const char *host) -{ - char *nick, *uhost, buf[UHOSTLEN]; - memberlist *m; - struct chanset_t *chan; - - strlcpy(buf, host, sizeof buf); - uhost = buf; - nick = splitnick(&uhost); - for (chan = chanset; chan; chan = chan->next) - for (m = chan->channel.member; m && m->nick[0]; m = m->next) - if (!rfc_casecmp(nick, m->nick) && !strcasecmp(uhost, m->userhost)) - return m->user; - return NULL; -} - /* Clear the user pointers in the chanlists. * * Necessary when a hostmask is added/removed, a user is added or a new @@ -152,13 +128,12 @@ void clear_chanlist(void) for (chan = chanset; chan; chan = chan->next) for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - m->user = NULL; m->tried_getuser = 0; } } /* Clear the user pointer of a specific nick in the chanlists. - * + * Necessary when a hostmask is added/removed, a nick changes, etc. * Does not completely invalidate the channel cache like clear_chanlist(). */ @@ -170,29 +145,11 @@ void clear_chanlist_member(const char *nick) for (chan = chanset; chan; chan = chan->next) for (m = chan->channel.member; m && m->nick[0]; m = m->next) if (!rfc_casecmp(m->nick, nick)) { - m->user = NULL; m->tried_getuser = 0; break; } } -/* If this user@host is in a channel, set it (it was null) - */ -void set_chanlist(const char *host, struct userrec *rec) -{ - char *nick, *uhost, buf[UHOSTLEN]; - memberlist *m; - struct chanset_t *chan; - - strlcpy(buf, host, sizeof buf); - uhost = buf; - nick = splitnick(&uhost); - for (chan = chanset; chan; chan = chan->next) - for (m = chan->channel.member; m && m->nick[0]; m = m->next) - if (!rfc_casecmp(nick, m->nick) && !strcasecmp(uhost, m->userhost)) - m->user = rec; -} - /* Calculate the memory we should be using */ int expmem_chanprog() diff --git a/src/mod/channels.mod/userchan.c b/src/mod/channels.mod/userchan.c index 12d5c3202..2bac2ac3a 100644 --- a/src/mod/channels.mod/userchan.c +++ b/src/mod/channels.mod/userchan.c @@ -1270,12 +1270,7 @@ static int expired_mask(struct chanset_t *chan, char *who) * present in the channel and has op. */ - if (m->user) - u = m->user; - else { - simple_sprintf(buf, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(buf); - } + u = get_user_from_member(m); /* Do not expire masks set by bots. */ if (u && u->flags & USER_BOT) return 0; diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index 0a80927e9..1d0082547 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -110,7 +110,7 @@ static void setaccount(char *nick, char *account) } else { putlog(LOG_MODES, chan->dname, "%s!%s logged in to their account %s", nick, m->userhost, account); } - check_tcl_account(m->nick, m->userhost, m->user, chan->dname, account); + check_tcl_account(m->nick, m->userhost, get_user_from_member(m), chan->dname, account); } strlcpy(m->account, account, sizeof m->account); } @@ -207,9 +207,11 @@ static void do_mask(struct chanset_t *chan, masklist *m, char *mask, char mode) /* This is a clone of detect_flood, but works for channel specificity now * and handles kick & deop as well. + * + * victim for flood-deop, account for flood-join */ static int detect_chan_flood(char *floodnick, char *floodhost, char *from, - struct chanset_t *chan, int which, char *victim) + struct chanset_t *chan, int which, char *victim_or_account) { char h[NICKMAX+UHOSTLEN+1], ftype[12], *p; struct userrec *u; @@ -236,7 +238,16 @@ static int detect_chan_flood(char *floodnick, char *floodhost, char *from, if (!m && (which != FLOOD_JOIN)) return 0; - get_user_flagrec(get_user_by_host(from), &fr, chan->dname); + if (m) { + u = get_user_from_member(m); + } else { + u = victim_or_account ? get_user_by_account(victim_or_account) : NULL; + if (!u) { + u = get_user_by_host(from); + } + } + + get_user_flagrec(u, &fr, chan->dname); if (glob_bot(fr) || ((which == FLOOD_DEOP) && (glob_master(fr) || chan_master(fr)) && (glob_friend(fr) || chan_friend(fr))) || ((which == FLOOD_KICK) && (glob_master(fr) || chan_master(fr)) && @@ -307,10 +318,10 @@ static int detect_chan_flood(char *floodnick, char *floodhost, char *from, } /* Deop'n the same person, sillyness ;) - so just ignore it */ if (which == FLOOD_DEOP) { - if (!rfc_casecmp(chan->deopd, victim)) + if (!rfc_casecmp(chan->deopd, victim_or_account)) return 0; else - strlcpy(chan->deopd, victim, sizeof chan->deopd); + strlcpy(chan->deopd, victim_or_account, sizeof chan->deopd); } chan->floodnum[which]++; if (chan->floodnum[which] >= thr) { /* FLOOD */ @@ -320,7 +331,7 @@ static int detect_chan_flood(char *floodnick, char *floodhost, char *from, chan->floodwho[which][0] = 0; if (which == FLOOD_DEOP) chan->deopd[0] = 0; - u = get_user_by_host(from); + u = get_user_from_member(m); if (check_tcl_flud(floodnick, floodhost, u, ftype, chan->dname)) return 0; switch (which) { @@ -425,8 +436,7 @@ static void kick_all(struct chanset_t *chan, char *hostmask, char *comment, flushed = 0; kicknick[0] = 0; for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - sprintf(s, "%s!%s", m->nick, m->userhost); - get_user_flagrec(m->user ? m->user : get_user_by_host(s), &fr, chan->dname); + get_user_flagrec(get_user_from_member(m), &fr, chan->dname); if ((me_op(chan) || (me_halfop(chan) && !chan_hasop(m))) && match_addr(hostmask, s) && !chan_sentkick(m) && !match_my_nick(m->nick) && !chan_issplit(m) && @@ -474,10 +484,7 @@ static void refresh_ban_kick(struct chanset_t *chan, char *user, char *nick) if (match_addr(b->mask, user)) { struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; char c[512]; /* The ban comment. */ - char s[NICKMAX+UHOSTLEN+1]; - - sprintf(s, "%s!%s", m->nick, m->userhost); - get_user_flagrec(m->user ? m->user : get_user_by_host(s), &fr, + get_user_flagrec(get_user_from_member(m), &fr, chan->dname); if (!glob_friend(fr) && !chan_friend(fr)) { add_mode(chan, '-', 'o', nick); /* Guess it can't hurt. */ @@ -869,7 +876,7 @@ static void check_this_member(struct chanset_t *chan, char *nick, (me_op(chan) || (me_halfop(chan) && !chan_hasop(m)))) { check_exemptlist(chan, s); quickban(chan, m->userhost); - p = get_user(&USERENTRY_COMMENT, m->user); + p = get_user(&USERENTRY_COMMENT, get_user_from_member(m)); dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick, p ? p : IRC_POLITEKICK); m->flags |= SENTKICK; @@ -888,8 +895,7 @@ static void check_this_user(char *hand, int delete, char *host) for (chan = chanset; chan; chan = chan->next) for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - sprintf(s, "%s!%s", m->nick, m->userhost); - u = m->user ? m->user : get_user_by_host(s); + u = get_user_from_member(m); if ((u && !strcasecmp(u->handle, hand) && delete < 2) || (!u && delete == 2 && match_addr(host, s))) { u = delete ? NULL : u; @@ -904,8 +910,8 @@ static void check_this_user(char *hand, int delete, char *host) static void recheck_channel(struct chanset_t *chan, int dobans) { memberlist *m; - char s[NICKMAX+UHOSTLEN+1]; struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; + struct userrec *u; static int stacking = 0; int stop_reset = 0; @@ -915,12 +921,8 @@ static void recheck_channel(struct chanset_t *chan, int dobans) stacking++; /* Okay, sort through who needs to be deopped. */ for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - sprintf(s, "%s!%s", m->nick, m->userhost); - if (!m->user && !m->tried_getuser) { - m->tried_getuser = 1; - m->user = get_user_by_host(s); - } - get_user_flagrec(m->user, &fr, chan->dname); + u = get_user_from_member(m); + get_user_flagrec(u, &fr, chan->dname); if (glob_bot(fr) && chan_hasop(m) && !match_my_nick(m->nick)) stop_reset = 1; /* Perhaps we were halfop and tried to halfop/kick the user earlier but @@ -1084,7 +1086,6 @@ static int got352or4(struct chanset_t *chan, char *user, char *host, simple_sprintf(m->userhost, "%s@%s", user, host); simple_sprintf(userhost, "%s!%s", nick, m->userhost); /* Combine n!u@h */ - m->user = NULL; /* No handle match (yet) */ if (match_my_nick(nick)) /* Is it me? */ strcpy(botuserhost, m->userhost); /* Yes, save my own userhost */ m->flags |= WHO_SYNCED; @@ -1115,7 +1116,6 @@ static int got352or4(struct chanset_t *chan, char *user, char *host, if (chan->need_op[0]) do_tcl("need-op", chan->need_op); } - m->user = get_user_by_host(userhost); /* Update accountname in channel records, 0 means logged out */ /* A 0 is not a change from "" */ @@ -1214,7 +1214,7 @@ static int got354(char *from, char *msg) } return 0; } - + /* React to IRCv3 CHGHOST command. CHGHOST changes the hostname and/or * ident of the user. Format: * :geo!awesome@eggdrop.com CHGHOST tehgeo foo.io @@ -1234,17 +1234,16 @@ static int gotchghost(char *from, char *msg){ if (match_my_nick(nick)) { snprintf(botuserhost, UHOSTMAX, "%s@%s", ident, msg); } - u = get_user_by_host(from); /* Run the bind for each channel the user is on */ for (chan = chanset; chan; chan = chan->next) { chname = chan->dname; m = ismember(chan, nick); if (m) { + u = get_user_from_member(m); snprintf(m->userhost, sizeof m->userhost, "%s@%s", ident, msg); snprintf(mask, sizeof mask, "%s %s!%s@%s", chname, nick, ident, msg); check_tcl_chghost(nick, from, mask, u, chname, ident, msg); - get_user_flagrec(m->user ? m->user : get_user_by_host(s1), &fr, - chan->dname); + get_user_flagrec(u, &fr, chan->dname); check_this_member(chan, m->nick, &fr); } } @@ -1309,7 +1308,7 @@ static int got353(char *from, char *msg) } return 0; } - + /* React to 396 numeric (HOSTHIDDEN), sent when user mode +x (hostmasking) was * successfully set. Format: * :barjavel.freenode.net 396 BeerBot unaffiliated/geo/bot/beerbot :is now your hidden host (set by services.) @@ -1400,12 +1399,12 @@ static int gotaway(char *from, char *msg) strlcpy(s1, from, sizeof buf); nick = splitnick(&s1); - u = get_user_by_host(from); /* Run the bind for each channel the user is on */ for (chan = chanset; chan; chan = chan->next) { chname = chan->dname; m = ismember(chan, nick); if (m) { + u = get_user_from_member(m); snprintf(mask, sizeof mask, "%s %s", chname, from); check_tcl_ircaway(nick, from, mask, u, chname, msg); if (strlen(msg)) { @@ -1831,7 +1830,6 @@ static int gottopic(char *from, char *msg) chname = newsplit(&msg); fixcolon(msg); - u = get_user_by_host(from); nick = splitnick(&from); chan = findchan(chname); if (chan) { @@ -1841,6 +1839,7 @@ static int gottopic(char *from, char *msg) if (m != NULL) m->last = now; set_topic(chan, msg); + u = get_user_from_member(m); check_tcl_topc(nick, from, u, chan->dname, msg); } return 0; @@ -1942,28 +1941,27 @@ static void set_delay(struct chanset_t *chan, char *nick) */ static int gotjoin(char *from, char *channame) { - char *nick, *p, buf[UHOSTLEN], *uhost = buf, *chname; + char *nick, *p, buf[UHOSTLEN], *uhost = buf, *chname, *account = NULL; char *ch_dname = NULL; - int extjoin = 0; struct chanset_t *chan; memberlist *m; masklist *b; - struct capability *current; + int extjoin = 0; + struct capability *captmp; struct userrec *u; struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; - /* Check if extended-join CAP is enabled */ - current = cap; - while (current != NULL) { - if (!strcasecmp("extended-join", current->name)) { - extjoin = current->enabled ? 1 : 0; - } - current = current->next; - } + captmp = find_capability("extended-join"); + extjoin = captmp && captmp->enabled; + strlcpy(uhost, from, sizeof buf); nick = splitnick(&uhost); chname = newsplit(&channame); - if (!extjoin) { + if (extjoin) { + // :nick!user@host JOIN #chan account :realname + account = newsplit(&channame); + } else { + // :nick!user@host JOIN :#chan fixcolon(chname); } chan = findchan_by_dname(chname); @@ -2014,7 +2012,8 @@ static int gotjoin(char *from, char *channame) } } else if (!channel_pending(chan)) { chan->status &= ~CHAN_STOP_CYCLE; - detect_chan_flood(nick, uhost, from, chan, FLOOD_JOIN, NULL); + + detect_chan_flood(nick, uhost, from, chan, FLOOD_JOIN, extjoin ? account : NULL); chan = findchan(chname); if (!chan) { @@ -2027,9 +2026,6 @@ static int gotjoin(char *from, char *channame) /* The channel doesn't exist anymore, so get out of here. */ goto exit; - /* Grab last time joined before we update it */ - u = get_user_by_host(from); - get_user_flagrec(u, &fr, chan->dname); /* Lam: fix to work with !channels */ if (!channel_active(chan) && !match_my_nick(nick)) { /* uh, what?! i'm on the channel?! */ putlog(LOG_MISC, chan->dname, @@ -2041,6 +2037,8 @@ static int gotjoin(char *from, char *channame) } else { m = ismember(chan, nick); if (m && m->split && !strcasecmp(m->userhost, uhost)) { + u = get_user_from_member(m); + get_user_flagrec(u, &fr, chan->dname); check_tcl_rejn(nick, uhost, u, chan->dname); chan = findchan(chname); @@ -2055,12 +2053,11 @@ static int gotjoin(char *from, char *channame) goto exit; /* The tcl binding might have deleted the current user. Recheck. */ - u = get_user_by_host(from); + u = get_user_from_member(m); m->split = 0; m->last = now; m->delay = 0L; m->flags = (chan_hasop(m) ? WASOP : 0) | (chan_hashalfop(m) ? WASHALFOP : 0); - m->user = u; set_handle_laston(chan->dname, u, now); m->flags |= STOPWHO; putlog(LOG_JOIN, chan->dname, "%s (%s) returned to %s.", nick, uhost, @@ -2076,19 +2073,19 @@ static int gotjoin(char *from, char *channame) m->delay = 0L; strlcpy(m->nick, nick, sizeof m->nick); strlcpy(m->userhost, uhost, sizeof m->userhost); - m->user = u; m->flags |= STOPWHO; + u = get_user_from_member(m); + if (extjoin) { /* calls check_tcl_account which can delete the channel */ - setaccount(nick, newsplit(&channame)); - + setaccount(nick, account); + if (!(chan = findchan(chname)) && !(chan = findchan_by_dname(ch_dname ? ch_dname : chname))) { /* The channel doesn't exist anymore, so get out of here. */ goto exit; } } - check_tcl_join(nick, uhost, u, chan->dname); if (!(chan = findchan(chname)) && !(chan = findchan_by_dname(ch_dname ? ch_dname : chname))) { @@ -2098,7 +2095,6 @@ static int gotjoin(char *from, char *channame) /* The record saved in the channel record always gets updated, * so we can use that. */ - u = m->user; if (match_my_nick(nick)) { /* It was me joining! Need to update the channel record with the @@ -2129,9 +2125,9 @@ static int gotjoin(char *from, char *channame) if (u) { struct laston_info *li = 0; - cr = get_chanrec(m->user, chan->dname); + cr = get_chanrec(get_user_from_member(m), chan->dname); if (!cr && no_chanrec_info) - li = get_user(&USERENTRY_LASTON, m->user); + li = get_user(&USERENTRY_LASTON, get_user_from_member(m)); if (channel_greet(chan) && use_info && ((cr && now - cr->laston > wait_info) || (no_chanrec_info && (!li || now - li->laston > wait_info)))) { @@ -2189,7 +2185,7 @@ static int gotjoin(char *from, char *channame) (me_op(chan) || (me_halfop(chan) && !chan_hasop(m)))) { check_exemptlist(chan, from); quickban(chan, from); - p = get_user(&USERENTRY_COMMENT, m->user); + p = get_user(&USERENTRY_COMMENT, get_user_from_member(m)); dprintf(DP_MODE, "KICK %s %s :%s\n", chname, nick, (p && (p[0] != '@')) ? p : IRC_COMMENTKICK); m->flags |= SENTKICK; @@ -2249,6 +2245,7 @@ static int gotpart(char *from, char *msg) char *nick, *chname, *key; struct chanset_t *chan; struct userrec *u; + memberlist *m; chname = newsplit(&msg); fixcolon(chname); @@ -2260,8 +2257,9 @@ static int gotpart(char *from, char *msg) return 0; } if (chan && !channel_pending(chan)) { - u = get_user_by_host(from); nick = splitnick(&from); + m = ismember(chan, nick); + u = get_user_from_member(m); if (!channel_active(chan)) { /* whoa! */ putlog(LOG_MISC, chan->dname, @@ -2341,7 +2339,6 @@ static int gotkick(char *from, char *origmsg) } if (channel_active(chan)) { fixcolon(msg); - u = get_user_by_host(from); strlcpy(buf, from, sizeof buf); uhost = buf; whodid = splitnick(&uhost); @@ -2352,6 +2349,7 @@ static int gotkick(char *from, char *origmsg) return 0; m = ismember(chan, whodid); + u = get_user_from_member(m); if (m) m->last = now; /* This _needs_ to use chan->dname */ @@ -2368,7 +2366,7 @@ static int gotkick(char *from, char *origmsg) struct userrec *u2; simple_sprintf(s1, "%s!%s", m->nick, m->userhost); - u2 = get_user_by_host(s1); + u2 = get_user_from_member(m); set_handle_laston(chan->dname, u2, now); maybe_revenge(chan, from, s1, REVENGE_KICK); } @@ -2451,12 +2449,11 @@ static int gotnick(char *from, char *msg) m->flags &= ~(SENTKICK | SENTDEOP | SENTOP | SENTDEHALFOP | SENTHALFOP | SENTVOICE | SENTDEVOICE); /* nick-ban or nick is +k or something? */ - get_user_flagrec(m->user ? m->user : get_user_by_host(s1), &fr, - chan->dname); + u = get_user_from_member(m); + get_user_flagrec(u, &fr, chan->dname); check_this_member(chan, m->nick, &fr); /* Make sure this is in the loop, someone could have changed the record * in an earlier iteration of the loop. */ - u = get_user_by_host(from); found = 1; check_tcl_nick(nick, uhost, u, chan->dname, msg); @@ -2467,10 +2464,9 @@ static int gotnick(char *from, char *msg) } } if (!found) { - u = get_user_by_host(from); s1[0] = '*'; s1[1] = 0; - check_tcl_nick(nick, uhost, u, s1, msg); + check_tcl_nick(nick, uhost, NULL, s1, msg); } return 0; } @@ -2514,7 +2510,7 @@ static int gotquit(char *from, char *msg) chname = chan->dname; m = ismember(chan, nick); if (m) { - u = get_user_by_host(from2); + u = get_user_from_member(m); if (u) /* If you remove this, the bot will crash when the user record in * question is removed/modified during the tcl binds below, and the @@ -2569,6 +2565,7 @@ static int gotmsg(char *from, char *msg) int ctcp_count = 0, ignoring; struct chanset_t *chan; struct userrec *u; + memberlist *m; /* Only handle if message is to a channel, or to @#channel. */ /* FIXME: Properly handle ovNotices (@+#channel), vNotices (+#channel), etc. */ @@ -2612,7 +2609,15 @@ static int gotmsg(char *from, char *msg) ctcp_count++; if (ctcp[0] != ' ') { code = newsplit(&ctcp); - u = get_user_by_host(from); + u = NULL; + for (chan = chanset; chan; chan = chan->next) { + for (m = chan->channel.member; m && m->nick[0]; m = m->next) { + if (!rfc_casecmp(m->nick, nick)) { + u = get_user_from_member(m); + break; + } + } + } if (!ignoring || trigger_on_ignore) { if (!check_tcl_ctcp(nick, uhost, u, to, code, ctcp)) { chan = findchan(realto); @@ -2691,6 +2696,7 @@ static int gotnotice(char *from, char *msg) char *ctcp, *code; struct userrec *u; struct chanset_t *chan; + memberlist *m; int ignoring; if (!strchr(CHANMETA "@", *msg)) @@ -2704,8 +2710,15 @@ static int gotnotice(char *from, char *msg) fixcolon(msg); strlcpy(uhost, from, sizeof buf); nick = splitnick(&uhost); - u = get_user_by_host(from); - + u = NULL; + for (chan = chanset; chan; chan = chan->next) { + for (m = chan->channel.member; m && m->nick[0]; m = m->next) { + if (!rfc_casecmp(m->nick, nick)) { + u = get_user_from_member(m); + break; + } + } + } /* Check for CTCP: */ p = strchr(msg, 1); while (p && *p) { diff --git a/src/mod/irc.mod/cmdsirc.c b/src/mod/irc.mod/cmdsirc.c index 1caefe53e..3b387c8f6 100644 --- a/src/mod/irc.mod/cmdsirc.c +++ b/src/mod/irc.mod/cmdsirc.c @@ -68,13 +68,11 @@ static int has_oporhalfop(int idx, struct chanset_t *chan) */ static char *getnick(char *handle, struct chanset_t *chan) { - char s[UHOSTLEN]; struct userrec *u; memberlist *m; for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - if ((u = get_user_by_host(s)) && !strcasecmp(u->handle, handle)) + if ((u = get_user_from_member(m)) && !strcasecmp(u->handle, handle)) return m->nick; } return NULL; @@ -163,8 +161,8 @@ static void cmd_kickban(struct userrec *u, int idx, char *par) struct chanset_t *chan; char *chname, *nick, *s1; memberlist *m; - char s[UHOSTLEN]; char bantype = 0; + char s[UHOSTLEN]; if (!par[0]) { dprintf(idx, "Usage: kickban [channel] [-|@] [reason]\n"); @@ -208,7 +206,7 @@ static void cmd_kickban(struct userrec *u, int idx, char *par) return; } egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s); + u = get_user_from_member(m); get_user_flagrec(u, &victim, chan->dname); if ((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) && !(chan_master(user) || glob_master(user))) { @@ -265,7 +263,6 @@ static void cmd_op(struct userrec *u, int idx, char *par) struct chanset_t *chan; char *nick; memberlist *m; - char s[UHOSTLEN]; nick = newsplit(&par); chan = get_channel(idx, par); @@ -294,8 +291,7 @@ static void cmd_op(struct userrec *u, int idx, char *par) dprintf(idx, "%s is not on %s.\n", nick, chan->dname); return; } - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s); + u = get_user_from_member(m); get_user_flagrec(u, &victim, chan->dname); if (chan_deop(victim) || (glob_deop(victim) && !glob_op(victim))) { dprintf(idx, "%s is currently being auto-deopped.\n", m->nick); @@ -315,7 +311,6 @@ static void cmd_deop(struct userrec *u, int idx, char *par) struct chanset_t *chan; char *nick; memberlist *m; - char s[UHOSTLEN]; nick = newsplit(&par); chan = get_channel(idx, par); @@ -348,8 +343,7 @@ static void cmd_deop(struct userrec *u, int idx, char *par) dprintf(idx, "I'm not going to deop myself.\n"); return; } - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s); + u = get_user_from_member(m); get_user_flagrec(u, &victim, chan->dname); if ((chan_master(victim) || glob_master(victim)) && !(chan_owner(user) || glob_owner(user))) { @@ -371,7 +365,6 @@ static void cmd_halfop(struct userrec *u, int idx, char *par) struct userrec *u2; char *nick; memberlist *m; - char s[UHOSTLEN]; nick = newsplit(&par); chan = get_channel(idx, par); @@ -386,8 +379,7 @@ static void cmd_halfop(struct userrec *u, int idx, char *par) get_user_flagrec(dcc[idx].user, &user, chan->dname); m = ismember(chan, nick); if (m && !chan_op(user) && (!glob_op(user) || chan_deop(user))) { - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u2 = m->user ? m->user : get_user_by_host(s); + u2 = get_user_from_member(m); if (!u2 || strcasecmp(u2->handle, dcc[idx].nick) || (!chan_halfop(user) && (!glob_halfop(user) || chan_dehalfop(user)))) { @@ -414,8 +406,7 @@ static void cmd_halfop(struct userrec *u, int idx, char *par) dprintf(idx, "%s is not on %s.\n", nick, chan->dname); return; } - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s); + u = get_user_from_member(m); get_user_flagrec(u, &victim, chan->dname); if (chan_dehalfop(victim) || (glob_dehalfop(victim) && !glob_halfop(victim))) { dprintf(idx, "%s is currently being auto-dehalfopped.\n", m->nick); @@ -437,7 +428,6 @@ static void cmd_dehalfop(struct userrec *u, int idx, char *par) struct userrec *u2; char *nick; memberlist *m; - char s[UHOSTLEN]; nick = newsplit(&par); chan = get_channel(idx, par); @@ -452,9 +442,7 @@ static void cmd_dehalfop(struct userrec *u, int idx, char *par) get_user_flagrec(dcc[idx].user, &user, chan->dname); m = ismember(chan, nick); if (m && !chan_op(user) && (!glob_op(user) || chan_deop(user))) { - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u2 = m->user ? m->user : get_user_by_host(s); - + u2 = get_user_from_member(m); if (!u2 || strcasecmp(u2->handle, dcc[idx].nick) || (!chan_halfop(user) && (!glob_halfop(user) || chan_dehalfop(user)))) { dprintf(idx, "You are not a channel op on %s.\n", chan->dname); @@ -484,8 +472,7 @@ static void cmd_dehalfop(struct userrec *u, int idx, char *par) dprintf(idx, "I'm not going to dehalfop myself.\n"); return; } - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s); + u = get_user_from_member(m); get_user_flagrec(u, &victim, chan->dname); if ((chan_master(victim) || glob_master(victim)) && !(chan_owner(user) || glob_owner(user))) { @@ -512,7 +499,6 @@ static void cmd_voice(struct userrec *u, int idx, char *par) struct userrec *u2; char *nick; memberlist *m; - char s[UHOSTLEN]; nick = newsplit(&par); chan = get_channel(idx, par); @@ -533,8 +519,7 @@ static void cmd_voice(struct userrec *u, int idx, char *par) * - stdarg */ if (m && !(chan_op(user) || chan_halfop(user) || (glob_op(user) && !chan_deop(user)) || (glob_halfop(user) && !chan_dehalfop(user)))) { - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u2 = m->user ? m->user : get_user_by_host(s); + u2 = get_user_from_member(m); if (!u2 || strcasecmp(u2->handle, dcc[idx].nick) || (!chan_voice(user) && (!glob_voice(user) || chan_quiet(user)))) { @@ -570,7 +555,6 @@ static void cmd_devoice(struct userrec *u, int idx, char *par) struct userrec *u2; char *nick; memberlist *m; - char s[UHOSTLEN]; nick = newsplit(&par); chan = get_channel(idx, par); @@ -586,8 +570,7 @@ static void cmd_devoice(struct userrec *u, int idx, char *par) m = ismember(chan, nick); if (m && !(chan_op(user) || chan_halfop(user) || (glob_op(user) && !chan_deop(user)) || (glob_halfop(user) && !chan_dehalfop(user)))) { - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u2 = m->user ? m->user : get_user_by_host(s); + u2 = get_user_from_member(m); if (!u2 || strcasecmp(u2->handle, dcc[idx].nick) || (!chan_voice(user) && (!glob_voice(user) || chan_quiet(user)))) { @@ -623,7 +606,6 @@ static void cmd_kick(struct userrec *u, int idx, char *par) struct chanset_t *chan; char *chname, *nick; memberlist *m; - char s[UHOSTLEN]; if (!par[0]) { dprintf(idx, "Usage: kick [channel] [reason]\n"); @@ -663,8 +645,7 @@ static void cmd_kick(struct userrec *u, int idx, char *par) chan->dname); return; } - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s); + u = get_user_from_member(m); get_user_flagrec(u, &victim, chan->dname); if ((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) && !(chan_master(user) || glob_master(user))) { @@ -748,8 +729,9 @@ static void cmd_channel(struct userrec *u, int idx, char *par) for (m = chan->channel.member; m && m->nick[0]; m = m->next) { if (strlen(m->nick) > maxnicklen) maxnicklen = strlen(m->nick); - if ((m->user) && (strlen(m->user->handle) > maxhandlen)) - maxhandlen = strlen(m->user->handle); + u = get_user_from_member(m); + if (u && (strlen(u->handle) > maxhandlen)) + maxhandlen = strlen(u->handle); } if (maxnicklen < 9) maxnicklen = 9; @@ -768,15 +750,14 @@ static void cmd_channel(struct userrec *u, int idx, char *par) strftime(s, 6, "%H:%M", localtime(&(m->joined))); } else strlcpy(s, " --- ", sizeof s); - if (m->user == NULL) { - egg_snprintf(s1, sizeof s1, "%s!%s", m->nick, m->userhost); - m->user = get_user_by_host(s1); - } - if (m->user == NULL) + egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); + + u = get_user_from_member(m); + if (u == NULL) strlcpy(handle, "*", sizeof handle); else - strlcpy(handle, m->user->handle, sizeof handle); - get_user_flagrec(m->user, &user, chan->dname); + strlcpy(handle, u->handle, sizeof handle); + get_user_flagrec(u, &user, chan->dname); /* Determine status char to use */ if (glob_bot(user) && (glob_op(user) || chan_op(user))) atrflag = 'B'; @@ -1022,7 +1003,7 @@ static void cmd_adduser(struct userrec *u, int idx, char *par) if (strlen(hand) > HANDLEN) hand[HANDLEN] = 0; egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s); + u = get_user_from_member(m); if (u) { dprintf(idx, "%s is already known as %s.\n", nick, u->handle); return; @@ -1059,7 +1040,7 @@ static void cmd_adduser(struct userrec *u, int idx, char *par) static void cmd_deluser(struct userrec *u, int idx, char *par) { - char *nick, s[UHOSTLEN]; + char *nick; struct chanset_t *chan; memberlist *m = NULL; struct flag_record victim = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 }; @@ -1080,8 +1061,7 @@ static void cmd_deluser(struct userrec *u, int idx, char *par) return; } get_user_flagrec(u, &user, chan->dname); - egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s); + u = get_user_from_member(m); if (!u) { dprintf(idx, "%s is not a valid user.\n", nick); return; diff --git a/src/mod/irc.mod/irc.c b/src/mod/irc.mod/irc.c index 8cce81776..dc03c7f24 100644 --- a/src/mod/irc.mod/irc.c +++ b/src/mod/irc.mod/irc.c @@ -142,7 +142,6 @@ static void punish_badguy(struct chanset_t *chan, char *whobad, /* Set the offender +d */ if ((chan->revenge_mode > 0) && !(chan_deop(fr) || glob_deop(fr))) { char s[UHOSTLEN], s1[UHOSTLEN]; - memberlist *mx = NULL; /* Removing op */ if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) { @@ -186,8 +185,6 @@ static void punish_badguy(struct chanset_t *chan, char *whobad, fr.chan = USER_DEOP; fr.udef_chan = 0; u = get_user_by_handle(userlist, s1); - if ((mx = ismember(chan, badnick))) - mx->user = u; set_user_flagrec(u, &fr, chan->dname); simple_sprintf(s, "(%s) %s (%s)", ct, reason, whobad); set_user(&USERENTRY_COMMENT, u, (void *) s); @@ -230,17 +227,20 @@ static void maybe_revenge(struct chanset_t *chan, char *whobad, char *badnick, *victim; int mevictim; struct userrec *u, *u2; + memberlist *m; if (!chan || (type < 0)) return; /* Get info about offender */ - u = get_user_by_host(whobad); badnick = splitnick(&whobad); + m = ismember(chan, badnick); + u = get_user_from_member(m); /* Get info about victim */ - u2 = get_user_by_host(whovictim); victim = splitnick(&whovictim); + m = ismember(chan, victim); + u2 = get_user_from_member(m); mevictim = match_my_nick(victim); /* Do we want to revenge? */ @@ -264,12 +264,10 @@ static void set_key(struct chanset_t *chan, char *k) static int hand_on_chan(struct chanset_t *chan, struct userrec *u) { - char s[NICKMAX+UHOSTLEN+1]; memberlist *m; for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - sprintf(s, "%s!%s", m->nick, m->userhost); - if (u == get_user_by_host(s)) + if (u == get_user_from_member(m)) return 1; } return 0; @@ -531,7 +529,6 @@ static void status_log() static void check_lonely_channel(struct chanset_t *chan) { memberlist *m; - char s[NICKMAX+UHOSTLEN+1]; int i = 0; if (channel_pending(chan) || !channel_active(chan) || me_op(chan) || @@ -576,8 +573,7 @@ static void check_lonely_channel(struct chanset_t *chan) chan->status |= CHAN_WHINED; } for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - sprintf(s, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s); + u = get_user_from_member(m); if (!match_my_nick(m->nick) && (!u || !(u->flags & USER_BOT))) { ok = 0; break; @@ -601,7 +597,7 @@ static void check_expired_chanstuff() { masklist *b, *e; memberlist *m, *n; - char *key, s[NICKMAX+UHOSTLEN+1]; + char *key; struct chanset_t *chan; struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; @@ -670,9 +666,7 @@ static void check_expired_chanstuff() for (m = chan->channel.member; m && m->nick[0]; m = m->next) if (now - m->last >= chan->idle_kick * 60 && !match_my_nick(m->nick) && !chan_issplit(m)) { - sprintf(s, "%s!%s", m->nick, m->userhost); - get_user_flagrec(m->user ? m->user : get_user_by_host(s), - &fr, chan->dname); + get_user_flagrec(get_user_from_member(m), &fr, chan->dname); if ((!(glob_bot(fr) || glob_friend(fr) || (glob_op(fr) && !chan_deop(fr)) || chan_friend(fr) || chan_op(fr))) && (me_op(chan) || (me_halfop(chan) && !chan_hasop(m)))) { @@ -685,9 +679,7 @@ static void check_expired_chanstuff() for (m = chan->channel.member; m && m->nick[0]; m = n) { n = m->next; if (m->split && now - m->split > wait_split) { - sprintf(s, "%s!%s", m->nick, m->userhost); - check_tcl_sign(m->nick, m->userhost, - m->user ? m->user : get_user_by_host(s), + check_tcl_sign(m->nick, m->userhost, get_user_from_member(m), chan->dname, "lost in the netsplit"); putlog(LOG_JOIN, chan->dname, "%s (%s) got lost in the net-split.", m->nick, m->userhost); @@ -915,12 +907,16 @@ static int check_tcl_pub(char *nick, char *from, char *chname, char *msg) struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; int x; char buf[512], *args = buf, *cmd, host[161], *hand; + struct chanset_t *chan; struct userrec *u; + memberlist *m; strlcpy(buf, msg, sizeof buf); cmd = newsplit(&args); simple_sprintf(host, "%s!%s", nick, from); - u = get_user_by_host(host); + chan = findchan(chname); + m = ismember(chan, nick); + u = get_user_from_member(m); hand = u ? u->handle : "*"; get_user_flagrec(u, &fr, chname); Tcl_SetVar(interp, "_pub1", nick, 0); @@ -943,10 +939,14 @@ static int check_tcl_pubm(char *nick, char *from, char *chname, char *msg) int x; char buf[1024], host[161]; struct userrec *u; + struct chanset_t *chan; + memberlist *m; simple_sprintf(buf, "%s %s", chname, msg); simple_sprintf(host, "%s!%s", nick, from); - u = get_user_by_host(host); + chan = findchan(chname); + m = ismember(chan, nick); + u = get_user_from_member(m); get_user_flagrec(u, &fr, chname); Tcl_SetVar(interp, "_pubm1", nick, 0); Tcl_SetVar(interp, "_pubm2", from, 0); diff --git a/src/mod/irc.mod/mode.c b/src/mod/irc.mod/mode.c index 327844c3b..88814d3bf 100644 --- a/src/mod/irc.mod/mode.c +++ b/src/mod/irc.mod/mode.c @@ -421,11 +421,7 @@ static void got_op(struct chanset_t *chan, char *nick, char *from, check_chan = 1; strcpy(ch, chan->name); - simple_sprintf(s, "%s!%s", m->nick, m->userhost); - if (!m->user) - u = get_user_by_host(s); - else - u = m->user; + u = get_user_from_member(m); get_user_flagrec(u, &victim, chan->dname); /* Flags need to be set correctly right from the beginning now, so that @@ -519,11 +515,7 @@ static void got_halfop(struct chanset_t *chan, char *nick, char *from, check_chan = 1; strcpy(ch, chan->name); - simple_sprintf(s, "%s!%s", m->nick, m->userhost); - if (!m->user) - u = get_user_by_host(s); - else - u = m->user; + u = get_user_from_member(m); get_user_flagrec(u, &victim, chan->dname); /* Flags need to be set correctly right from the beginning now, so that @@ -612,7 +604,7 @@ static void got_deop(struct chanset_t *chan, char *nick, char *from, strcpy(ch, chan->name); simple_sprintf(s, "%s!%s", m->nick, m->userhost); simple_sprintf(s1, "%s!%s", nick, from); - u = get_user_by_host(s); + u = get_user_from_member(m); get_user_flagrec(u, &victim, chan->dname); had_halfop = chan_hasop(m); @@ -703,9 +695,8 @@ static void got_dehalfop(struct chanset_t *chan, char *nick, char *from, } strcpy(ch, chan->name); - simple_sprintf(s, "%s!%s", m->nick, m->userhost); simple_sprintf(s1, "%s!%s", nick, from); - u = get_user_by_host(s); + u = get_user_from_member(m); get_user_flagrec(u, &victim, chan->dname); had_halfop = chan_hasop(m); @@ -784,7 +775,7 @@ static void got_ban(struct chanset_t *chan, char *nick, char *from, char *who, for (m = chan->channel.member; m && m->nick[0]; m = m->next) { egg_snprintf(s1, sizeof s1, "%s!%s", m->nick, m->userhost); if (match_addr(who, s1)) { - targ = get_user_by_host(s1); + targ = get_user_from_member(m); if (targ) { get_user_flagrec(targ, &victim, chan->dname); if ((glob_friend(victim) || (glob_op(victim) && !chan_deop(victim)) || @@ -1025,12 +1016,15 @@ static int gotmode(char *from, char *origmsg) msg[z] = 0; putlog(LOG_MODES, chan->dname, "%s: mode change '%s %s' by %s", ch, chg, msg, from); - u = get_user_by_host(from); - get_user_flagrec(u, &user, ch); nick = splitnick(&from); m = ismember(chan, nick); - if (m) + if (m) { + u = get_user_from_member(m); + get_user_flagrec(u, &user, ch); m->last = now; + } else { + u = NULL; + } if (m && channel_active(chan) && (me_op(chan) || (me_halfop(chan) && !chan_hasop(m))) && !(glob_friend(user) || chan_friend(user) || (channel_dontkickops(chan) && (chan_op(user) || (glob_op(user) && @@ -1249,8 +1243,7 @@ static int gotmode(char *from, char *origmsg) refresh_who_chan(chan->name); } else { simple_sprintf(s, "%s!%s", m->nick, m->userhost); - get_user_flagrec(m->user ? m->user : get_user_by_host(s), - &victim, chan->dname); + get_user_flagrec(get_user_from_member(m), &victim, chan->dname); if (ms2[0] == '+') { m->flags &= ~SENTVOICE; m->flags |= CHANVOICE; diff --git a/src/mod/irc.mod/msgcmds.c b/src/mod/irc.mod/msgcmds.c index d179ceac9..282687425 100644 --- a/src/mod/irc.mod/msgcmds.c +++ b/src/mod/irc.mod/msgcmds.c @@ -383,7 +383,7 @@ static int msg_who(char *nick, char *host, struct userrec *u, char *par) struct userrec *u; egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s); + u = get_user_from_member(m); info = get_user(&USERENTRY_INFO, u); if (u && (u->flags & USER_BOT)) info = 0; @@ -431,7 +431,7 @@ static int msg_who(char *nick, char *host, struct userrec *u, char *par) static int msg_whois(char *nick, char *host, struct userrec *u, char *par) { - char s[UHOSTLEN + 1], s1[143], *s2, stime[14]; + char s1[143], *s2, stime[14]; int ok; struct chanset_t *chan; memberlist *m; @@ -462,8 +462,7 @@ static int msg_whois(char *nick, char *host, struct userrec *u, char *par) for (chan = chanset; chan && !ok; chan = chan->next) { m = ismember(chan, par); if (m) { - egg_snprintf(s, sizeof s, "%s!%s", par, m->userhost); - u2 = get_user_by_host(s); + u2 = get_user_from_member(m); if (u2) { ok = 1; dprintf(DP_HELP, "NOTICE %s :[%s] AKA '%s':\n", nick, diff --git a/src/mod/irc.mod/tclirc.c b/src/mod/irc.mod/tclirc.c index 36b485a2a..b8a93b3cd 100644 --- a/src/mod/irc.mod/tclirc.c +++ b/src/mod/irc.mod/tclirc.c @@ -24,10 +24,10 @@ */ static int tcl_chanlist STDVAR { - char nuh[1024]; int f; memberlist *m; struct chanset_t *chan; + struct userrec *u; struct flag_record plus = { FR_CHAN | FR_GLOBAL | FR_BOT, 0, 0, 0, 0, 0 }, minus = { FR_CHAN | FR_GLOBAL | FR_BOT, 0, 0, 0, 0, 0}, user = { FR_CHAN | FR_GLOBAL | FR_BOT, 0, 0, 0, 0, 0 }; @@ -55,11 +55,8 @@ static int tcl_chanlist STDVAR minus.match = plus.match ^ (FR_AND | FR_OR); for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - if (!m->user) { - egg_snprintf(nuh, sizeof nuh, "%s!%s", m->nick, m->userhost); - m->user = get_user_by_host(nuh); - } - get_user_flagrec(m->user, &user, argv[1]); + u = get_user_from_member(m); + get_user_flagrec(u, &user, argv[1]); user.match = plus.match; if (flagrec_eq(&plus, &user)) { if (!f || !flagrec_eq(&minus, &user)) @@ -347,8 +344,8 @@ static int tcl_onchan STDVAR static int tcl_handonchan STDVAR { - char nuh[1024]; struct chanset_t *chan, *thechan = NULL; + struct userrec *u; memberlist *m; BADARGS(2, 3, " handle ?channel?"); @@ -365,11 +362,8 @@ static int tcl_handonchan STDVAR while (chan && (thechan == NULL || thechan == chan)) { for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - if (!m->user) { - egg_snprintf(nuh, sizeof nuh, "%s!%s", m->nick, m->userhost); - m->user = get_user_by_host(nuh); - } - if (m->user && !strcasecmp(m->user->handle, argv[1])) { + u = get_user_from_member(m); + if (u && !strcasecmp(u->handle, argv[1])) { Tcl_AppendResult(irp, "1", NULL); return TCL_OK; } @@ -1027,9 +1021,9 @@ static int tcl_account2nicks STDVAR static int tcl_hand2nicks STDVAR { - char nuh[1024]; memberlist *m; struct chanset_t *chan, *thechan = NULL; + struct userrec *u; Tcl_Obj *nicks; Tcl_Obj **nicksv = NULL; int nicksc = 0, i, found; @@ -1050,13 +1044,8 @@ static int tcl_hand2nicks STDVAR while (chan && (thechan == NULL || thechan == chan)) { for (m = chan->channel.member; m && m->nick[0]; m = m->next) { found = 0; - /* Does this user have the account we're looking for? */ - if (!m->user && !m->tried_getuser) { - egg_snprintf(nuh, sizeof nuh, "%s!%s", m->nick, m->userhost); - m->tried_getuser = 1; - m->user = get_user_by_host(nuh); - } - if (m->user && !strcasecmp(m->user->handle, argv[1])) { + u = get_user_from_member(m); + if (u && !strcasecmp(u->handle, argv[1])) { /* Is the nick of the user already in the list? */ Tcl_ListObjGetElements(irp, nicks, &nicksc, &nicksv); for (i = 0; i < nicksc; i++) { @@ -1078,9 +1067,9 @@ static int tcl_hand2nicks STDVAR static int tcl_hand2nick STDVAR { - char nuh[1024]; memberlist *m; struct chanset_t *chan, *thechan = NULL; + struct userrec *u; BADARGS(2, 3, " handle ?channel?"); @@ -1096,12 +1085,8 @@ static int tcl_hand2nick STDVAR while (chan && (thechan == NULL || thechan == chan)) { for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - if (!m->user && !m->tried_getuser) { - egg_snprintf(nuh, sizeof nuh, "%s!%s", m->nick, m->userhost); - m->tried_getuser = 1; - m->user = get_user_by_host(nuh); - } - if (m->user && !strcasecmp(m->user->handle, argv[1])) { + u = get_user_from_member(m); + if (u && !strcasecmp(u->handle, argv[1])) { Tcl_AppendResult(irp, m->nick, NULL); return TCL_OK; } @@ -1113,9 +1098,9 @@ static int tcl_hand2nick STDVAR static int tcl_nick2hand STDVAR { - char nuh[1024]; memberlist *m; struct chanset_t *chan, *thechan = NULL; + struct userrec *u; BADARGS(2, 3, " nick ?channel?"); @@ -1132,11 +1117,8 @@ static int tcl_nick2hand STDVAR while (chan && (thechan == NULL || thechan == chan)) { m = ismember(chan, argv[1]); if (m) { - if (!m->user) { - egg_snprintf(nuh, sizeof nuh, "%s!%s", m->nick, m->userhost); - m->user = get_user_by_host(nuh); - } - Tcl_AppendResult(irp, m->user ? m->user->handle : "*", NULL); + u = get_user_from_member(m); + Tcl_AppendResult(irp, u ? u->handle : "*", NULL); return TCL_OK; } chan = chan->next; diff --git a/src/mod/module.h b/src/mod/module.h index 951241adb..da1651c0a 100644 --- a/src/mod/module.h +++ b/src/mod/module.h @@ -524,7 +524,8 @@ typedef void (*chanout_butfunc)(int, int, const char *, ...) ATTRIBUTE_FORMAT(pr #define bind_bind_entry ((int(*)(tcl_bind_list_t *, const char *, const char *, const char *))global[320]) #define unbind_bind_entry ((int(*)(tcl_bind_list_t *, const char *, const char *, const char *))global[321]) #define argv0 ((char *)global[322]) - +#define get_user_from_member ((struct userrec * (*)(memberlist *))global[323]) +/* 324 - 327 */ /* hostmasking */ diff --git a/src/mod/notes.mod/notes.c b/src/mod/notes.mod/notes.c index 5c5d47aa8..ee9a9b3e5 100644 --- a/src/mod/notes.mod/notes.c +++ b/src/mod/notes.mod/notes.c @@ -834,13 +834,11 @@ static void notes_hourly() memberlist *m; int k; int l; - char s1[NICKMAX+UHOSTLEN+1]; struct userrec *u; for (chan = chanset; chan; chan = chan->next) { for (m = chan->channel.member; m && m->nick[0]; m = m->next) { - sprintf(s1, "%s!%s", m->nick, m->userhost); - u = get_user_by_host(s1); + u = get_user_from_member(m); if (u) { k = num_notes(u->handle); for (l = 0; l < dcc_total; l++) diff --git a/src/mod/seen.mod/seen.c b/src/mod/seen.mod/seen.c index 41cea68d2..5dbb095da 100644 --- a/src/mod/seen.mod/seen.c +++ b/src/mod/seen.mod/seen.c @@ -148,7 +148,7 @@ static int dcc_seen(struct userrec *u, int idx, char *par) static void do_seen(int idx, char *prefix, char *nick, char *hand, char *channel, char *text) { - char stuff[512], word1[512], word2[512], whotarget[128], object[128], + char word1[512], word2[512], whotarget[128], object[128], whoredirect[512], *oix, *lastonplace = 0; struct userrec *urec; struct chanset_t *chan; @@ -194,8 +194,7 @@ static void do_seen(int idx, char *prefix, char *nick, char *hand, m = ismember(chan, object); if (m) { onchan = 1; - snprintf(stuff, sizeof stuff, "%s!%s", object, m->userhost); - urec = get_user_by_host(stuff); + urec = get_user_from_member(m); if (!urec || !strcasecmp(object, urec->handle)) break; strcat(whoredirect, object); @@ -342,7 +341,7 @@ static void do_seen(int idx, char *prefix, char *nick, char *hand, if (m) { onchan = 1; snprintf(word1, sizeof word1, "%s!%s", whotarget, m->userhost); - urec = get_user_by_host(word1); + urec = get_user_from_member(m); if (!urec || !strcasecmp(whotarget, urec->handle)) break; strcat(whoredirect, whotarget); @@ -359,8 +358,7 @@ static void do_seen(int idx, char *prefix, char *nick, char *hand, while (chan) { m = chan->channel.member; while (m && m->nick[0]) { - snprintf(word2, sizeof word2, "%s!%s", m->nick, m->userhost); - urec = get_user_by_host(word2); + urec = get_user_from_member(m); if (urec && !strcasecmp(urec->handle, whotarget)) { strcat(whoredirect, whotarget); strcat(whoredirect, " is "); diff --git a/src/modules.c b/src/modules.c index afb614221..61ae64716 100644 --- a/src/modules.c +++ b/src/modules.c @@ -626,7 +626,9 @@ Function global_table[] = { /* 320 - 323 */ (Function) bind_bind_entry, (Function) unbind_bind_entry, - (Function) & argv0 + (Function) & argv0, + (Function) get_user_from_member +/* 324 - 327 */ }; void init_modules(void) diff --git a/src/userrec.c b/src/userrec.c index da5da6b42..61af179d5 100644 --- a/src/userrec.c +++ b/src/userrec.c @@ -171,20 +171,6 @@ static struct userrec *check_dcclist_hand(char *handle) return NULL; } -/* Shortcut for get_user_by_handle -- might have user record in channels - */ -static struct userrec *check_chanlist_hand(const char *hand) -{ - struct chanset_t *chan; - memberlist *m; - - for (chan = chanset; chan; chan = chan->next) - for (m = chan->channel.member; m && m->nick[0]; m = m->next) - if (m->user && !strcasecmp(m->user->handle, hand)) - return m->user; - return NULL; -} - /* Search userlist for a provided account name * Returns: userrecord for user containing the account */ @@ -193,12 +179,11 @@ struct userrec *get_user_by_account(char *acct) struct userrec *u; struct list_type *q; - if (acct == NULL) + if (!acct || !acct[0] || !strcmp(acct, "*")) return NULL; for (u = userlist; u; u = u->next) { - q = get_user(&USERENTRY_ACCOUNT, u); - for (; q; q = q->next) { - if(q && !strcasecmp(q->extra, acct)) { + for (q = get_user(&USERENTRY_ACCOUNT, u); q; q = q->next) { + if (!rfc_casecmp(q->extra, acct)) { return u; } } @@ -226,11 +211,6 @@ struct userrec *get_user_by_handle(struct userrec *bu, char *handle) cache_hit++; return ret; } - ret = check_chanlist_hand(handle); - if (ret) { - cache_hit++; - return ret; - } cache_miss++; } for (u = bu; u; u = u->next) @@ -242,6 +222,29 @@ struct userrec *get_user_by_handle(struct userrec *bu, char *handle) return NULL; } +struct userrec *get_user_from_member(memberlist *m) +{ + struct userrec *ret; + + /* Check if there is a user with a matching account if one is provided */ + if (m->account[0] != '*') { + ret = get_user_by_account(m->account); + if (ret) { + return ret; + } + } + /* Check if there is a user with a matching hostmask if one is provided */ + if ((m->userhost[0] != '\0') && (m->nick[0] != '\0')) { + char s[NICKMAX+UHOSTLEN+1]; + sprintf(s, "%s!%s", m->nick, m->userhost); + ret = get_user_by_host(s); + if (ret) { + return ret; + } + } + return NULL; +} + /* Fix capitalization, etc */ void correct_handle(char *handle) @@ -265,8 +268,6 @@ void clear_masks(maskrec *m) temp = m->next; if (m->mask) nfree(m->mask); - if (m->user) - nfree(m->user); if (m->desc) nfree(m->desc); nfree(m); @@ -311,12 +312,10 @@ void clear_userlist(struct userrec *bu) /* Find CLOSEST host match * (if "*!*@*" and "*!*@*clemson.edu" both match, use the latter!) - * - * Checks the chanlist first, to possibly avoid needless search. */ struct userrec *get_user_by_host(char *host) { - struct userrec *u, *ret; + struct userrec *u, *ret = NULL; struct list_type *q; int cnt, i; char host2[UHOSTLEN]; @@ -326,12 +325,7 @@ struct userrec *get_user_by_host(char *host) rmspace(host); if (!host[0]) return NULL; - ret = check_chanlist(host); cnt = 0; - if (ret != NULL) { - cache_hit++; - return ret; - } cache_miss++; strlcpy(host2, host, sizeof host2); for (u = userlist; u; u = u->next) { @@ -346,7 +340,6 @@ struct userrec *get_user_by_host(char *host) } if (ret != NULL) { lastuser = ret; - set_chanlist(host2, ret); } return ret; } diff --git a/src/users.h b/src/users.h index e9a451418..a273ca95c 100644 --- a/src/users.h +++ b/src/users.h @@ -184,6 +184,7 @@ struct userrec *get_user_by_handle(struct userrec *, char *); struct userrec *get_user_by_host(char *); struct userrec *get_user_by_account(char *); struct userrec *get_user_by_nick(char *); +struct userrec *get_user_from_member(memberlist *); struct userrec *check_chanlist(const char *); /* All the default userentry stuff, for code re-use diff --git a/src/version.h b/src/version.h index 63e9d3316..64e4e4698 100644 --- a/src/version.h +++ b/src/version.h @@ -27,5 +27,5 @@ */ #define EGG_STRINGVER "1.9.5" -#define EGG_NUMVER 1090505 -#define EGG_PATCH "python" +#define EGG_NUMVER 1090506 +#define EGG_PATCH "accounttracking"