diff --git a/doc/sphinx_source/using/ircv3.rst b/doc/sphinx_source/using/ircv3.rst index c2fff5299..8ed8e5afa 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 -Copyright (C) 2010 - 2024 Eggheads Development Team +------ +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 - 2024 Eggheads Development Team \ No newline at end of file diff --git a/src/mod/irc.mod/chan.c b/src/mod/irc.mod/chan.c index 46aa48190..dda2fe2d8 100644 --- a/src/mod/irc.mod/chan.c +++ b/src/mod/irc.mod/chan.c @@ -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 @@ -1251,6 +1251,65 @@ static int gotchghost(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 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 =, @, or * symbol */ + chname = newsplit(&msg); + nameptr = newsplit(&msg); + fixcolon(nameptr); + while ((uhost = newsplit(&nameptr))) { + if (!strcmp(uhost, "")) { + break; + } + fixcolon(uhost); + nick = splitnick(&uhost); + /* Strip @, +, etc chars prefixed to nicks in NAMES */ + for (i = 0; prefixchars[i]; i++) { + if(nick[0] == prefixchars[i]) { + nick=nick+1; + } + } + if ((nick[0] == '+') || (nick[0] == '%')) { + nick=nick+1; + } + p = strchr(uhost, '@'); + if (p) { + *p = 0; + host = p+1; + } + chan = findchan(chname); /* See if I'm on channel */ + if (chan && host) { + /* Pretend we got a WHO and pass the info we got from NAMES */ + 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 + */ + if (chan) { + chan->status |= CHAN_ACTIVE; + chan->status &= ~CHAN_PEND; + } + } + 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.) @@ -2820,6 +2879,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"}, diff --git a/src/mod/server.mod/isupport.c b/src/mod/server.mod/isupport.c index 61636fc26..0ad50614f 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 907656c7f..80d0ad5f1 100644 --- a/src/mod/server.mod/server.c +++ b/src/mod/server.mod/server.c @@ -2385,7 +2385,8 @@ static Function server_table[] = { (Function) & find_capability, (Function) encode_msgtags, /* 52 - 55 */ - (Function) & H_monitor + (Function) & H_monitor, + (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 7764c6228..ac81a5422 100644 --- a/src/mod/server.mod/server.h +++ b/src/mod/server.mod/server.h @@ -98,6 +98,11 @@ /* #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 H_monitor (*(p_tcl_bind_list *)(server_funcs[52])) +#define isupport_get_prefixchars ((const char *(*)(void))server_funcs[53]) + + #endif /* MAKING_SERVER */ struct server_list {