/* * ms_whois - server message handler * * parv[0] = sender prefix * parv[1] = nickname masklist * * or * * parv[1] = target server, or a nickname representing a server to target. * parv[2] = nickname masklist */ int ms_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { char* nick; char* tmp; char* p = 0; int found = 0; int total = 0; if (parc < 2) { send_reply(sptr, ERR_NONICKNAMEGIVEN); return 0; } if (parc > 2) { if (hunt_server_cmd(sptr, CMD_WHOIS, cptr, 0, "%C :%s", 1, parc, parv) != HUNTED_ISME) return 0; parv[1] = parv[2]; } total = 0; for (tmp = parv[1]; (nick = ircd_strtok(&p, tmp, ",")); tmp = 0) { struct Client *acptr = 0; found = 0; collapse(nick); acptr = FindUser(nick); if (acptr && !IsServer(acptr)) { found++; do_whois(sptr, acptr, parc); } if (!found) send_reply(sptr, ERR_NOSUCHNICK, nick); total+=found; if (total >= MAX_WHOIS_LINES) { send_reply(sptr, ERR_QUERYTOOLONG, parv[1]); break; } if (p) p[-1] = ','; } /* of tokenised parm[1] */ send_reply(sptr, RPL_ENDOFWHOIS, parv[1]); return 0; }
void cmd_whois::Handle (const char** parameters, int pcnt, userrec *user) { userrec *dest; if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0)) return; dest = ServerInstance->FindNick(parameters[0]); if (dest) { do_whois(this->ServerInstance, user,dest,0,0,parameters[0]); } else { /* no such nick/channel */ user->WriteServ("401 %s %s :No such nick/channel",user->nick, *parameters[0] ? parameters[0] : "*"); user->WriteServ("318 %s %s :End of /WHOIS list.",user->nick, *parameters[0] ? parameters[0] : "*"); } }
/* * m_whois - generic message handler * * parv[0] = sender prefix * parv[1] = nickname masklist * * or * * parv[1] = target server, or a nickname representing a server to target. * parv[2] = nickname masklist */ int m_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { char* nick; char* tmp; char* p = 0; int found = 0; int total = 0; int wildscount = 0; if (parc < 2) { send_reply(sptr, ERR_NONICKNAMEGIVEN); return 0; } if (parc > 2) { /* For convenience: Accept a nickname as first parameter, by replacing * it with the correct servername - as is needed by hunt_server(). * This is the secret behind the /whois nick nick trick. */ if (feature_int(FEAT_HIS_REMOTE)) { /* If remote queries are disabled, then use the *second* parameter of * of whois, so /whois nick nick still works. */ if (!IsAnOper(sptr)) { if (!FindUser(parv[2])) { send_reply(sptr, ERR_NOSUCHNICK, parv[2]); send_reply(sptr, RPL_ENDOFWHOIS, parv[2]); return 0; } parv[1] = parv[2]; } } if (hunt_server_cmd(sptr, CMD_WHOIS, cptr, 0, "%C :%s", 1, parc, parv) != HUNTED_ISME) return 0; parv[1] = parv[2]; } for (tmp = parv[1]; (nick = ircd_strtok(&p, tmp, ",")); tmp = 0) { int wilds; found = 0; collapse(nick); wilds = (strchr(nick, '?') || strchr(nick, '*')); if (!wilds) { struct Client *acptr = 0; /* No wildcards */ acptr = FindUser(nick); if (acptr && !IsServer(acptr)) { do_whois(sptr, acptr, parc); found = 1; } } else /* wilds */ { if (++wildscount > 3) { send_reply(sptr, ERR_QUERYTOOLONG, parv[1]); break; } found=do_wilds(sptr, nick, total, parc); } if (!found) send_reply(sptr, ERR_NOSUCHNICK, nick); total+=found; if (total >= MAX_WHOIS_LINES) { send_reply(sptr, ERR_QUERYTOOLONG, parv[1]); break; } if (p) p[-1] = ','; } /* of tokenised parm[1] */ send_reply(sptr, RPL_ENDOFWHOIS, parv[1]); return 0; }
/* * Search and return as many people as matched by the wild 'nick'. * returns the number of people found (or, obviously, 0, if none where * found). */ static int do_wilds(struct Client* sptr, char *nick, int count, int parc) { struct Client *acptr; /* Current client we're considering */ struct User *user; /* the user portion of the client */ const char *name; /* the name of this client */ struct Membership* chan; int invis; /* does +i apply? */ int member; /* Is this user on any channels? */ int showperson; /* Should we show this person? */ int found = 0 ; /* How many were found? */ /* Ech! This is hideous! */ for (acptr = GlobalClientList; (acptr = next_client(acptr, nick)); acptr = cli_next(acptr)) { if (!IsRegistered(acptr)) continue; if (IsServer(acptr)) continue; /* * I'm always last :-) and acptr->next == 0!! * * Isomer: Does this strike anyone else as being a horrible hideous * hack? */ if (IsMe(acptr)) { assert(!cli_next(acptr)); break; } /* * 'Rules' established for sending a WHOIS reply: * * - if wildcards are being used don't send a reply if * the querier isn't any common channels and the * client in question is invisible. * * - only send replies about common or public channels * the target user(s) are on; */ user = cli_user(acptr); name = (!*(cli_name(acptr))) ? "?" : cli_name(acptr); assert(user); invis = (acptr != sptr) && IsInvisible(acptr); member = (user && user->channel) ? 1 : 0; showperson = !invis && !member; /* Should we show this person now? */ if (showperson) { found++; do_whois(sptr, acptr, parc); if (count+found>MAX_WHOIS_LINES) return found; continue; } /* Step through the channels this user is on */ for (chan = user->channel; chan; chan = chan->next_channel) { struct Channel *chptr = chan->channel; /* If this is a public channel, show the person */ if (!invis && PubChannel(chptr)) { showperson = 1; break; } /* if this channel is +p and not +s, show them */ if (!invis && HiddenChannel(chptr) && !SecretChannel(chptr)) { showperson = 1; break; } member = find_channel_member(sptr, chptr) ? 1 : 0; if (invis && !member) continue; /* If sptr isn't really on this channel, skip it */ if (IsZombie(chan)) continue; /* Is this a common channel? */ if (member) { showperson = 1; break; } } /* of for (chan in channels) */ /* Don't show this person */ if (!showperson) continue; do_whois(sptr, acptr, parc); found++; if (count+found>MAX_WHOIS_LINES) return found; } /* of global client list */ return found; }