From ef6a458ce93d63f585115f1280ece2959428cc1d Mon Sep 17 00:00:00 2001 From: Geo Date: Sun, 18 Dec 2022 13:19:24 -0500 Subject: [PATCH 01/11] initial commit --- src/mod/irc.mod/chan.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index e16e85527..9a3d7e951 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -1335,6 +1335,34 @@ static int got354(char *from, char *msg) return 0; } +/* got 353: NAMES + * 353 :[+/@]nick [+/@]nick .... + * + * if userhost-in-names is enabled, nick is nick@userhost.com + * this function is added solely to handle userhost-in-names stuff, and will + * update hostnames for nicks received + */ +static int got353(char *from, char *msg) +{ + char *nameptr, *uhost, *nick; + struct chanset_t *chan; + memberlist *m; + + if (find_capability("userhost-in-names")) { + nameptr = strchr(msg, ':'); + while ((uhost = newsplit(&nameptr))) { + nick = splitnick(&uhost); + for (chan = chanset; chan; chan = chan->next) { + m = ismember(chan, nick); + if (m) { + strlcpy(m->userhost, uhost, UHOSTLEN); + } + } + } + } + return 0; +} + /* got 315: end of who * 315 :End of /who @@ -2997,6 +3025,7 @@ static int gotrawt(char *from, char *msg, Tcl_Obj *tags) { static cmd_t irc_raw[] = { {"324", "", (IntFunc) got324, "irc:324"}, {"352", "", (IntFunc) got352, "irc:352"}, + {"353", "", (IntFunc) got353, "irc:353"}, {"354", "", (IntFunc) got354, "irc:354"}, {"315", "", (IntFunc) got315, "irc:315"}, {"366", "", (IntFunc) gottwitch366, "irc:t366"}, From 94fbbf4ff47f69f020be00296df27c07acafe4a1 Mon Sep 17 00:00:00 2001 From: Geo Date: Sat, 24 Dec 2022 10:39:56 -0500 Subject: [PATCH 02/11] strip opchars from nicks and fix infinite loop --- src/mod/irc.mod/chan.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index 9a3d7e951..8cdb04475 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -1347,11 +1347,21 @@ static int got353(char *from, char *msg) char *nameptr, *uhost, *nick; struct chanset_t *chan; memberlist *m; + int i; if (find_capability("userhost-in-names")) { nameptr = strchr(msg, ':'); while ((uhost = newsplit(&nameptr))) { + if (!strcmp(uhost, "")) { + break; + } + fixcolon(uhost); nick = splitnick(&uhost); + for (i = 0; opchars[i]; i++) { + if(nick[0] == opchars[i]) { + nick=nick+1; + } + } for (chan = chanset; chan; chan = chan->next) { m = ismember(chan, nick); if (m) { From dadf690377412dba1ec1e4f1833f22056e88a5b0 Mon Sep 17 00:00:00 2001 From: Geo Date: Sat, 24 Dec 2022 10:58:41 -0500 Subject: [PATCH 03/11] check for voice/halfop status too --- src/mod/irc.mod/chan.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index 8cdb04475..a6fb54b3a 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -1357,11 +1357,15 @@ static int got353(char *from, char *msg) } fixcolon(uhost); nick = splitnick(&uhost); + /* Strip @, +, etc chars prefixed to nicks in NAMES */ for (i = 0; opchars[i]; i++) { if(nick[0] == opchars[i]) { nick=nick+1; } } + if ((nick[0] == '+') || (nick[0] == '%')) { + nick=nick+1; + } for (chan = chanset; chan; chan = chan->next) { m = ismember(chan, nick); if (m) { From d814a4fed8519b96cfbf175d34be3584939bc116 Mon Sep 17 00:00:00 2001 From: Geo Date: Wed, 28 Dec 2022 22:01:05 -0500 Subject: [PATCH 04/11] remove pending status --- src/mod/irc.mod/chan.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index a6fb54b3a..33fdebc36 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -1344,12 +1344,14 @@ static int got354(char *from, char *msg) */ static int got353(char *from, char *msg) { - char *nameptr, *uhost, *nick; + char *nameptr, *chname, *uhost, *nick; struct chanset_t *chan; memberlist *m; int i; if (find_capability("userhost-in-names")) { + chname = newsplit(msg); + /* use this instead of newsplit(), because sometimes there's a = in a 353 */ nameptr = strchr(msg, ':'); while ((uhost = newsplit(&nameptr))) { if (!strcmp(uhost, "")) { @@ -1373,6 +1375,13 @@ static int got353(char *from, char *msg) } } } + /* The assumption here is the user enabled userhost-in-names because WHO + * is disabled. We remove the pending flag here because we'll never get a + * a WHO to do it + */ + chan = findchan(chname); + chan->status |= CHAN_ACTIVE; + chan->status &= ~CHAN_PEND; } return 0; } From 88b37c01ce99a50b5cb160a169dda31702c34d98 Mon Sep 17 00:00:00 2001 From: Geo Date: Wed, 28 Dec 2022 22:21:14 -0500 Subject: [PATCH 05/11] Update ircv3 doc with errata --- doc/sphinx_source/using/ircv3.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/sphinx_source/using/ircv3.rst b/doc/sphinx_source/using/ircv3.rst index ee3c6b9e2..2491b2fa8 100644 --- a/doc/sphinx_source/using/ircv3.rst +++ b/doc/sphinx_source/using/ircv3.rst @@ -41,6 +41,14 @@ The following capabilities are supported by Eggdrop: * Monitor * server-time * setname + * userhost-in-names * +typing +------ +Errata +------ + +* Enabling echo-message will cause Eggdrop to trigger PUB/PUBM binds on its own messages (because now it can actually see them). This may cause unintentional functionality with some scripts +* Enabling userhost-in-names will cause Eggdrop's internal mechanisms to mark a channel's userlist as synch'd upon receiving the NAMES list after a join, instead of waiting for a full WHO listing. This is done because the assumption is that userhost-in-names was enabled as a response to WHO queries being disabled on a server, which prevents Eggdrop from populating its userlist. To avoid unintended functionality, it is suggested that this capability only be enabled on servers that disable WHO queries. + Copyright (C) 2010 - 2022 Eggheads Development Team From 9ff301477e15532943322edb31158ac5e2d42f13 Mon Sep 17 00:00:00 2001 From: Geo Date: Wed, 28 Dec 2022 22:21:48 -0500 Subject: [PATCH 06/11] fixup --- src/mod/irc.mod/chan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index 33fdebc36..9700a3f42 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -1350,7 +1350,7 @@ static int got353(char *from, char *msg) int i; if (find_capability("userhost-in-names")) { - chname = newsplit(msg); + chname = newsplit(&msg); /* use this instead of newsplit(), because sometimes there's a = in a 353 */ nameptr = strchr(msg, ':'); while ((uhost = newsplit(&nameptr))) { From 5a047d7cd4f887a88ed8d4ebae7617aaa2b0dad5 Mon Sep 17 00:00:00 2001 From: Geo Date: Mon, 1 Jan 2024 18:52:50 -0500 Subject: [PATCH 07/11] Update channel records with NAMES hosts --- src/mod/irc.mod/chan.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index c979df41d..ec13998a7 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -1344,15 +1344,15 @@ static int got354(char *from, char *msg) */ static int got353(char *from, char *msg) { - char *nameptr, *chname, *uhost, *nick; + char *nameptr, *chname, *uhost, *nick, *p, *host; struct chanset_t *chan; - memberlist *m; int i; if (find_capability("userhost-in-names")) { + newsplit(&msg); + newsplit(&msg); /* Get rid of =/@ prefix */ chname = newsplit(&msg); - /* use this instead of newsplit(), because sometimes there's a = in a 353 */ - nameptr = strchr(msg, ':'); + nameptr = newsplit(&msg); while ((uhost = newsplit(&nameptr))) { if (!strcmp(uhost, "")) { break; @@ -1369,9 +1369,13 @@ static int got353(char *from, char *msg) nick=nick+1; } for (chan = chanset; chan; chan = chan->next) { - m = ismember(chan, nick); - if (m) { - strlcpy(m->userhost, uhost, UHOSTLEN); + p = strchr(uhost, '@'); + if (p) { + *p = 0; + host = p+1; + } + if (uhost && host) { + got352or4(chan, uhost, host, nick, "", NULL); } } } @@ -1380,8 +1384,14 @@ static int got353(char *from, char *msg) * a WHO to do it */ chan = findchan(chname); - chan->status |= CHAN_ACTIVE; - chan->status &= ~CHAN_PEND; + /* From painful troubleshooting experience, servers that deny WHO also like + * to force joins, so let's make sure we have an internal record for the + * channel we just joined + */ + if (chan) { + chan->status |= CHAN_ACTIVE; + chan->status &= ~CHAN_PEND; + } } return 0; } From 7f71a379cf3afb7904921c8c5d7670e9e0be52eb Mon Sep 17 00:00:00 2001 From: Geo Date: Mon, 1 Jan 2024 19:47:43 -0500 Subject: [PATCH 08/11] remove redundant host splitting --- src/mod/irc.mod/chan.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index ec13998a7..b67010dae 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -1368,26 +1368,20 @@ static int got353(char *from, char *msg) if ((nick[0] == '+') || (nick[0] == '%')) { nick=nick+1; } - for (chan = chanset; chan; chan = chan->next) { - p = strchr(uhost, '@'); - if (p) { - *p = 0; - host = p+1; - } - if (uhost && host) { - got352or4(chan, uhost, host, nick, "", NULL); - } + p = strchr(uhost, '@'); + if (p) { + *p = 0; + host = p+1; + } + chan = findchan(chname); /* See if I'm on channel */ + if (chan && uhost && host) { + got352or4(chan, uhost, host, nick, "", NULL); } } /* The assumption here is the user enabled userhost-in-names because WHO * is disabled. We remove the pending flag here because we'll never get a * a WHO to do it */ - chan = findchan(chname); - /* From painful troubleshooting experience, servers that deny WHO also like - * to force joins, so let's make sure we have an internal record for the - * channel we just joined - */ if (chan) { chan->status |= CHAN_ACTIVE; chan->status &= ~CHAN_PEND; From eed19ed180a561ab9f32c7e0dd1f9c8b584bebe0 Mon Sep 17 00:00:00 2001 From: Geo Date: Fri, 19 Jan 2024 21:54:12 -0500 Subject: [PATCH 09/11] extract prefix chars, fixups --- src/mod/irc.mod/chan.c | 12 ++++++++---- src/mod/server.mod/isupport.c | 12 ++++++++++++ src/mod/server.mod/server.c | 6 ++++-- src/mod/server.mod/server.h | 4 ++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index b67010dae..a6d7f15a2 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -1336,7 +1336,7 @@ static int got354(char *from, char *msg) } /* got 353: NAMES - * 353 :[+/@]nick [+/@]nick .... + * 353 :[+/@]nick [+/@]nick .... * * if userhost-in-names is enabled, nick is nick@userhost.com * this function is added solely to handle userhost-in-names stuff, and will @@ -1344,15 +1344,18 @@ static int got354(char *from, char *msg) */ static int got353(char *from, char *msg) { + char prefixchars[64]; char *nameptr, *chname, *uhost, *nick, *p, *host; struct chanset_t *chan; int i; if (find_capability("userhost-in-names")) { + strlcpy(prefixchars, isupport_get_prefixchars(), sizeof prefixchars); newsplit(&msg); - newsplit(&msg); /* Get rid of =/@ prefix */ + newsplit(&msg); /* Get rid of =, @, or * symbol */ chname = newsplit(&msg); nameptr = newsplit(&msg); + fixcolon(nameptr); while ((uhost = newsplit(&nameptr))) { if (!strcmp(uhost, "")) { break; @@ -1360,8 +1363,8 @@ static int got353(char *from, char *msg) fixcolon(uhost); nick = splitnick(&uhost); /* Strip @, +, etc chars prefixed to nicks in NAMES */ - for (i = 0; opchars[i]; i++) { - if(nick[0] == opchars[i]) { + for (i = 0; prefixchars[i]; i++) { + if(nick[0] == prefixchars[i]) { nick=nick+1; } } @@ -1375,6 +1378,7 @@ static int got353(char *from, char *msg) } chan = findchan(chname); /* See if I'm on channel */ if (chan && uhost && host) { + /* Pretend we got a WHO and pass the info we got from NAMES */ got352or4(chan, uhost, host, nick, "", NULL); } } diff --git a/src/mod/server.mod/isupport.c b/src/mod/server.mod/isupport.c index d3d08ada7..e1d7ff83d 100644 --- a/src/mod/server.mod/isupport.c +++ b/src/mod/server.mod/isupport.c @@ -509,3 +509,15 @@ void isupport_report(int idx, const char *prefix, int details) } } +static const char *isupport_get_prefixchars(void) +{ + const char *str = isupport_get("PREFIX", strlen("PREFIX")); + + if (str) { + str = strchr(str, ')'); + if (str && str[1]) { + return str + 1; + } + } + return "+%@&~"; +} diff --git a/src/mod/server.mod/server.c b/src/mod/server.mod/server.c index f341d1901..56598cced 100644 --- a/src/mod/server.mod/server.c +++ b/src/mod/server.mod/server.c @@ -2242,11 +2242,13 @@ static Function server_table[] = { (Function) & account_notify, /* int */ (Function) & H_isupport, /* p_tcl_bind_list */ (Function) & isupport_get, /* */ - /* 48 - 52 */ + /* 48 - 51 */ (Function) & isupport_parseint,/* */ (Function) NULL, /* was check_tcl_account, now irc.mod */ (Function) & find_capability, - (Function) encode_msgtags + (Function) encode_msgtags, + /* 52 - 55 */ + (Function) isupport_get_prefixchars }; char *server_start(Function *global_funcs) diff --git a/src/mod/server.mod/server.h b/src/mod/server.mod/server.h index 93b525ab4..a8a71a1a6 100644 --- a/src/mod/server.mod/server.h +++ b/src/mod/server.mod/server.h @@ -98,6 +98,10 @@ /* #define check_tcl_account NULL */ #define find_capability ((struct capability *(*)(char *))(server_funcs[50])) #define encode_msgtags ((char *(*)(Tcl_Obj *))(server_funcs[51])) +/* 52 - 55 */ +#define isupport_get_prefixchars ((const char *(*)(void))server_funcs[52]) + + #endif /* MAKING_SERVER */ struct server_list { From 350cf9012e3a2014e6dd6d03f2f110d71e26c73e Mon Sep 17 00:00:00 2001 From: Geo Date: Fri, 19 Jan 2024 22:22:22 -0500 Subject: [PATCH 10/11] Fix missing H_monitor define --- src/mod/server.mod/server.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod/server.mod/server.h b/src/mod/server.mod/server.h index 9d6a3e2a6..ac81a5422 100644 --- a/src/mod/server.mod/server.h +++ b/src/mod/server.mod/server.h @@ -99,7 +99,8 @@ #define find_capability ((struct capability *(*)(char *))(server_funcs[50])) #define encode_msgtags ((char *(*)(Tcl_Obj *))(server_funcs[51])) /* 52 - 55 */ -#define isupport_get_prefixchars ((const char *(*)(void))server_funcs[52]) +#define H_monitor (*(p_tcl_bind_list *)(server_funcs[52])) +#define isupport_get_prefixchars ((const char *(*)(void))server_funcs[53]) #endif /* MAKING_SERVER */ From a9bef3faaee7ad1cfe41967a7609d713b393a461 Mon Sep 17 00:00:00 2001 From: Geo Date: Sat, 20 Jan 2024 09:30:35 -0500 Subject: [PATCH 11/11] fixup --- src/mod/irc.mod/chan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index 1911c8756..dda2fe2d8 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -1293,7 +1293,7 @@ static int got353(char *from, char *msg) host = p+1; } chan = findchan(chname); /* See if I'm on channel */ - if (chan && uhost && host) { + if (chan && host) { /* Pretend we got a WHO and pass the info we got from NAMES */ got352or4(chan, uhost, host, nick, "", NULL); }