X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fnumeric.c;h=7d32ddc933fd5fd132e4efbf74defa1c961d3fd3;hp=0dcfe75b6e3d9c0bca6ad9d7b7a0ead4876aaa74;hb=9a931a549b7e1b0979ce5f6088edf5136546f3ed;hpb=5462c6c50fd01fd516e29a42ee0b15c946c11d27 diff --git a/src/ngircd/numeric.c b/src/ngircd/numeric.c index 0dcfe75b..7d32ddc9 100644 --- a/src/ngircd/numeric.c +++ b/src/ngircd/numeric.c @@ -1,40 +1,38 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. - * - * Handlers for IRC numerics sent to the server */ #include "portab.h" -#include "imp.h" +/** + * @file + * Handlers for IRC numerics sent to the server + */ + #include #include #include #include +#include -#include "defines.h" -#include "conn.h" -#include "conf.h" -#include "conn.h" #include "conn-func.h" +#include "conf.h" #include "channel.h" +#include "class.h" #include "irc-write.h" #include "lists.h" #include "log.h" -#include "messages.h" #include "parse.h" -#include "exp.h" #include "numeric.h" - /** * Announce a channel and its users in the network. */ @@ -43,13 +41,12 @@ Announce_Channel(CLIENT *Client, CHANNEL *Chan) { CL2CHAN *cl2chan; CLIENT *cl; - char str[LINE_LEN], *ptr; - bool njoin; + char str[COMMAND_LEN], *ptr; + bool njoin, xop; - if (Conn_Options(Client_Conn(Client)) & CONN_RFC1459) - njoin = false; - else - njoin = true; + /* Check features of remote server */ + njoin = Conn_Options(Client_Conn(Client)) & CONN_RFC1459 ? false : true; + xop = Client_HasFlag(Client, 'X') ? true : false; /* Get all the members of this channel */ cl2chan = Channel_FirstMember(Chan); @@ -59,18 +56,27 @@ Announce_Channel(CLIENT *Client, CHANNEL *Chan) assert(cl != NULL); if (njoin) { - /* RFC 2813: send NJOIN with nick names and modes + /* RFC 2813: send NJOIN with nicknames 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')) + + /* Prepare user prefix (ChanOp, voiced, ...) */ + if (xop && Channel_UserHasMode(Chan, cl, 'q')) + strlcat(str, "~", sizeof(str)); + if (xop && Channel_UserHasMode(Chan, cl, 'a')) + strlcat(str, "&", sizeof(str)); + if (Channel_UserHasMode(Chan, cl, 'o')) strlcat(str, "@", sizeof(str)); + if (xop && Channel_UserHasMode(Chan, cl, 'h')) + strlcat(str, "%", sizeof(str)); + if (Channel_UserHasMode(Chan, cl, 'v')) + 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 (strlen(str) > (sizeof(str) - CLIENT_NICK_LEN - 8)) { if (!IRC_WriteStrClient(Client, "%s", str)) return DISCONNECTED; snprintf(str, sizeof(str), "NJOIN %s :", @@ -105,7 +111,6 @@ Announce_Channel(CLIENT *Client, CHANNEL *Chan) return CONNECTED; } /* Announce_Channel */ - /** * Announce new server in the network * @param Client New server @@ -137,62 +142,33 @@ Announce_Server(CLIENT * Client, CLIENT * Server) Client_MyToken(Server), Client_Info(Server)); } /* Announce_Server */ +#ifdef IRCPLUS /** - * Announce existing user to a new server - * @param Client New server - * @param User Existing user in the network + * Send a specific list to a remote server. */ static bool -Announce_User(CLIENT * Client, CLIENT * User) +Send_List(CLIENT *Client, CHANNEL *Chan, struct list_head *Head, char Type) { - 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; - 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))) + struct list_elem *elem; + + elem = Lists_GetFirst(Head); + while (elem) { + if (!IRC_WriteStrClient(Client, "MODE %s +%c %s", + Channel_Name(Chan), Type, + Lists_GetMask(elem))) { 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 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)), - Client_Modes(User), Client_Info(User)); + elem = Lists_GetNext(elem); } -} /* Announce_User */ - - -#ifdef IRCPLUS + return CONNECTED; +} /** - * Synchronize invite and ban lists between servers - * @param Client New server + * Synchronize invite, ban, except, and G-Line lists between servers. + * + * @param Client New server. + * @return CONNECTED or DISCONNECTED. */ static bool Synchronize_Lists(CLIENT * Client) @@ -203,38 +179,31 @@ Synchronize_Lists(CLIENT * Client) assert(Client != NULL); + /* g-lines */ + head = Class_GetList(CLASS_GLINE); + elem = Lists_GetFirst(head); + while (elem) { + if (!IRC_WriteStrClient(Client, "GLINE %s %ld :%s", + Lists_GetMask(elem), + Lists_GetValidity(elem) - time(NULL), + Lists_GetReason(elem))) + return DISCONNECTED; + elem = Lists_GetNext(elem); + } + c = Channel_First(); while (c) { - /* ban list */ - head = Channel_GetListBans(c); - elem = Lists_GetFirst(head); - while (elem) { - if (!IRC_WriteStrClient(Client, "MODE %s +b %s", - Channel_Name(c), - Lists_GetMask(elem))) { - return DISCONNECTED; - } - elem = Lists_GetNext(elem); - } - - /* invite list */ - head = Channel_GetListInvites(c); - elem = Lists_GetFirst(head); - while (elem) { - if (!IRC_WriteStrClient(Client, "MODE %s +I %s", - Channel_Name(c), - Lists_GetMask(elem))) { - return DISCONNECTED; - } - elem = Lists_GetNext(elem); - } - + if (!Send_List(Client, c, Channel_GetListExcepts(c), 'e')) + return DISCONNECTED; + if (!Send_List(Client, c, Channel_GetListBans(c), 'b')) + return DISCONNECTED; + if (!Send_List(Client, c, Channel_GetListInvites(c), 'I')) + return DISCONNECTED; c = Channel_Next(c); } return CONNECTED; } - /** * Send CHANINFO commands to a new server (inform it about existing channels). * @param Client New server @@ -247,7 +216,8 @@ Send_CHANINFO(CLIENT * Client, CHANNEL * Chan) bool has_k, has_l; #ifdef DEBUG - Log(LOG_DEBUG, "Sending CHANINFO commands ..."); + Log(LOG_DEBUG, "Sending CHANINFO commands for \"%s\" ...", + Channel_Name(Chan)); #endif modes = Channel_Modes(Chan); @@ -256,8 +226,8 @@ Send_CHANINFO(CLIENT * Client, CHANNEL * Chan) if (!*modes && !*topic) return CONNECTED; - has_k = strchr(modes, 'k') != NULL; - has_l = strchr(modes, 'l') != NULL; + has_k = Channel_HasMode(Chan, 'k'); + has_l = Channel_HasMode(Chan, 'l'); /* send CHANINFO */ if (!has_k && !has_l) { @@ -279,7 +249,6 @@ Send_CHANINFO(CLIENT * Client, CHANNEL * Chan) #endif /* IRCPLUS */ - /** * Handle ENDOFMOTD (376) numeric and login remote server. * The peer is either an IRC server (no IRC+ protocol), or we got the @@ -330,7 +299,7 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req) while (c) { if (Client_Type(c) == CLIENT_USER || Client_Type(c) == CLIENT_SERVICE) { - if (!Announce_User(Client, c)) + if (!Client_Announce(Client, Client_ThisServer(), c)) return DISCONNECTED; } c = Client_Next(c); @@ -345,7 +314,7 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req) } #ifdef IRCPLUS /* Send CHANINFO if the peer supports it */ - if (strchr(Client_Flags(Client), 'C')) { + if (Client_HasFlag(Client, 'C')) { if (!Send_CHANINFO(Client, chan)) return DISCONNECTED; } @@ -359,17 +328,20 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req) } #ifdef IRCPLUS - if (strchr(Client_Flags(Client), 'L')) { + if (Client_HasFlag(Client, 'L')) { LogDebug("Synchronizing INVITE- and BAN-lists ..."); if (!Synchronize_Lists(Client)) return DISCONNECTED; } #endif + if (!IRC_WriteStrClient(Client, "PING :%s", + Client_ID(Client_ThisServer()))) + return DISCONNECTED; + return CONNECTED; } /* IRC_Num_ENDOFMOTD */ - /** * Handle ISUPPORT (005) numeric. */ @@ -391,12 +363,12 @@ IRC_Num_ISUPPORT(CLIENT * Client, REQUEST * Req) if ((unsigned int)atol(value) == Conf_MaxNickLength - 1) continue; - /* Nick name length settings are different! */ + /* Nickname length settings are different! */ Log(LOG_ERR, - "Peer uses incompatible nick name length (%d/%d)! Disconnecting ...", + "Peer uses incompatible nickname length (%d/%d)! Disconnecting ...", Conf_MaxNickLength - 1, atoi(value)); Conn_Close(Client_Conn(Client), - "Incompatible nick name length", + "Incompatible nickname length", NULL, false); return DISCONNECTED; } @@ -405,5 +377,4 @@ IRC_Num_ISUPPORT(CLIENT * Client, REQUEST * Req) return CONNECTED; } /* IRC_Num_ISUPPORT */ - /* -eof- */