diff --git a/src/cmds.c b/src/cmds.c index e1730507a..507c69687 100644 --- a/src/cmds.c +++ b/src/cmds.c @@ -1908,11 +1908,11 @@ static int add_to_handle(struct userrec *u, int idx, char *handle, char *host, i } } if ( !type && !glob_botmast(fr) && !chan_master(fr) && get_user_by_host(host)) { - dprintf(idx, "You cannot add %s matching another user!\n", - type ? "an account" : "a host"); + dprintf(idx, "You cannot add a host matching another user!\n"); return 1; } if (type) { + // host-variable contains account u2 = get_user_by_account(host); if (u2) { dprintf(idx, "That account already exists for user %s\n", u2->handle); @@ -1920,6 +1920,7 @@ static int add_to_handle(struct userrec *u, int idx, char *handle, char *host, i } addaccount_by_handle(handle, host); } else { + // host for (q = get_user(&USERENTRY_HOSTS, u); q; q = q->next) { if (!strcasecmp(q->extra, host)) { dprintf(idx, "That %s is already there.\n", diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index f0cb827d7..9124d428c 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -240,15 +240,7 @@ static int detect_chan_flood(char *floodnick, char *floodhost, char *from, if (!m && (which != FLOOD_JOIN)) return 0; - 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); - } - } - + u = lookup_user_record(m, victim_or_account, 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))) || @@ -333,7 +325,6 @@ 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_from_member(m); if (check_tcl_flud(floodnick, floodhost, u, ftype, chan->dname)) return 0; switch (which) { @@ -1843,7 +1834,7 @@ static int gottopic(char *from, char *msg) if (m != NULL) m->last = now; set_topic(chan, msg); - u = get_user_from_member(m); + u = lookup_user_record(m, NULL, from); // TODO: get account from msgtags check_tcl_topc(nick, from, u, chan->dname, msg); } return 0; @@ -2079,9 +2070,8 @@ static int gotjoin(char *from, char *channame) strlcpy(m->userhost, uhost, sizeof m->userhost); m->flags |= STOPWHO; - u = get_user_from_member(m); - if (extjoin) { + u = lookup_user_record(m, account, from); /* calls check_tcl_account which can delete the channel */ setaccount(nick, account); @@ -2089,6 +2079,8 @@ static int gotjoin(char *from, char *channame) /* The channel doesn't exist anymore, so get out of here. */ goto exit; } + } else { + u = lookup_user_record(find_member_from_nick(nick), NULL, from); // TODO: get account from msgtags } check_tcl_join(nick, uhost, u, chan->dname); @@ -2129,9 +2121,9 @@ static int gotjoin(char *from, char *channame) if (u) { struct laston_info *li = 0; - cr = get_chanrec(get_user_from_member(m), chan->dname); + cr = get_chanrec(u, chan->dname); if (!cr && no_chanrec_info) - li = get_user(&USERENTRY_LASTON, get_user_from_member(m)); + li = get_user(&USERENTRY_LASTON, u); if (channel_greet(chan) && use_info && ((cr && now - cr->laston > wait_info) || (no_chanrec_info && (!li || now - li->laston > wait_info)))) { @@ -2353,7 +2345,7 @@ static int gotkick(char *from, char *origmsg) return 0; m = ismember(chan, whodid); - u = get_user_from_member(m); + u = lookup_user_record(m, NULL, from); // TODO: get account from msgtags if (m) m->last = now; /* This _needs_ to use chan->dname */ @@ -2569,7 +2561,6 @@ 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. */ @@ -2613,15 +2604,7 @@ static int gotmsg(char *from, char *msg) ctcp_count++; if (ctcp[0] != ' ') { code = newsplit(&ctcp); - 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; - } - } - } + u = lookup_user_record(find_member_from_nick(nick), NULL, from); // TODO: get account from msgtags if (!ignoring || trigger_on_ignore) { if (!check_tcl_ctcp(nick, uhost, u, to, code, ctcp)) { chan = findchan(realto); @@ -2700,7 +2683,6 @@ 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)) @@ -2714,15 +2696,7 @@ static int gotnotice(char *from, char *msg) fixcolon(msg); strlcpy(uhost, from, sizeof buf); nick = splitnick(&uhost); - 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; - } - } - } + u = lookup_user_record(find_member_from_nick(nick), NULL, from); // TODO: get account from msgtags /* 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 3b387c8f6..c9bf58ab1 100644 --- a/src/mod/irc.mod/cmdsirc.c +++ b/src/mod/irc.mod/cmdsirc.c @@ -751,7 +751,6 @@ static void cmd_channel(struct userrec *u, int idx, char *par) } else strlcpy(s, " --- ", sizeof s); egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost); - u = get_user_from_member(m); if (u == NULL) strlcpy(handle, "*", sizeof handle); diff --git a/src/mod/irc.mod/irc.c b/src/mod/irc.mod/irc.c index dc03c7f24..bc3f578e4 100644 --- a/src/mod/irc.mod/irc.c +++ b/src/mod/irc.mod/irc.c @@ -224,7 +224,7 @@ static void punish_badguy(struct chanset_t *chan, char *whobad, static void maybe_revenge(struct chanset_t *chan, char *whobad, char *whovictim, int type) { - char *badnick, *victim; + char *badnick, *victim, buf[NICKLEN + UHOSTLEN]; int mevictim; struct userrec *u, *u2; memberlist *m; @@ -233,14 +233,16 @@ static void maybe_revenge(struct chanset_t *chan, char *whobad, return; /* Get info about offender */ + strlcpy(buf, whobad, sizeof buf); badnick = splitnick(&whobad); m = ismember(chan, badnick); - u = get_user_from_member(m); + u = lookup_user_record(m, NULL, buf); // TODO: get account from msgtags /* Get info about victim */ + strlcpy(buf, whovictim, sizeof buf); victim = splitnick(&whovictim); m = ismember(chan, victim); - u2 = get_user_from_member(m); + u2 = lookup_user_record(m, NULL, buf); // TODO: get account from msgtags mevictim = match_my_nick(victim); /* Do we want to revenge? */ @@ -908,7 +910,7 @@ static int check_tcl_pub(char *nick, char *from, char *chname, char *msg) int x; char buf[512], *args = buf, *cmd, host[161], *hand; struct chanset_t *chan; - struct userrec *u; + struct userrec *u = NULL; memberlist *m; strlcpy(buf, msg, sizeof buf); @@ -916,7 +918,7 @@ static int check_tcl_pub(char *nick, char *from, char *chname, char *msg) simple_sprintf(host, "%s!%s", nick, from); chan = findchan(chname); m = ismember(chan, nick); - u = get_user_from_member(m); + u = lookup_user_record(m ? m : find_member_from_nick(nick), NULL, from); // TODO: get account from msgtags hand = u ? u->handle : "*"; get_user_flagrec(u, &fr, chname); Tcl_SetVar(interp, "_pub1", nick, 0); @@ -946,7 +948,7 @@ static int check_tcl_pubm(char *nick, char *from, char *chname, char *msg) simple_sprintf(host, "%s!%s", nick, from); chan = findchan(chname); m = ismember(chan, nick); - u = get_user_from_member(m); + u = lookup_user_record(m ? m : find_member_from_nick(nick), NULL, from); // TODO: get account from msgtags 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 88814d3bf..5350fafd7 100644 --- a/src/mod/irc.mod/mode.c +++ b/src/mod/irc.mod/mode.c @@ -52,11 +52,11 @@ static struct chanset_t *modebind_refresh(char *chname, if (!chname || !(chan = findchan(chname))) return NULL; if (usrhost) { - u = get_user_by_host(usrhost); + u = lookup_user_record(NULL, NULL, usrhost); // TODO: get account from somewhere get_user_flagrec(u, usr, chan->dname); } if (vcrhost) { - u = get_user_by_host(vcrhost); + u = lookup_user_record(NULL, NULL, vcrhost); // TODO: get account from somewhere get_user_flagrec(u, vcr, chan->dname); } return chan; diff --git a/src/mod/irc.mod/msgcmds.c b/src/mod/irc.mod/msgcmds.c index 282687425..1c8a45f6b 100644 --- a/src/mod/irc.mod/msgcmds.c +++ b/src/mod/irc.mod/msgcmds.c @@ -383,6 +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); + /* Don't use s for host here, b/c if we don't have m, we won't have s */ u = get_user_from_member(m); info = get_user(&USERENTRY_INFO, u); if (u && (u->flags & USER_BOT)) @@ -431,7 +432,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 s1[143], *s2, stime[14]; + char s1[143], *s2, stime[14], uhost[NICKLEN + UHOSTLEN]; int ok; struct chanset_t *chan; memberlist *m; @@ -454,7 +455,8 @@ static int msg_whois(char *nick, char *host, struct userrec *u, char *par) } if (strlen(par) > NICKMAX) par[NICKMAX] = 0; - putlog(LOG_CMDS, "*", "(%s!%s) !%s! WHOIS %s", nick, host, u->handle, par); + egg_snprintf(uhost, sizeof uhost, "%s!%s", nick, host); + putlog(LOG_CMDS, "*", "(%s) !%s! WHOIS %s", uhost, u->handle, par); u2 = get_user_by_handle(userlist, par); if (!u2) { /* No such handle -- maybe it's a nickname of someone on a chan? */ diff --git a/src/mod/module.h b/src/mod/module.h index da1651c0a..488664322 100644 --- a/src/mod/module.h +++ b/src/mod/module.h @@ -524,8 +524,9 @@ 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]) +#define lookup_user_record ((struct userrec * (*)(memberlist *, char *, char *))global[323]) /* 324 - 327 */ +#define find_member_from_nick ((memberlist * (*) (char *))global[324]) /* hostmasking */ diff --git a/src/mod/server.mod/servmsg.c b/src/mod/server.mod/servmsg.c index 952ff70bf..91a50e2e9 100644 --- a/src/mod/server.mod/servmsg.c +++ b/src/mod/server.mod/servmsg.c @@ -493,7 +493,7 @@ static int detect_flood(char *floodnick, char *floodhost, char *from, int which) if (!strcasecmp(floodhost, botuserhost)) return 0; - u = get_user_by_host(from); + u = lookup_user_record(NULL, NULL, from); // TODO: get account somehow atr = u ? u->flags : 0; if (atr & (USER_BOT | USER_FRIEND)) return 0; @@ -539,7 +539,7 @@ static int detect_flood(char *floodnick, char *floodhost, char *from, int which) lastmsgs[which] = 0; lastmsgtime[which] = 0; lastmsghost[which][0] = 0; - u = get_user_by_host(from); + u = lookup_user_record(NULL, NULL, from); // TODO: get account somehow if (check_tcl_flud(floodnick, floodhost, u, ftype, "*")) return 0; /* Private msg */ @@ -607,7 +607,7 @@ static int gotmsg(char *from, char *msg) putlog(LOG_PUBLIC, to, "CTCP %s: %s from %s (%s) to %s", code, ctcp, nick, uhost, to); } else { - u = get_user_by_host(from); + u = lookup_user_record(find_member_from_nick(nick), NULL, from); // TODO: get account from msgtags if (!ignoring || trigger_on_ignore) { if (!check_tcl_ctcp(nick, uhost, u, to, code, ctcp) && !ignoring) { if ((lowercase_ctcp && !strcasecmp(code, "DCC")) || @@ -670,7 +670,7 @@ static int gotmsg(char *from, char *msg) } detect_flood(nick, uhost, from, FLOOD_PRIVMSG); - u = get_user_by_host(from); + u = lookup_user_record(find_member_from_nick(nick), NULL, from); // TODO: get account from msgtags code = newsplit(&msg); rmspace(msg); @@ -730,7 +730,7 @@ static int gotnotice(char *from, char *msg) "CTCP reply %s: %s from %s (%s) to %s", code, ctcp, nick, uhost, to); } else { - u = get_user_by_host(from); + u = lookup_user_record(find_member_from_nick(nick), NULL, from); // TODO: get account from msgtags if (!ignoring || trigger_on_ignore) { check_tcl_ctcr(nick, uhost, u, to, code, ctcp); if (!ignoring) @@ -766,7 +766,7 @@ static int gotnotice(char *from, char *msg) } detect_flood(nick, uhost, from, FLOOD_NOTICE); - u = get_user_by_host(from); + u = lookup_user_record(find_member_from_nick(nick), NULL, from); // TODO: get account from msgtags if (!ignoring || trigger_on_ignore) if (check_tcl_notc(nick, uhost, u, botname, msg) == 2) diff --git a/src/modules.c b/src/modules.c index 61ae64716..b2ebf37ae 100644 --- a/src/modules.c +++ b/src/modules.c @@ -627,8 +627,9 @@ Function global_table[] = { (Function) bind_bind_entry, (Function) unbind_bind_entry, (Function) & argv0, - (Function) get_user_from_member + (Function) lookup_user_record, /* 324 - 327 */ + (Function) find_member_from_nick }; void init_modules(void) diff --git a/src/userrec.c b/src/userrec.c index 084dbcd64..66bb8f16c 100644 --- a/src/userrec.c +++ b/src/userrec.c @@ -171,6 +171,23 @@ static struct userrec *check_dcclist_hand(char *handle) return NULL; } +/* Search every channel record for the provided nickname. Used in cases where + * we are searching for a user record but don't have a memberlist to start from + */ +memberlist *find_member_from_nick(char *nick) { + struct chanset_t *chan; + memberlist *m = 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)) { + return m; + } + } + } + return m; +} + /* Search userlist for a provided account name * Returns: userrecord for user containing the account */ @@ -255,6 +272,43 @@ struct userrec *get_user_from_member(memberlist *m) return NULL; } +/* Wrapper function to find an Eggdrop user record based on either a provided + * channel memberlist record, host, or account. This function will first check + * a provided memberlist and return the result. If no user record is found (or + * the memberlist itself was NULL), this function will try again based on a + * provided account, and then again on a provided host. + * + * When calling this function it is best to provide all available independent + * variables- ie, if you provide 'm' for the memberlist, don't provide + * 'm->account' for the account, use the independent source variable 'account' + * if available. This allows redundant checking in case of unexpected NULLs + */ +struct userrec *lookup_user_record(memberlist *m, char *host, char *account) +{ + struct userrec *u = NULL; + +/* First check for a user record tied to a memberlist */ + if (m) { + u = get_user_from_member(m); + if (u) { + return u; + } + } +/* Next check for a user record tied to an account */ + if (account && account[0]) { + u = get_user_by_account(account); + if (u) { + return u; + } + } +/* Last check for a user record tied to a hostmask */ + if (host && host[0]) { + u = get_user_by_host(host); + return u; + } + return NULL; +} + /* Fix capitalization, etc */ void correct_handle(char *handle) diff --git a/src/users.c b/src/users.c index d5c48f234..928f85ae9 100644 --- a/src/users.c +++ b/src/users.c @@ -523,8 +523,6 @@ void tell_user_ident(int idx, char *id) struct userrec *u; u = get_user_by_handle(userlist, id); - if (u == NULL) - u = get_user_by_host(id); if (u == NULL) { dprintf(idx, "%s.\n", USERF_NOMATCH); return; diff --git a/src/users.h b/src/users.h index a273ca95c..6bc27c1ce 100644 --- a/src/users.h +++ b/src/users.h @@ -185,7 +185,9 @@ 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 *lookup_user_record(memberlist *, char *, char *); struct userrec *check_chanlist(const char *); +memberlist *find_member_from_nick(char *); /* All the default userentry stuff, for code re-use */