00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "stdinc.h"
00025 #include "tools.h"
00026 #include "common.h"
00027 #include "handlers.h"
00028 #include "client.h"
00029 #include "channel.h"
00030 #include "channel_mode.h"
00031 #include "hash.h"
00032 #include "ircd.h"
00033 #include "numeric.h"
00034 #include "s_serv.h"
00035 #include "send.h"
00036 #include "list.h"
00037 #include "irc_string.h"
00038 #include "sprintf_irc.h"
00039 #include "s_conf.h"
00040 #include "msg.h"
00041 #include "parse.h"
00042 #include "modules.h"
00043
00044 static time_t last_used = 0;
00045
00046 static void m_who(struct Client *, struct Client *, int, char **);
00047 static void ms_who(struct Client *, struct Client *, int, char **);
00048
00049 struct Message who_msgtab = {
00050 "WHO", 0, 0, 2, 0, MFLG_SLOW, 0,
00051 {m_unregistered, m_who, ms_who, m_ignore, m_who, m_ignore}
00052 };
00053
00054 #ifndef STATIC_MODULES
00055 void
00056 _modinit(void)
00057 {
00058 mod_add_cmd(&who_msgtab);
00059 }
00060
00061 void
00062 _moddeinit(void)
00063 {
00064 mod_del_cmd(&who_msgtab);
00065 }
00066
00067 const char *_version = "$Revision: 313 $";
00068 #endif
00069
00070 static void who_global(struct Client *source_p, char *mask, int server_oper);
00071 static void do_who(struct Client *source_p, struct Client *target_p,
00072 const char *chname, const char *op_flags);
00073 static void do_who_on_channel(struct Client *source_p, struct Channel *chptr,
00074 const char *chname, int member, int server_oper);
00075
00076
00077
00078
00079
00080
00081
00082 static void
00083 m_who(struct Client *client_p, struct Client *source_p,
00084 int parc, char *parv[])
00085 {
00086 struct Client *target_p;
00087 char *mask = parv[1];
00088 dlink_node *lp;
00089 int server_oper = parc > 2 ? (*parv[2] == 'o') : 0;
00090 struct Channel *chptr;
00091 const char *from, *to;
00092
00093 if (IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
00094 {
00095 from = me.id;
00096 to = source_p->id;
00097 }
00098 else
00099 {
00100 from = me.name;
00101 to = source_p->name;
00102 }
00103
00104
00105 if (mask == NULL || !*mask)
00106 {
00107 who_global(source_p, mask, server_oper);
00108 sendto_one(source_p, form_str(RPL_ENDOFWHO),
00109 from, to, "*");
00110 return;
00111 }
00112
00113
00114 collapse(mask);
00115
00116
00117 if (mask[0] == '*' && !mask[1])
00118 {
00119 if ((lp = source_p->channel.head) != NULL)
00120 {
00121 struct Channel *mychannel = ((struct Membership *)lp->data)->chptr;
00122 do_who_on_channel(source_p, mychannel, mychannel->chname, YES,
00123 server_oper);
00124 }
00125
00126 sendto_one(source_p, form_str(RPL_ENDOFWHO), from, to, "*");
00127 return;
00128 }
00129
00130
00131 if (IsChanPrefix(*mask))
00132 {
00133
00134 if ((chptr = hash_find_channel(mask)) != NULL)
00135 {
00136 if (IsMember(source_p, chptr))
00137 do_who_on_channel(source_p, chptr, chptr->chname, YES, server_oper);
00138 else if (!SecretChannel(chptr))
00139 do_who_on_channel(source_p, chptr, chptr->chname, NO, server_oper);
00140 }
00141
00142 sendto_one(source_p, form_str(RPL_ENDOFWHO),
00143 from, to, mask);
00144 return;
00145 }
00146
00147
00148 if (((target_p = find_client(mask)) != NULL) &&
00149 IsClient(target_p) && (!server_oper || IsOper(target_p)))
00150 {
00151 if (IsServer(client_p))
00152 client_burst_if_needed(client_p,target_p);
00153
00154 DLINK_FOREACH(lp, target_p->channel.head)
00155 {
00156 chptr = ((struct Membership *) lp->data)->chptr;
00157 if (PubChannel(chptr) || IsMember(source_p, chptr))
00158 break;
00159 }
00160
00161 if (lp != NULL)
00162 do_who(source_p, target_p, chptr->chname,
00163 get_member_status(lp->data, NO));
00164 else
00165 do_who(source_p, target_p, NULL, "");
00166
00167 sendto_one(source_p, form_str(RPL_ENDOFWHO),
00168 from, to, mask);
00169 return;
00170 }
00171
00172
00173 if (mask[0] == '0' && !mask[1])
00174 who_global(source_p, NULL, server_oper);
00175 else
00176 who_global(source_p, mask, server_oper);
00177
00178
00179 sendto_one(source_p, form_str(RPL_ENDOFWHO),
00180 from, to, mask);
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 static void
00195 who_common_channel(struct Client *source_p, struct Channel *chptr,
00196 char *mask, int server_oper, int *maxmatches)
00197 {
00198 dlink_node *ptr;
00199 struct Client *target_p;
00200
00201 DLINK_FOREACH(ptr, chptr->members.head)
00202 {
00203 target_p = ((struct Membership *)ptr->data)->client_p;
00204
00205 if (!IsInvisible(target_p) || IsMarked(target_p))
00206 continue;
00207
00208 if (server_oper && !IsOper(target_p))
00209 continue;
00210
00211 SetMark(target_p);
00212
00213 assert(target_p->servptr != NULL);
00214
00215 if ((mask == NULL) ||
00216 match(mask, target_p->name) || match(mask, target_p->username) ||
00217 match(mask, target_p->host) ||
00218 ((!ConfigServerHide.hide_servers || IsOper(source_p)) &&
00219 match(mask, target_p->servptr->name)) ||
00220 match(mask, target_p->info))
00221 {
00222 do_who(source_p, target_p, NULL, "");
00223
00224 if (*maxmatches > 0)
00225 {
00226 if (--(*maxmatches) == 0)
00227 return;
00228 }
00229 }
00230 }
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 static void
00243 who_global(struct Client *source_p, char *mask, int server_oper)
00244 {
00245 struct Channel *chptr;
00246 struct Client *target_p;
00247 dlink_node *lp;
00248 dlink_node *lp_next;
00249 dlink_node *gcptr;
00250 dlink_node *gcptr_next;
00251 int maxmatches = 500;
00252
00253 if (!IsOper(source_p))
00254 {
00255 if ((last_used + ConfigFileEntry.pace_wait) > CurrentTime)
00256 {
00257
00258 sendto_one(source_p, form_str(RPL_LOAD2HI),
00259 me.name, source_p->name);
00260 return;
00261 }
00262 else
00263 last_used = CurrentTime;
00264 }
00265
00266
00267 DLINK_FOREACH_SAFE(lp, lp_next, source_p->channel.head)
00268 {
00269 chptr = ((struct Membership *)lp->data)->chptr;
00270 who_common_channel(source_p, chptr, mask, server_oper, &maxmatches);
00271 }
00272
00273
00274 DLINK_FOREACH_SAFE(gcptr, gcptr_next, global_client_list.head)
00275 {
00276 target_p = gcptr->data;
00277
00278 if (!IsClient(target_p))
00279 continue;
00280
00281 if (IsInvisible(target_p))
00282 {
00283 ClearMark(target_p);
00284 continue;
00285 }
00286
00287 if (server_oper && !IsOper(target_p))
00288 continue;
00289
00290 assert(target_p->servptr != NULL);
00291
00292 if (!mask ||
00293 match(mask, target_p->name) || match(mask, target_p->username) ||
00294 match(mask, target_p->host) || match(mask, target_p->servptr->name) ||
00295 match(mask, target_p->info))
00296 {
00297 do_who(source_p, target_p, NULL, "");
00298
00299 if (maxmatches > 0)
00300 {
00301 if (--maxmatches == 0)
00302 return;
00303 }
00304 }
00305 }
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 static void
00320 do_who_on_channel(struct Client *source_p, struct Channel *chptr,
00321 const char *chname, int member, int server_oper)
00322 {
00323 dlink_node *ptr = NULL, *ptr_next = NULL;
00324 struct Client *target_p;
00325 struct Membership *ms;
00326
00327 DLINK_FOREACH_SAFE(ptr, ptr_next, chptr->members.head)
00328 {
00329 ms = ptr->data;
00330 target_p = ms->client_p;
00331
00332 if (member || !IsInvisible(target_p))
00333 {
00334 if (server_oper && !IsOper(target_p))
00335 continue;
00336 do_who(source_p, target_p, chname, get_member_status(ms, NO));
00337 }
00338 }
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 static void
00351 do_who(struct Client *source_p, struct Client *target_p,
00352 const char *chname, const char *op_flags)
00353 {
00354 char status[6];
00355 const char *from, *to;
00356
00357 if (IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
00358 {
00359 from = me.id;
00360 to = source_p->id;
00361 }
00362 else
00363 {
00364 from = me.name;
00365 to = source_p->name;
00366 }
00367
00368 if (IsOper(source_p))
00369 ircsprintf(status, "%c%s%s%s",
00370 target_p->away ? 'G' : 'H',
00371 IsOper(target_p) ? "*" : "", IsCaptured(target_p) ? "#" : "", op_flags);
00372 else
00373 ircsprintf(status, "%c%s%s", target_p->away ? 'G' : 'H',
00374 IsOper(target_p) ? "*" : "", op_flags);
00375
00376 if (ConfigServerHide.hide_servers)
00377 {
00378 sendto_one(source_p, form_str(RPL_WHOREPLY), from, to,
00379 (chname) ? (chname) : "*",
00380 target_p->username, target_p->host,
00381 IsOper(source_p) ? target_p->servptr->name : "*",
00382 target_p->name, status, 0, target_p->info);
00383 }
00384 else
00385 {
00386 sendto_one(source_p, form_str(RPL_WHOREPLY), from, to,
00387 (chname) ? (chname) : "*",
00388 target_p->username,
00389 target_p->host, target_p->servptr->name, target_p->name,
00390 status, target_p->hopcount, target_p->info);
00391 }
00392 }
00393
00394
00395
00396
00397
00398
00399
00400 static void
00401 ms_who(struct Client *client_p, struct Client *source_p,
00402 int parc, char *parv[])
00403 {
00404
00405
00406
00407
00408 if (IsClient(source_p) && ServerInfo.hub &&
00409 IsCapable(client_p->from, CAP_LL))
00410 m_who(client_p, source_p, parc, parv);
00411 }