1 /*
2 * IRC - Internet Relay Chat, src/modules/m_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 #include "config.h"
23 #include "struct.h"
24 #include "common.h"
25 #include "sys.h"
26 #include "numeric.h"
27 #include "msg.h"
28 #include "proto.h"
29 #include "channel.h"
30 #include <time.h>
31 #include <sys/stat.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #ifdef _WIN32
36 #include <io.h>
37 #endif
38 #include <fcntl.h>
39 #include "h.h"
40 #ifdef STRIPBADWORDS
41 #include "badwords.h"
42 #endif
43 #ifdef _WIN32
44 #include "version.h"
45 #endif
46
47 DLLFUNC CMD_FUNC(m_names);
48
49 #define MSG_NAMES "NAMES"
50 #define TOK_NAMES "?"
51
52 ModuleHeader MOD_HEADER(m_names)
53 = {
54 "m_names",
55 "$Id$",
56 "command /names",
57 "3.2-b8-1",
58 NULL
59 };
60
MOD_INIT(m_names)61 DLLFUNC int MOD_INIT(m_names)(ModuleInfo *modinfo)
62 {
63 CommandAdd(modinfo->handle, MSG_NAMES, TOK_NAMES, m_names, MAXPARA, M_USER|M_SERVER);
64 MARK_AS_OFFICIAL_MODULE(modinfo);
65 return MOD_SUCCESS;
66 }
67
MOD_LOAD(m_names)68 DLLFUNC int MOD_LOAD(m_names)(int module_load)
69 {
70 return MOD_SUCCESS;
71 }
72
MOD_UNLOAD(m_names)73 DLLFUNC int MOD_UNLOAD(m_names)(int module_unload)
74 {
75 return MOD_SUCCESS;
76 }
77
78 /************************************************************************
79 * m_names() - Added by Jto 27 Apr 1989
80 * 12 Feb 2000 - geesh, time for a rewrite -lucas
81 ************************************************************************/
82
83 static char buf[BUFSIZE];
84
85 /*
86 ** m_names
87 ** parv[0] = sender prefix
88 ** parv[1] = channel
89 */
90 #define TRUNCATED_NAMES 64
CMD_FUNC(m_names)91 DLLFUNC CMD_FUNC(m_names)
92 {
93 int uhnames = (MyConnect(sptr) && SupportUHNAMES(sptr)); // cache UHNAMES support
94 int bufLen = NICKLEN + (!uhnames ? 0 : (1 + USERLEN + 1 + HOSTLEN));
95 int mlen = strlen(me.name) + bufLen + 7;
96 aChannel *chptr;
97 aClient *acptr;
98 int member;
99 Member *cm;
100 int idx, flag = 1, spos;
101 char *s, *para = parv[1];
102 char nuhBuffer[NICKLEN+USERLEN+HOSTLEN+3];
103
104
105 if (parc < 2 || !MyConnect(sptr))
106 {
107 sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name,
108 parv[0], "*");
109 return 0;
110 }
111
112 if (parc > 1 &&
113 hunt_server_token(cptr, sptr, MSG_NAMES, TOK_NAMES, "%s %s", 2, parc, parv))
114 return 0;
115
116 for (s = para; *s; s++)
117 {
118 if (*s == ',')
119 {
120 if (strlen(para) > TRUNCATED_NAMES)
121 para[TRUNCATED_NAMES] = '\0';
122 sendto_realops("names abuser %s %s",
123 get_client_name(sptr, FALSE), para);
124 sendto_one(sptr, err_str(ERR_TOOMANYTARGETS),
125 me.name, sptr->name, "NAMES");
126 return 0;
127 }
128 }
129
130 chptr = find_channel(para, (aChannel *)NULL);
131
132 if (!chptr || (!ShowChannel(sptr, chptr) && !OPCanSeeSecret(sptr)))
133 {
134 sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name,
135 parv[0], para);
136 return 0;
137 }
138
139 /* cache whether this user is a member of this channel or not */
140 member = IsMember(sptr, chptr);
141
142 if (PubChannel(chptr))
143 buf[0] = '=';
144 else if (SecretChannel(chptr))
145 buf[0] = '@';
146 else
147 buf[0] = '*';
148
149 idx = 1;
150 buf[idx++] = ' ';
151 for (s = chptr->chname; *s; s++)
152 buf[idx++] = *s;
153 buf[idx++] = ' ';
154 buf[idx++] = ':';
155
156 /* If we go through the following loop and never add anything,
157 we need this to be empty, otherwise spurious things from the
158 LAST /names call get stuck in there.. - lucas */
159 buf[idx] = '\0';
160
161 spos = idx; /* starting point in buffer for names! */
162
163 for (cm = chptr->members; cm; cm = cm->next)
164 {
165 acptr = cm->cptr;
166 if (IsInvisible(acptr) && !member && !IsNetAdmin(sptr))
167 continue;
168 if (chptr->mode.mode & MODE_AUDITORIUM)
169 if (!is_chan_op(sptr, chptr)
170 && !is_chanprot(sptr, chptr)
171 && !is_chanowner(sptr, chptr))
172 if (!(cm->
173 flags & (CHFL_CHANOP | CHFL_CHANPROT |
174 CHFL_CHANOWNER)) && acptr != sptr)
175 continue;
176
177 if (!SupportNAMESX(sptr))
178 {
179 /* Standard NAMES reply */
180 #ifdef PREFIX_AQ
181 if (cm->flags & CHFL_CHANOWNER)
182 buf[idx++] = '~';
183 else if (cm->flags & CHFL_CHANPROT)
184 buf[idx++] = '&';
185 else
186 #endif
187 if (cm->flags & CHFL_CHANOP)
188 buf[idx++] = '@';
189 else if (cm->flags & CHFL_HALFOP)
190 buf[idx++] = '%';
191 else if (cm->flags & CHFL_VOICE)
192 buf[idx++] = '+';
193 } else {
194 /* NAMES reply with all rights included (NAMESX) */
195 #ifdef PREFIX_AQ
196 if (cm->flags & CHFL_CHANOWNER)
197 buf[idx++] = '~';
198 if (cm->flags & CHFL_CHANPROT)
199 buf[idx++] = '&';
200 #endif
201 if (cm->flags & CHFL_CHANOP)
202 buf[idx++] = '@';
203 if (cm->flags & CHFL_HALFOP)
204 buf[idx++] = '%';
205 if (cm->flags & CHFL_VOICE)
206 buf[idx++] = '+';
207 }
208
209 if (lifesux || !uhnames) {
210 s = acptr->name;
211 } else {
212 strlcpy(nuhBuffer,
213 make_nick_user_host(acptr->name, acptr->user->username, GetHost(acptr)),
214 bufLen + 1);
215 s = nuhBuffer;
216 }
217 /* 's' is intialized above to point to either acptr->name (normal),
218 * or to nuhBuffer (for UHNAMES).
219 */
220 for (; *s; s++)
221 buf[idx++] = *s;
222 buf[idx++] = ' ';
223 buf[idx] = '\0';
224 flag = 1;
225 if (mlen + idx + bufLen > BUFSIZE - 7)
226 {
227 sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name,
228 parv[0], buf);
229 idx = spos;
230 flag = 0;
231 }
232 }
233
234 if (flag)
235 sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
236
237 sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], para);
238
239 return 0;
240
241 }
242