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 }