X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Firc-info.c;h=e38d5bb6f3338629f35cc2e22b7ef46bb08f6e15;hp=f1d02711b35cfba3de103bfa836c366a40ad21c8;hb=HEAD;hpb=344185b1bd6254ac4a198b3caeaf08db285016c8 diff --git a/src/ngircd/irc-info.c b/src/ngircd/irc-info.c index f1d02711..7287f3ca 100644 --- a/src/ngircd/irc-info.c +++ b/src/ngircd/irc-info.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. + * 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 @@ -16,13 +16,12 @@ * IRC info commands */ -#include "imp.h" #include -#include #include #include #include #include +#include #include "ngircd.h" #include "conn-func.h" @@ -30,12 +29,9 @@ #include "channel.h" #include "class.h" #include "conf.h" -#include "defines.h" #include "lists.h" -#include "log.h" #include "messages.h" #include "match.h" -#include "tool.h" #include "parse.h" #include "irc.h" #include "irc-macros.h" @@ -43,7 +39,6 @@ #include "client-cap.h" #include "op.h" -#include "exp.h" #include "irc-info.h" /* Local functions */ @@ -143,7 +138,7 @@ who_flags_qualifier(CLIENT *Client, const char *chan_user_modes, static bool IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) { - bool is_visible, is_member, is_ircop; + bool is_visible, is_member, is_ircop, is_oper; CL2CHAN *cl2chan; char flags[10]; CLIENT *c; @@ -153,9 +148,10 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) assert( Chan != NULL ); is_member = Channel_IsMemberOf(Chan, Client); + is_oper = Client_HasMode(Client, 'o'); /* Secret channel? */ - if (!is_member && Channel_HasMode(Chan, 's')) + if (!is_member && !is_oper && Channel_HasMode(Chan, 's')) return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan)); @@ -167,8 +163,8 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) if (OnlyOps && !is_ircop) continue; - is_visible = Client_HasMode(c, 'i'); - if (is_member || is_visible) { + is_visible = !Client_HasMode(c, 'i'); + if (is_member || is_visible || is_oper) { memset(flags, 0, sizeof(flags)); if (Client_HasMode(c, 'a')) @@ -189,7 +185,7 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) } } - /* If there are a lot of clients, augment penalty a bit */ + /* If there are a lot of clients, increase the penalty a bit */ if (count > MAX_RPL_WHO) IRC_SetPenalty(Client, 1); @@ -318,48 +314,50 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) Client_Info(Client_Introducer(c)))) return DISCONNECTED; - /* Channels */ - snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG, - Client_ID(from), Client_ID(c)); - cl2chan = Channel_FirstChannelOf(c); - while (cl2chan) { - chan = Channel_GetChannel(cl2chan); - assert(chan != NULL); - - /* next */ - cl2chan = Channel_NextChannelOf(c, cl2chan); - - /* Secret channel? */ - if (Channel_HasMode(chan, 's') - && !Channel_IsMemberOf(chan, Client)) - continue; + /* Channels, show only if client has no +I or if from is oper */ + if(!(Client_HasMode(c, 'I')) || Client_HasMode(from, 'o')) { + snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG, + Client_ID(from), Client_ID(c)); + cl2chan = Channel_FirstChannelOf(c); + while (cl2chan) { + chan = Channel_GetChannel(cl2chan); + assert(chan != NULL); + + /* next */ + cl2chan = Channel_NextChannelOf(c, cl2chan); + + /* Secret channel? */ + if (Channel_HasMode(chan, 's') + && !Channel_IsMemberOf(chan, Client)) + continue; - /* Local channel and request is not from a user? */ - if (Client_Type(Client) == CLIENT_SERVER - && Channel_IsLocal(chan)) - continue; + /* Local channel and request is not from a user? */ + if (Client_Type(Client) == CLIENT_SERVER + && Channel_IsLocal(chan)) + continue; - /* Concatenate channel names */ - if (str[strlen(str) - 1] != ':') - strlcat(str, " ", sizeof(str)); + /* Concatenate channel names */ + if (str[strlen(str) - 1] != ':') + strlcat(str, " ", sizeof(str)); - who_flags_qualifier(Client, Channel_UserModes(chan, c), - str, sizeof(str)); - strlcat(str, Channel_Name(chan), sizeof(str)); + who_flags_qualifier(Client, Channel_UserModes(chan, c), + str, sizeof(str)); + strlcat(str, Channel_Name(chan), sizeof(str)); - if (strlen(str) > (COMMAND_LEN - CHANNEL_NAME_LEN - 4)) { - /* Line becomes too long: send it! */ + if (strlen(str) > (COMMAND_LEN - CHANNEL_NAME_LEN - 4)) { + /* Line becomes too long: send it! */ + if (!IRC_WriteStrClient(Client, "%s", str)) + return DISCONNECTED; + snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG, + Client_ID(from), Client_ID(c)); + } + } + if(str[strlen(str) - 1] != ':') { + /* There is data left to send: */ if (!IRC_WriteStrClient(Client, "%s", str)) return DISCONNECTED; - snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG, - Client_ID(from), Client_ID(c)); } } - if(str[strlen(str) - 1] != ':') { - /* There is data left to send: */ - if (!IRC_WriteStrClient(Client, "%s", str)) - return DISCONNECTED; - } /* IRC-Services? */ if (Client_Type(c) == CLIENT_SERVICE && @@ -401,9 +399,16 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) Client_ID(from), Client_ID(c))) return DISCONNECTED; + /* Account name metadata? */ + if (Client_AccountName(c) && + !IRC_WriteStrClient(from, RPL_WHOISLOGGEDIN_MSG, + Client_ID(from), Client_ID(c), + Client_AccountName(c))) + return DISCONNECTED; + /* Local client and requester is the user itself or an IRC Op? */ if (Client_Conn(c) > NONE && - (from == c || (!Conf_MorePrivacy && Client_HasMode(from, 'o')))) { + (from == c || Client_HasMode(from, 'o'))) { /* Client hostname */ if (!IRC_WriteStrClient(from, RPL_WHOISHOST_MSG, Client_ID(from), Client_ID(c), @@ -554,7 +559,15 @@ IRC_INFO(CLIENT * Client, REQUEST * Req) NGIRCd_Version)) return DISCONNECTED; -#if defined(__DATE__) && defined(__TIME__) +#if defined(BIRTHDATE) + char t_str[60]; + time_t t = BIRTHDATE; + (void)strftime(t_str, sizeof(t_str), "%a %b %d %Y at %H:%M:%S (%Z)", + localtime(&t)); + snprintf(msg, sizeof(msg), "Birth Date: %s", t_str); + if (!IRC_WriteStrClient(Client, RPL_INFO_MSG, Client_ID(prefix), msg)) + return DISCONNECTED; +#elif defined(__DATE__) && defined(__TIME__) snprintf(msg, sizeof(msg), "Birth Date: %s at %s", __DATE__, __TIME__); if (!IRC_WriteStrClient(Client, RPL_INFO_MSG, Client_ID(prefix), msg)) return DISCONNECTED; @@ -805,7 +818,7 @@ IRC_NAMES( CLIENT *Client, REQUEST *Req ) /* Now print all clients which are not in any channel */ c = Client_First(); - snprintf(rpl, sizeof(rpl), RPL_NAMREPLY_MSG, Client_ID(from), "*", "*"); + snprintf(rpl, sizeof(rpl), RPL_NAMREPLY_MSG, Client_ID(from), '*', "*"); while (c) { if (Client_Type(c) == CLIENT_USER && Channel_FirstChannelOf(c) == NULL @@ -817,11 +830,11 @@ IRC_NAMES( CLIENT *Client, REQUEST *Req ) strlcat(rpl, Client_ID(c), sizeof(rpl)); if (strlen(rpl) > COMMAND_LEN - CLIENT_NICK_LEN - 4) { - /* Line is gwoing too long, send now */ + /* Line is going too long, send now */ if (!IRC_WriteStrClient(from, "%s", rpl)) return DISCONNECTED; snprintf(rpl, sizeof(rpl), RPL_NAMREPLY_MSG, - Client_ID(from), "*", "*"); + Client_ID(from), '*', "*"); } } c = Client_Next(c); @@ -882,22 +895,22 @@ IRC_STATS( CLIENT *Client, REQUEST *Req ) list = Class_GetList(CLASS_GLINE); else list = Class_GetList(CLASS_KLINE); - list_item = Lists_GetFirst(list); - while (list_item) { - if (!IRC_WriteStrClient(from, RPL_STATSXLINE_MSG, + list_item = Lists_GetFirst(list); + while (list_item) { + if (!IRC_WriteStrClient(from, RPL_STATSXLINE_MSG, Client_ID(from), query, Lists_GetMask(list_item), Lists_GetValidity(list_item), Lists_GetReason(list_item))) - return DISCONNECTED; - list_item = Lists_GetNext(list_item); - } + return DISCONNECTED; + list_item = Lists_GetNext(list_item); + } break; case 'L': /* Link status (servers and user links) */ if (!Op_Check(from, Req)) return Op_NoPrivileges(from, Req); more_links = true; - + /* fall through */ case 'l': /* Link status (servers and own link) */ time_now = time(NULL); for (con = Conn_First(); con != NONE; con = Conn_Next(con)) { @@ -1099,10 +1112,19 @@ IRC_VERSION( CLIENT *Client, REQUEST *Req ) } /* send version information */ - return IRC_WriteStrClient(Client, RPL_VERSION_MSG, Client_ID(prefix), - PACKAGE_NAME, PACKAGE_VERSION, - NGIRCd_DebugLevel, Conf_ServerName, - NGIRCd_VersionAddition); + if (!IRC_WriteStrClient(Client, RPL_VERSION_MSG, Client_ID(prefix), + PACKAGE_NAME, PACKAGE_VERSION, + NGIRCd_DebugLevel, Conf_ServerName, + NGIRCd_VersionAddition)) + return DISCONNECTED; + +#ifndef STRICT_RFC + /* send RPL_ISUPPORT(005) numerics */ + if (!IRC_Send_ISUPPORT(prefix)) + return DISCONNECTED; +#endif + + return CONNECTED; } /* IRC_VERSION */ /** @@ -1233,6 +1255,7 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req ) continue; } got_wildcard = true; + /* Increase penalty for wildcard queries */ IRC_SetPenalty(Client, 3); for (c = Client_First(); c; c = Client_Next(c)) { @@ -1242,6 +1265,8 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req ) if (Client_Type(c) != CLIENT_USER) continue; + if (Client_HasMode(c, 'i')) + continue; if (!MatchCaseInsensitive(query, Client_ID(c))) continue; if (!IRC_WHOIS_SendReply(Client, from, c)) @@ -1350,7 +1375,7 @@ IRC_WHOWAS( CLIENT *Client, REQUEST *Req ) /** * Send LUSERS reply to a client. * - * @param Client The receipient of the information. + * @param Client The recipient of the information. * @return CONNECTED or DISCONNECTED. */ GLOBAL bool @@ -1475,6 +1500,8 @@ IRC_Send_NAMES(CLIENT * Client, CHANNEL * Chan) char str[COMMAND_LEN]; CL2CHAN *cl2chan; CLIENT *cl; + bool secret_channel; + char chan_symbol; assert(Client != NULL); assert(Chan != NULL); @@ -1489,10 +1516,13 @@ IRC_Send_NAMES(CLIENT * Client, CHANNEL * Chan) return CONNECTED; /* Secret channel? */ - if (!is_member && Channel_HasMode(Chan, 's')) + secret_channel = Channel_HasMode(Chan, 's'); + if (!is_member && secret_channel) return CONNECTED; - snprintf(str, sizeof(str), RPL_NAMREPLY_MSG, Client_ID(Client), "=", + chan_symbol = secret_channel ? '@' : '='; + + snprintf(str, sizeof(str), RPL_NAMREPLY_MSG, Client_ID(Client), chan_symbol, Channel_Name(Chan)); cl2chan = Channel_FirstMember(Chan); while (cl2chan) { @@ -1515,7 +1545,7 @@ IRC_Send_NAMES(CLIENT * Client, CHANNEL * Chan) if (!IRC_WriteStrClient(Client, "%s", str)) return DISCONNECTED; snprintf(str, sizeof(str), RPL_NAMREPLY_MSG, - Client_ID(Client), "=", + Client_ID(Client), chan_symbol, Channel_Name(Chan)); } } @@ -1538,6 +1568,10 @@ IRC_Send_NAMES(CLIENT * Client, CHANNEL * Chan) GLOBAL bool IRC_Send_ISUPPORT(CLIENT * Client) { + if (Conf_Network[0] && !IRC_WriteStrClient(Client, RPL_ISUPPORTNET_MSG, + Client_ID(Client), + Conf_Network)) + return DISCONNECTED; if (!IRC_WriteStrClient(Client, RPL_ISUPPORT1_MSG, Client_ID(Client), CHANTYPES, CHANTYPES, Conf_MaxJoins)) return DISCONNECTED;