unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

names.c (4897B)

      1 /*
      2  *   IRC - Internet Relay Chat, src/modules/names.c
      3  *   (C) 2006 The UnrealIRCd Team
      4  *
      5  *   See file AUTHORS in IRC package for additional names of
      6  *   the programmers.
      7  *
      8  *   This program is free software; you can redistribute it and/or modify
      9  *   it under the terms of the GNU General Public License as published by
     10  *   the Free Software Foundation; either version 1, or (at your option)
     11  *   any later version.
     12  *
     13  *   This program is distributed in the hope that it will be useful,
     14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *   GNU General Public License for more details.
     17  *
     18  *   You should have received a copy of the GNU General Public License
     19  *   along with this program; if not, write to the Free Software
     20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     21  */
     22 
     23 #include "unrealircd.h"
     24 
     25 CMD_FUNC(cmd_names);
     26 
     27 long CAP_MULTI_PREFIX = 0L;
     28 long CAP_USERHOST_IN_NAMES = 0L;
     29 
     30 #define MSG_NAMES 	"NAMES"
     31 
     32 ModuleHeader MOD_HEADER
     33   = {
     34 	"names",
     35 	"5.0",
     36 	"command /names", 
     37 	"UnrealIRCd Team",
     38 	"unrealircd-6",
     39     };
     40 
     41 MOD_INIT()
     42 {
     43 	ClientCapabilityInfo c;
     44 	memset(&c, 0, sizeof(c));
     45 	c.name = "multi-prefix";
     46 	ClientCapabilityAdd(modinfo->handle, &c, &CAP_MULTI_PREFIX);
     47 	memset(&c, 0, sizeof(c));
     48 	c.name = "userhost-in-names";
     49 	ClientCapabilityAdd(modinfo->handle, &c, &CAP_USERHOST_IN_NAMES);
     50 
     51 	CommandAdd(modinfo->handle, MSG_NAMES, cmd_names, MAXPARA, CMD_USER|CMD_SERVER);
     52 	MARK_AS_OFFICIAL_MODULE(modinfo);
     53 	return MOD_SUCCESS;
     54 }
     55 
     56 MOD_LOAD()
     57 {
     58 	return MOD_SUCCESS;
     59 }
     60 
     61 MOD_UNLOAD()
     62 {
     63 	return MOD_SUCCESS;
     64 }
     65 
     66 /************************************************************************
     67  * cmd_names() - Added by Jto 27 Apr 1989
     68  * 12 Feb 2000 - geesh, time for a rewrite -lucas
     69  ************************************************************************/
     70 
     71 /*
     72 ** cmd_names
     73 **	parv[1] = channel
     74 */
     75 #define TRUNCATED_NAMES 64
     76 CMD_FUNC(cmd_names)
     77 {
     78 	int multiprefix = (MyConnect(client) && HasCapabilityFast(client, CAP_MULTI_PREFIX));
     79 	int uhnames = (MyConnect(client) && HasCapabilityFast(client, CAP_USERHOST_IN_NAMES)); // cache UHNAMES support
     80 	int bufLen = NICKLEN + (!uhnames ? 0 : (1 + USERLEN + 1 + HOSTLEN));
     81 	int mlen = strlen(me.name) + bufLen + 7;
     82 	Channel *channel;
     83 	Client *acptr;
     84 	int member;
     85 	Member *cm;
     86 	int idx, flag = 1, spos;
     87 	const char *para = parv[1], *s;
     88 	char nuhBuffer[NICKLEN+USERLEN+HOSTLEN+3];
     89 	char buf[BUFSIZE];
     90 
     91 	if (parc < 2 || !MyConnect(client))
     92 	{
     93 		sendnumeric(client, RPL_ENDOFNAMES, "*");
     94 		return;
     95 	}
     96 
     97 	for (s = para; *s; s++)
     98 	{
     99 		if (*s == ',')
    100 		{
    101 			sendnumeric(client, ERR_TOOMANYTARGETS, s+1, 1, "NAMES");
    102 			return;
    103 		}
    104 	}
    105 
    106 	channel = find_channel(para);
    107 
    108 	if (!channel || (!ShowChannel(client, channel) && !ValidatePermissionsForPath("channel:see:names:secret",client,NULL,channel,NULL)))
    109 	{
    110 		sendnumeric(client, RPL_ENDOFNAMES, para);
    111 		return;
    112 	}
    113 
    114 	/* cache whether this user is a member of this channel or not */
    115 	member = IsMember(client, channel);
    116 
    117 	// FIXME: consider rewriting this whole thing to get rid of pointer juggling and stuff.
    118 
    119 	if (PubChannel(channel))
    120 		buf[0] = '=';
    121 	else if (SecretChannel(channel))
    122 		buf[0] = '@';
    123 	else
    124 		buf[0] = '*';
    125 
    126 	idx = 1;
    127 	buf[idx++] = ' ';
    128 	for (s = channel->name; *s; s++)
    129 		buf[idx++] = *s;
    130 	buf[idx++] = ' ';
    131 	buf[idx++] = ':';
    132 
    133 	/* If we go through the following loop and never add anything,
    134 	   we need this to be empty, otherwise spurious things from the
    135 	   LAST /names call get stuck in there.. - lucas */
    136 	buf[idx] = '\0';
    137 
    138 	spos = idx;		/* starting point in buffer for names! */
    139 
    140 	for (cm = channel->members; cm; cm = cm->next)
    141 	{
    142 		acptr = cm->client;
    143 		if (IsInvisible(acptr) && !member && !ValidatePermissionsForPath("channel:see:names:invisible",client,acptr,channel,NULL))
    144 			continue;
    145 
    146 		if (!user_can_see_member(client, acptr, channel))
    147 			continue; /* invisible (eg: due to delayjoin) */
    148 
    149 		if (!multiprefix)
    150 		{
    151 			/* Standard NAMES reply (single character) */
    152 			char c = mode_to_prefix(*cm->member_modes);
    153 			if (c)
    154 				buf[idx++] = c;
    155 		} else {
    156 			/* NAMES reply with all rights included (multi-prefix / NAMESX) */
    157 			strcpy(&buf[idx], modes_to_prefix(cm->member_modes));
    158 			idx += strlen(&buf[idx]);
    159 		}
    160 
    161 		if (!uhnames) {
    162 			s = acptr->name;
    163 		} else {
    164 			strlcpy(nuhBuffer,
    165 			        make_nick_user_host(acptr->name, acptr->user->username, GetHost(acptr)),
    166 				bufLen + 1);
    167 			s = nuhBuffer;
    168 		}
    169 		/* 's' is intialized above to point to either acptr->name (normal),
    170 		 * or to nuhBuffer (for UHNAMES).
    171 		 */
    172 		for (; *s; s++)
    173 			buf[idx++] = *s;
    174 		if (cm->next)
    175 			buf[idx++] = ' ';
    176 		buf[idx] = '\0';
    177 		flag = 1;
    178 		if (mlen + idx + bufLen + MEMBERMODESLEN >= BUFSIZE - 1)
    179 		{
    180 			sendnumeric(client, RPL_NAMREPLY, buf);
    181 			idx = spos;
    182 			flag = 0;
    183 		}
    184 	}
    185 
    186 	if (flag)
    187 		sendnumeric(client, RPL_NAMREPLY, buf);
    188 
    189 	sendnumeric(client, RPL_ENDOFNAMES, para);
    190 }