X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fnumeric.c;h=0dcfe75b6e3d9c0bca6ad9d7b7a0ead4876aaa74;hp=d22bf3ae348c3b2ebeccf63dc3fbad1e5f3d56a0;hb=76f40bdb988440a73431eb14a27f30aeaa18ebe5;hpb=a60465be3ec6e6960a981c5e2c21846839359653 diff --git a/src/ngircd/numeric.c b/src/ngircd/numeric.c index d22bf3ae..0dcfe75b 100644 --- a/src/ngircd/numeric.c +++ b/src/ngircd/numeric.c @@ -20,12 +20,10 @@ #include #include "defines.h" -#include "resolve.h" #include "conn.h" #include "conf.h" #include "conn.h" #include "conn-func.h" -#include "client.h" #include "channel.h" #include "irc-write.h" #include "lists.h" @@ -37,6 +35,77 @@ #include "numeric.h" +/** + * Announce a channel and its users in the network. + */ +static bool +Announce_Channel(CLIENT *Client, CHANNEL *Chan) +{ + CL2CHAN *cl2chan; + CLIENT *cl; + char str[LINE_LEN], *ptr; + bool njoin; + + if (Conn_Options(Client_Conn(Client)) & CONN_RFC1459) + njoin = false; + else + njoin = true; + + /* Get all the members of this channel */ + cl2chan = Channel_FirstMember(Chan); + snprintf(str, sizeof(str), "NJOIN %s :", Channel_Name(Chan)); + while (cl2chan) { + cl = Channel_GetClient(cl2chan); + assert(cl != NULL); + + if (njoin) { + /* RFC 2813: send NJOIN with nick names and modes + * (if user is channel operator or has voice) */ + if (str[strlen(str) - 1] != ':') + strlcat(str, ",", sizeof(str)); + if (strchr(Channel_UserModes(Chan, cl), 'v')) + strlcat(str, "+", sizeof(str)); + if (strchr(Channel_UserModes(Chan, cl), 'o')) + strlcat(str, "@", sizeof(str)); + strlcat(str, Client_ID(cl), sizeof(str)); + + /* Send the data if the buffer is "full" */ + if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 8)) { + if (!IRC_WriteStrClient(Client, "%s", str)) + return DISCONNECTED; + snprintf(str, sizeof(str), "NJOIN %s :", + Channel_Name(Chan)); + } + } else { + /* RFC 1459: no NJOIN, send JOIN and MODE */ + if (!IRC_WriteStrClientPrefix(Client, cl, "JOIN %s", + Channel_Name(Chan))) + return DISCONNECTED; + ptr = Channel_UserModes(Chan, cl); + while (*ptr) { + if (!IRC_WriteStrClientPrefix(Client, cl, + "MODE %s +%c %s", + Channel_Name(Chan), ptr[0], + Client_ID(cl))) + return DISCONNECTED; + ptr++; + } + } + + cl2chan = Channel_NextMember(Chan, cl2chan); + } + + /* Data left in the buffer? */ + if (str[strlen(str) - 1] != ':') { + /* Yes, send it ... */ + if (!IRC_WriteStrClient(Client, "%s", str)) + return DISCONNECTED; + } + + return CONNECTED; +} /* Announce_Channel */ + + /** * Announce new server in the network * @param Client New server @@ -60,7 +129,7 @@ Announce_Server(CLIENT * Client, CLIENT * Server) if (Client_Hops(Server) == 1) c = Client_ThisServer(); else - c = Client_Introducer(Server); + c = Client_TopServer(Server); /* Inform new server about the one already registered in the network */ return IRC_WriteStrClientPrefix(Client, c, "SERVER %s %d %d :%s", @@ -78,21 +147,39 @@ static bool Announce_User(CLIENT * Client, CLIENT * User) { CONN_ID conn; + char *modes; + conn = Client_Conn(Client); if (Conn_Options(conn) & CONN_RFC1459) { /* RFC 1459 mode: separate NICK and USER commands */ if (! Conn_WriteStr(conn, "NICK %s :%d", Client_ID(User), Client_Hops(User) + 1)) return DISCONNECTED; - return Conn_WriteStr(conn, ":%s USER %s %s %s :%s", + if (! Conn_WriteStr(conn, ":%s USER %s %s %s :%s", Client_ID(User), Client_User(User), Client_Hostname(User), Client_ID(Client_Introducer(User)), - Client_Info(User)); - + Client_Info(User))) + return DISCONNECTED; + modes = Client_Modes(User); + if (modes[0]) { + return Conn_WriteStr(conn, ":%s MODE %s +%s", + Client_ID(User), Client_ID(User), + modes); + } + return CONNECTED; } else { - /* RFC 2813 mode: one combined NICK command */ - return IRC_WriteStrClient(Client, "NICK %s %d %s %s %d +%s :%s", + /* RFC 2813 mode: one combined NICK or SERVICE command */ + if (Client_Type(User) == CLIENT_SERVICE + && strchr(Client_Flags(Client), 'S')) + return IRC_WriteStrClient(Client, + "SERVICE %s %d * +%s %d :%s", Client_Mask(User), + Client_MyToken(Client_Introducer(User)), + Client_Modes(User), Client_Hops(User) + 1, + Client_Info(User)); + else + return IRC_WriteStrClient(Client, + "NICK %s %d %s %s %d +%s :%s", Client_ID(User), Client_Hops(User) + 1, Client_User(User), Client_Hostname(User), Client_MyToken(Client_Introducer(User)), @@ -158,20 +245,20 @@ Send_CHANINFO(CLIENT * Client, CHANNEL * Chan) { char *modes, *topic; bool has_k, has_l; - + #ifdef DEBUG Log(LOG_DEBUG, "Sending CHANINFO commands ..."); #endif - + modes = Channel_Modes(Chan); topic = Channel_Topic(Chan); - + if (!*modes && !*topic) return CONNECTED; - + has_k = strchr(modes, 'k') != NULL; has_l = strchr(modes, 'l') != NULL; - + /* send CHANINFO */ if (!has_k && !has_l) { if (!*topic) { @@ -201,11 +288,9 @@ Send_CHANINFO(CLIENT * Client, CHANNEL * Chan) GLOBAL bool IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req) { - char str[LINE_LEN]; int max_hops, i; - CLIENT *c, *cl; + CLIENT *c; CHANNEL *chan; - CL2CHAN *cl2chan; Client_SetType(Client, CLIENT_SERVER); @@ -243,7 +328,8 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req) /* Announce all the users to the new server */ c = Client_First(); while (c) { - if (Client_Type(c) == CLIENT_USER) { + if (Client_Type(c) == CLIENT_USER || + Client_Type(c) == CLIENT_SERVICE) { if (!Announce_User(Client, c)) return DISCONNECTED; } @@ -253,6 +339,10 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req) /* Announce all channels to the new server */ chan = Channel_First(); while (chan) { + if (Channel_IsLocal(chan)) { + chan = Channel_Next(chan); + continue; + } #ifdef IRCPLUS /* Send CHANINFO if the peer supports it */ if (strchr(Client_Flags(Client), 'C')) { @@ -261,39 +351,8 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req) } #endif - /* Get all the members of this channel */ - cl2chan = Channel_FirstMember(chan); - snprintf(str, sizeof(str), "NJOIN %s :", Channel_Name(chan)); - while (cl2chan) { - cl = Channel_GetClient(cl2chan); - assert(cl != NULL); - - /* Nick name, with modes (if applicable) */ - if (str[strlen(str) - 1] != ':') - strlcat(str, ",", sizeof(str)); - if (strchr(Channel_UserModes(chan, cl), 'v')) - strlcat(str, "+", sizeof(str)); - if (strchr(Channel_UserModes(chan, cl), 'o')) - strlcat(str, "@", sizeof(str)); - strlcat(str, Client_ID(cl), sizeof(str)); - - /* Send the data if the buffer is "full" */ - if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 8)) { - if (!IRC_WriteStrClient(Client, "%s", str)) - return DISCONNECTED; - snprintf(str, sizeof(str), "NJOIN %s :", - Channel_Name(chan)); - } - - cl2chan = Channel_NextMember(chan, cl2chan); - } - - /* Data left in the buffer? */ - if (str[strlen(str) - 1] != ':') { - /* Yes, send it ... */ - if (!IRC_WriteStrClient(Client, "%s", str)) - return DISCONNECTED; - } + if (!Announce_Channel(Client, chan)) + return DISCONNECTED; /* Get next channel ... */ chan = Channel_Next(chan);