Beispiel #1
0
static void
h_can_join(hook_data_channel *data)
{
	struct Client *source_p = data->client;
	struct Channel *chptr = data->chptr;

	if((chptr->mode.mode & mymode) && !IsNetAdmin(source_p)) {
		sendto_one_numeric(source_p, 519, "%s :Cannot join channel (+N) - you are not an IRC network administrator", chptr->chname);
		data->approved = ERR_CUSTOM;
	}
}
Beispiel #2
0
static void do_channel_who(aClient *sptr, aChannel *channel, char *mask)
{
	Member *cm = channel->members;
	if (IsMember(sptr, channel) || IsNetAdmin(sptr))
		who_flags |= WF_ONCHANNEL;

	for (cm = channel->members; cm; cm = cm->next)
	{
		aClient *acptr = cm->cptr;
		char status[20];
		int cansee;
		if ((cansee = can_see(sptr, acptr, channel)) & WHO_CANTSEE)
			continue;

		make_who_status(sptr, acptr, channel, cm, status, cansee);
		send_who_reply(sptr, acptr, channel->chname, status, "");
    }
}
Beispiel #3
0
/*
 * mo_restart
 *
 */
static int
mo_restart(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	if(!IsOperDie(source_p))
	{
		sendto_one(source_p, form_str(ERR_NOPRIVS),
			   me.name, source_p->name, "die");
		return 0;
	}

	if(parc < 2 || EmptyString(parv[1]))
	{
		sendto_one_notice(source_p, ":Need server name /restart %s", me.name);
		return 0;
	}

	if(parc >2)
	{
		/* Remote restart.  Pass it along. */
		struct Client *server_p = find_server(NULL, parv[2]);
		if (!server_p)
		{
			sendto_one_numeric(source_p, ERR_NOSUCHSERVER, form_str(ERR_NOSUCHSERVER), parv[2]);
			return 0;
		}
		if (!IsMe(server_p))
		{
			if (!IsNetAdmin(source_p))
			{
				sendto_one(source_p, form_str(ERR_NOPRIVS),
					me.name, source_p->name, "netadmin");
				return 0;
			}

			sendto_one(server_p, ":%s ENCAP %s RESTART %s", source_p->name, parv[2], parv[1]);
			return 0;
		}
	}

	return do_restart(source_p, parv[1]);
}
Beispiel #4
0
DLLFUNC int _can_join(aClient *cptr, aClient *sptr, aChannel *chptr, char *key, char *link, char *parv[])
{
    Link *lp;
    Ban *banned;

    if ((chptr->mode.mode & MODE_ONLYSECURE) && !(sptr->umodes & UMODE_SECURE))
    {
        if (IsAnOper(sptr))
        {
            /* Yeah yeah.. duplicate code..
             * Anyway: if the channel is +z we still allow an ircop to bypass it
             * if they are invited.
             */
            for (lp = sptr->user->invited; lp; lp = lp->next)
                if (lp->value.chptr == chptr)
                    return 0;
        }
        return (ERR_SECUREONLYCHAN);
    }

    if ((chptr->mode.mode & MODE_OPERONLY) && !IsAnOper(sptr))
        return (ERR_OPERONLY);

    if ((chptr->mode.mode & MODE_ADMONLY) && !IsSkoAdmin(sptr))
        return (ERR_ADMONLY);

    /* Admin, Coadmin, Netadmin, and SAdmin can still walk +b in +O */
    banned = is_banned(sptr, chptr, BANCHK_JOIN);
    if (banned && (chptr->mode.mode & MODE_OPERONLY) &&
            IsAnOper(sptr) && !IsSkoAdmin(sptr) && !IsCoAdmin(sptr))
        return (ERR_BANNEDFROMCHAN);

    /* Only NetAdmin/SAdmin can walk +b in +A */
    if (banned && (chptr->mode.mode & MODE_ADMONLY) &&
            IsAnOper(sptr) && !IsNetAdmin(sptr) && !IsSAdmin(sptr))
        return (ERR_BANNEDFROMCHAN);

    for (lp = sptr->user->invited; lp; lp = lp->next)
        if (lp->value.chptr == chptr)
            return 0;

    if ((chptr->mode.limit && chptr->users >= chptr->mode.limit))
    {
        if (chptr->mode.link)
        {
            if (*chptr->mode.link != '\0')
            {
                /* We are linked. */
                sendto_one(sptr,
                           err_str(ERR_LINKCHANNEL), me.name,
                           sptr->name, chptr->chname,
                           chptr->mode.link);
                parv[0] = sptr->name;
                parv[1] = (chptr->mode.link);
                do_join(cptr, sptr, 2, parv);
                return -1;
            }
        }
        /* We check this later return (ERR_CHANNELISFULL); */
    }

    if ((chptr->mode.mode & MODE_RGSTRONLY) && !IsLoggedIn(sptr))
        return (ERR_NEEDREGGEDNICK);

    if (*chptr->mode.key && (BadPtr(key) || strcmp(chptr->mode.key, key)))
        return (ERR_BADCHANNELKEY);

    if ((chptr->mode.mode & MODE_INVITEONLY) && !find_invex(chptr, sptr))
        return (ERR_INVITEONLYCHAN);

    if ((chptr->mode.limit && chptr->users >= chptr->mode.limit))
        return (ERR_CHANNELISFULL);

    if (banned)
        return (ERR_BANNEDFROMCHAN);

#ifndef NO_OPEROVERRIDE
#ifdef OPEROVERRIDE_VERIFY
    if (IsOper(sptr) && (chptr->mode.mode & MODE_SECRET ||
                         chptr->mode.mode & MODE_PRIVATE) && !is_autojoin_chan(chptr->chname))
        return (ERR_OPERSPVERIFY);
#endif
#endif

#ifdef JOINTHROTTLE
    if (!IsAnOper(cptr) &&
            (chptr->mode.extmode & EXTMODE_JOINTHROTTLE) && isjthrottled(cptr, chptr))
        return ERR_TOOMANYJOINS;
#endif

    return 0;
}
Beispiel #5
0
/*
** m_kill
**	parv[0] = sender prefix
**	parv[1] = kill victim(s) - comma separated list
**	parv[2] = kill path
*/
DLLFUNC int  m_kill(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	aClient *acptr;
	anUser *auser;
	char inpath[HOSTLEN * 2 + USERLEN + 5];
	char *oinpath = get_client_name(cptr, FALSE);
	char *user, *path, *killer, *nick, *p, *s;
	int  chasing = 0, kcount = 0;



	if (parc < 2 || *parv[1] == '\0')
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
		    me.name, parv[0], "KILL");
		return 0;
	}

	user = parv[1];
	path = parv[2];		/* Either defined or NULL (parc >= 2!!) */

	strlcpy(inpath, oinpath, sizeof inpath);

#ifndef ROXnet
	if (IsServer(cptr) && (s = (char *)index(inpath, '.')) != NULL)
		*s = '\0';	/* Truncate at first "." */
#endif

	if (!IsPrivileged(cptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
		return 0;
	}
	if (IsAnOper(cptr))
	{
		if (BadPtr(path))
		{
			sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
			    me.name, parv[0], "KILL");
			return 0;
		}
		if (strlen(path) > (size_t)TOPICLEN)
			path[TOPICLEN] = '\0';
	}

	if (MyClient(sptr))
		user = (char *)canonize(user);

	for (p = NULL, nick = strtoken(&p, user, ","); nick;
	    nick = strtoken(&p, NULL, ","))
	{

		chasing = 0;

		if (!(acptr = find_client(nick, NULL)))
		{
			/*
			   ** If the user has recently changed nick, we automaticly
			   ** rewrite the KILL for this new nickname--this keeps
			   ** servers in synch when nick change and kill collide
			 */
			if (!(acptr =
			    get_history(nick, (long)KILLCHASETIMELIMIT)))
			{
				sendto_one(sptr, err_str(ERR_NOSUCHNICK),
				    me.name, parv[0], nick);
				continue;
			}
			sendto_one(sptr,
			    ":%s %s %s :*** KILL changed from %s to %s",
			    me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0], nick, acptr->name);
			chasing = 1;
		}
		if ((!MyConnect(acptr) && MyClient(cptr) && !OPCanGKill(cptr))
		    || (MyConnect(acptr) && MyClient(cptr)
		    && !OPCanLKill(cptr)))
		{
			sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,
			    parv[0]);
			continue;
		}
		if (IsServer(acptr) || IsMe(acptr))
		{
			sendto_one(sptr, err_str(ERR_CANTKILLSERVER),
			    me.name, parv[0]);
			continue;
		}
		if (!IsPerson(acptr))
		{
			/* Nick exists but user is not registered yet: IOTW "doesn't exist". -- Syzop */
			sendto_one(sptr, err_str(ERR_NOSUCHNICK),
			    me.name, parv[0], nick);
			continue;
		}

		if (IsServices(acptr) && !(IsNetAdmin(sptr) || IsULine(sptr)))
		{
			sendto_one(sptr, err_str(ERR_KILLDENY), me.name,
			    parv[0], parv[1]);
			return 0;
		}
		/* From here on, the kill is probably going to be successful. */

		kcount++;

		if (!IsServer(sptr) && (kcount > MAXKILLS))
		{
			sendto_one(sptr,
			    ":%s %s %s :*** Too many targets, kill list was truncated. Maximum is %d.",
			    me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0], MAXKILLS);
			break;
		}
		if (!IsServer(cptr))
		{
			/*
			   ** The kill originates from this server, initialize path.
			   ** (In which case the 'path' may contain user suplied
			   ** explanation ...or some nasty comment, sigh... >;-)
			   **
			   **   ...!operhost!oper
			   **   ...!operhost!oper (comment)
			 */
			strlcpy(inpath, GetHost(cptr), sizeof inpath);
			if (kcount < 2) {	/* Only check the path the first time
					   around, or it gets appended to itself. */
				if (!BadPtr(path))
				{
					(void)ircsprintf(buf, "%s%s (%s)",
					    cptr->name,
					    IsOper(sptr) ? "" : "(L)", path);
					path = buf;
				}
				else
					path = cptr->name;
			}
		}
		else if (BadPtr(path))
			path = "*no-path*";	/* Bogus server sending??? */
		/*
		   ** Notify all *local* opers about the KILL (this includes the one
		   ** originating the kill, if from this server--the special numeric
		   ** reply message is not generated anymore).
		   **
		   ** Note: "acptr->name" is used instead of "user" because we may
		   **    have changed the target because of the nickname change.
		 */

		auser = acptr->user;

		sendto_snomask_normal(SNO_KILLS,
		    "*** Notice -- Received KILL message for %s!%s@%s from %s Path: %s!%s",
		    acptr->name, auser->username,
		    IsHidden(acptr) ? auser->virthost : auser->realhost,
		    parv[0], inpath, path);
#if defined(USE_SYSLOG) && defined(SYSLOG_KILL)
		if (IsOper(sptr))
			syslog(LOG_DEBUG, "KILL From %s For %s Path %s!%s",
			    parv[0], acptr->name, inpath, path);
#endif
		/*
		 * By otherguy
		*/
                ircd_log
                    (LOG_KILL, "KILL (%s) by  %s(%s!%s)",
                           make_nick_user_host
                     (acptr->name, acptr->user->username, GetHost(acptr)),
                            parv[0],
                            inpath,
                            path);
		/*
		   ** And pass on the message to other servers. Note, that if KILL
		   ** was changed, the message has to be sent to all links, also
		   ** back.
		   ** Suicide kills are NOT passed on --SRB
		 */
		if (!MyConnect(acptr) || !MyConnect(sptr) || !IsAnOper(sptr))
		{
			sendto_serv_butone(cptr, ":%s KILL %s :%s!%s",
			    parv[0], acptr->name, inpath, path);
			if (chasing && IsServer(cptr))
				sendto_one(cptr, ":%s KILL %s :%s!%s",
				    me.name, acptr->name, inpath, path);
			acptr->flags |= FLAGS_KILLED;
		}

		/*
		   ** Tell the victim she/he has been zapped, but *only* if
		   ** the victim is on current server--no sense in sending the
		   ** notification chasing the above kill, it won't get far
		   ** anyway (as this user don't exist there any more either)
		 */
		if (MyConnect(acptr))
			sendto_prefix_one(acptr, sptr, ":%s KILL %s :%s!%s",
			    parv[0], acptr->name, inpath, path);
		/*
		   ** Set FLAGS_KILLED. This prevents exit_one_client from sending
		   ** the unnecessary QUIT for this. (This flag should never be
		   ** set in any other place)
		 */
		if (MyConnect(acptr) && MyConnect(sptr) && IsAnOper(sptr))

			(void)ircsprintf(buf2, "[%s] Local kill by %s (%s)",
			    me.name, sptr->name,
			    BadPtr(parv[2]) ? sptr->name : parv[2]);
		else
		{
			if ((killer = index(path, ' ')))
			{
				while ((killer >= path) && *killer && *killer != '!')
					killer--;
				if (!*killer)
					killer = path;
				else
					killer++;
			}
			else
				killer = path;
			(void)ircsprintf(buf2, "Killed (%s)", killer);
		}

		if (MyClient(sptr))
			RunHook3(HOOKTYPE_LOCAL_KILL, sptr, acptr, parv[2]);
		if (exit_client(cptr, acptr, sptr, buf2) == FLUSH_BUFFER)
			return FLUSH_BUFFER;
	}
	return 0;
}
Beispiel #6
0
/*
** m_ircops() By Claudio
** Rewritten by HAMLET
**   Lists online IRCOps
**
*/
int m_ircops(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client *acptr;
  char *status;
  char buf[BUFSIZE];
  int locals = 0, globals = 0;

  if (!IRCopsForAll && !IsPrivileged(cptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }
	
  strcpy(buf, "========================================================================================");
  sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf);
  strcpy(buf, "\2Nick                           Status                           Server\2");
  sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf);
  strcpy(buf, "----------------------------------------------------------------------------------------");
  sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf);
  for (acptr = GlobalClientList; acptr; acptr = acptr->next)
	{
  	  if (!IsService(acptr) && !IsStealth(acptr) &&  IsAnOper(acptr)
  	     && (!IsHideOper(acptr) || IsAnOper(sptr)) ) {
    
          if (!acptr->user) continue;

	  if (IsTechAdmin(acptr)) 
		status = "Technical Administrator";
	  else if (IsNetAdmin(acptr)) 
		status = "Network Administrator";
	  else if (IsSAdmin(acptr)) 
		status = "Services Administrator";
	  else if (IsAdmin(acptr)) 
		status = "Server Administrator";		
	  else if(IsOper(acptr))
		status = "Global IRC Operator"; 
	  else
		status = "Local IRC Operator";  	
	  

/* vlinks on /IRCops
* code by openglx
* idea to this by Midnight_Commander
*/
    if (acptr->user && acptr->user->vlink)
      {
        ircsprintf(buf, "\2%-29s\2  %-23s  %-6s  %s", acptr->name ? acptr->name : "<unknown>", status,
                              acptr->user->away ? "(AWAY)" : "", acptr->user->vlink->name);
      }
    else
      {
      ircsprintf(buf, "\2%-29s\2  %-23s  %-6s  %s", acptr->name ? acptr->name : "<unknown>", status,
                            acptr->user->away ? "(AWAY)" : "", acptr->user->server);
      }
      
/* end of the vlink support code */
                                                                                                 
          sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf);
          sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], "-");
          if (IsOper(acptr)) globals++;
          else locals++;
    	}
    }
 
  ircsprintf(buf, "Total: \2%d\2 IRCOp%s connected - \2%d\2 Globa%s, \2%d\2 Loca%s", globals+locals,
                        (globals+locals) > 1 ? "s" : "",
                        globals, globals > 1 ? "ls" : "l", locals, locals > 1 ? "ls" : "l");
  sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf);
  strcpy(buf, "========================================================================================");
  sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf);
  sendto_one(sptr, form_str(RPL_ENDOFLISTS), me.name, parv[0], "IRCOPS");
  return 0;
}
Beispiel #7
0
DLLFUNC CMD_FUNC(m_names)
{
	int uhnames = (MyConnect(sptr) && SupportUHNAMES(sptr)); // cache UHNAMES support
	int bufLen = NICKLEN + (!uhnames ? 0 : (1 + USERLEN + 1 + HOSTLEN));
	int  mlen = strlen(me.name) + bufLen + 7;
	aChannel *chptr;
	aClient *acptr;
	int  member;
	Member *cm;
	int  idx, flag = 1, spos;
	char *s, *para = parv[1];
	char nuhBuffer[NICKLEN+USERLEN+HOSTLEN+3];


	if (parc < 2 || !MyConnect(sptr))
	{
		sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name,
		    parv[0], "*");
		return 0;
	}

	for (s = para; *s; s++)
	{
		if (*s == ',')
		{
			if (strlen(para) > TRUNCATED_NAMES)
				para[TRUNCATED_NAMES] = '\0';
			sendto_realops("names abuser %s %s",
			    get_client_name(sptr, FALSE), para);
			sendto_one(sptr, err_str(ERR_TOOMANYTARGETS),
			    me.name, sptr->name, "NAMES");
			return 0;
		}
	}

	chptr = find_channel(para, (aChannel *)NULL);

	if (!chptr || (!ShowChannel(sptr, chptr) && !OPCanSeeSecret(sptr)))
	{
		sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name,
		    parv[0], para);
		return 0;
	}

	/* cache whether this user is a member of this channel or not */
	member = IsMember(sptr, chptr);

	if (PubChannel(chptr))
		buf[0] = '=';
	else if (SecretChannel(chptr))
		buf[0] = '@';
	else
		buf[0] = '*';

	idx = 1;
	buf[idx++] = ' ';
	for (s = chptr->chname; *s; s++)
		buf[idx++] = *s;
	buf[idx++] = ' ';
	buf[idx++] = ':';

	/* If we go through the following loop and never add anything,
	   we need this to be empty, otherwise spurious things from the
	   LAST /names call get stuck in there.. - lucas */
	buf[idx] = '\0';

	spos = idx;		/* starting point in buffer for names! */

	for (cm = chptr->members; cm; cm = cm->next)
	{
		acptr = cm->cptr;
		if (IsInvisible(acptr) && !member && !IsNetAdmin(sptr))
			continue;
		if (chptr->mode.mode & MODE_AUDITORIUM)
			if (!is_chan_op(sptr, chptr)
			    && !is_chanprot(sptr, chptr)
			    && !is_chanowner(sptr, chptr))
				if (!(cm->
				    flags & (CHFL_CHANOP | CHFL_CHANPROT |
				    CHFL_CHANOWNER)) && acptr != sptr)
					continue;

		if (!SupportNAMESX(sptr))
		{
			/* Standard NAMES reply */
#ifdef PREFIX_AQ
			if (cm->flags & CHFL_CHANOWNER)
				buf[idx++] = '~';
			else if (cm->flags & CHFL_CHANPROT)
				buf[idx++] = '&';
			else
#endif
			if (cm->flags & CHFL_CHANOP)
				buf[idx++] = '@';
			else if (cm->flags & CHFL_HALFOP)
				buf[idx++] = '%';
			else if (cm->flags & CHFL_VOICE)
				buf[idx++] = '+';
		} else {
			/* NAMES reply with all rights included (NAMESX) */
#ifdef PREFIX_AQ
			if (cm->flags & CHFL_CHANOWNER)
				buf[idx++] = '~';
			if (cm->flags & CHFL_CHANPROT)
				buf[idx++] = '&';
#endif
			if (cm->flags & CHFL_CHANOP)
				buf[idx++] = '@';
			if (cm->flags & CHFL_HALFOP)
				buf[idx++] = '%';
			if (cm->flags & CHFL_VOICE)
				buf[idx++] = '+';
		}

		if (!uhnames) {
			s = acptr->name;
		} else {
			strlcpy(nuhBuffer,
			        make_nick_user_host(acptr->name, acptr->user->username, GetHost(acptr)),
				bufLen + 1);
			s = nuhBuffer;
		}
		/* 's' is intialized above to point to either acptr->name (normal),
		 * or to nuhBuffer (for UHNAMES).
		 */
		for (; *s; s++)
			buf[idx++] = *s;
		buf[idx++] = ' ';
		buf[idx] = '\0';
		flag = 1;
		if (mlen + idx + bufLen > BUFSIZE - 7)
		{
			sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name,
			    parv[0], buf);
			idx = spos;
			flag = 0;
		}
	}

	if (flag)
		sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);

	sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], para);

	return 0;

}
Beispiel #8
0
/*
** m_whois
**	parv[0] = sender prefix
**	parv[1] = nickname masklist
*/
DLLFUNC int  m_whois(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	Membership *lp;
	anUser *user;
	aClient *acptr, *a2cptr;
	aChannel *chptr;
	char *nick, *tmp, *name;
	char *p = NULL;
	int  found, len, mlen, cnt = 0;
	char querybuf[BUFSIZE];

	if (IsServer(sptr))	
		return 0;

	if (parc < 2)
	{
		sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
		    me.name, parv[0]);
		return 0;
	}

	if (parc > 2)
	{
		if (hunt_server(cptr, sptr, ":%s WHOIS %s :%s", 1, parc, parv) != HUNTED_ISME)
			return 0;
		parv[1] = parv[2];
	}

	strcpy(querybuf, parv[1]);

	for (tmp = canonize(parv[1]); (nick = strtok_r(tmp, ",", &p)); tmp = NULL)
	{
		unsigned char invis, showchannel, member, wilds, hideoper; /* <- these are all boolean-alike */

		if (++cnt > MAXTARGETS)
			break;

		found = 0;
		/* We do not support "WHOIS *" */
		wilds = (index(nick, '?') || index(nick, '*'));
		if (wilds)
			continue;

		if ((acptr = find_client(nick, NULL)))
		{
			if (IsServer(acptr))
				continue;
			/*
			 * I'm always last :-) and acptr->next == NULL!!
			 */
			if (IsMe(acptr))
				break;
			/*
			 * 'Rules' established for sending a WHOIS reply:
			 * - only send replies about common or public channels
			 *   the target user(s) are on;
			 */

			if (!IsPerson(acptr))
				continue;

			user = acptr->user;
			name = (!*acptr->name) ? "?" : acptr->name;

			invis = acptr != sptr && IsInvisible(acptr);
			member = (user->channel) ? 1 : 0;

			a2cptr = find_server_quick(user->server);

			hideoper = 0;
			if (IsHideOper(acptr) && (acptr != sptr) && !IsAnOper(sptr))
				hideoper = 1;

			if (IsWhois(acptr) && (sptr != acptr))
			{
				sendnotice(acptr,
				    "*** %s (%s@%s) did a /whois on you.",
				    sptr->name,
				    sptr->user->username, sptr->user->realhost);
			}
			sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name,
			    parv[0], name,
			    user->username,
			    IsHidden(acptr) ? user->virthost : user->realhost,
			    acptr->info);

			if (IsOper(sptr) || acptr == sptr)
			{
				char sno[512];
				strcpy(sno, get_sno_str(acptr));
				
				/* send the target user's modes */
				sendto_one(sptr, rpl_str(RPL_WHOISMODES),
				    me.name, parv[0], name,
				    get_mode_str(acptr), sno[1] == 0 ? "" : sno);
			}
			if ((acptr == sptr) || IsAnOper(sptr))
			{
				sendto_one(sptr, rpl_str(RPL_WHOISHOST),
				    me.name, parv[0], acptr->name,
					(MyConnect(acptr) && strcmp(acptr->username, "unknown")) ? acptr->username : "******",
					user->realhost, user->ip_str ? user->ip_str : "");
			}

			if (IsARegNick(acptr))
				sendto_one(sptr, rpl_str(RPL_WHOISREGNICK), me.name, parv[0], name);
			
			found = 1;
			mlen = strlen(me.name) + strlen(parv[0]) + 10 + strlen(name);
			for (len = 0, *buf = '\0', lp = user->channel; lp; lp = lp->next)
			{
				chptr = lp->chptr;
				showchannel = 0;
				if (ShowChannel(sptr, chptr))
					showchannel = 1;
				if (OPCanSeeSecret(sptr))
					showchannel = 1;
				if ((acptr->umodes & UMODE_HIDEWHOIS) && !IsMember(sptr, chptr) && !IsAnOper(sptr))
					showchannel = 0;
				if (IsServices(acptr) && !IsNetAdmin(sptr) && !IsSAdmin(sptr))
					showchannel = 0;
				if (acptr == sptr)
					showchannel = 1;
				/* Hey, if you are editting here... don't forget to change the webtv w_whois ;p. */

				if (showchannel)
				{
					long access;
					if (len + strlen(chptr->chname) > (size_t)BUFSIZE - 4 - mlen)
					{
						sendto_one(sptr,
						    ":%s %d %s %s :%s",
						    me.name,
						    RPL_WHOISCHANNELS,
						    parv[0], name, buf);
						*buf = '\0';
						len = 0;
					}
#ifdef SHOW_SECRET
					if (IsAnOper(sptr)
#else
					if (IsNetAdmin(sptr)
#endif
					    && SecretChannel(chptr) && !IsMember(sptr, chptr))
						*(buf + len++) = '?';
					if (acptr->umodes & UMODE_HIDEWHOIS && !IsMember(sptr, chptr)
						&& IsAnOper(sptr))
						*(buf + len++) = '!';
					access = get_access(acptr, chptr);
					if (!SupportNAMESX(sptr))
					{
#ifdef PREFIX_AQ
						if (access & CHFL_CHANOWNER)
							*(buf + len++) = '~';
						else if (access & CHFL_CHANPROT)
							*(buf + len++) = '&';
						else
#endif
						if (access & CHFL_CHANOP)
							*(buf + len++) = '@';
						else if (access & CHFL_HALFOP)
							*(buf + len++) = '%';
						else if (access & CHFL_VOICE)
							*(buf + len++) = '+';
					}
					else
					{
#ifdef PREFIX_AQ
						if (access & CHFL_CHANOWNER)
							*(buf + len++) = '~';
						if (access & CHFL_CHANPROT)
							*(buf + len++) = '&';
#endif
						if (access & CHFL_CHANOP)
							*(buf + len++) = '@';
						if (access & CHFL_HALFOP)
							*(buf + len++) = '%';
						if (access & CHFL_VOICE)
							*(buf + len++) = '+';
					}
					if (len)
						*(buf + len) = '\0';
					(void)strcpy(buf + len, chptr->chname);
					len += strlen(chptr->chname);
					(void)strcat(buf + len, " ");
					len++;
				}
			}

			if (buf[0] != '\0')
				sendto_one(sptr, rpl_str(RPL_WHOISCHANNELS), me.name, parv[0], name, buf); 

                        if (!(IsULine(acptr) && !IsOper(sptr) && HIDE_ULINES))
				sendto_one(sptr, rpl_str(RPL_WHOISSERVER),
				    me.name, parv[0], name, user->server,
				    a2cptr ? a2cptr->info : "*Not On This Net*");

			if (user->away)
				sendto_one(sptr, rpl_str(RPL_AWAY), me.name,
				    parv[0], name, user->away);
			/* makesure they aren't +H (we'll also check
			   before we display a helpop or IRCD Coder msg)
			   -- codemastr */

			if ((IsAnOper(acptr) || IsServices(acptr)) && !hideoper)
			{
				buf[0] = '\0';
				if (IsNetAdmin(acptr))
					strlcat(buf, "a Network Administrator", sizeof buf);
				else if (IsSAdmin(acptr))
					strlcat(buf, "a Services Administrator", sizeof buf);
				else if (IsAdmin(acptr) && !IsCoAdmin(acptr))
					strlcat(buf, "a Server Administrator", sizeof buf);
				else if (IsCoAdmin(acptr))
					strlcat(buf, "a Co Administrator", sizeof buf);
				else if (IsServices(acptr))
					strlcat(buf, "a Network Service", sizeof buf);
				else if (IsOper(acptr))
					strlcat(buf, "an IRC Operator", sizeof buf);

				else
					strlcat(buf, "a Local IRC Operator", sizeof buf);
				if (buf[0])
				{
					if (IsOper(sptr) && MyClient(acptr))
						sendto_one(sptr,
						    ":%s 313 %s %s :is %s (%s)", me.name,
						    parv[0], name, buf, acptr->user->operlogin);
					else
						sendto_one(sptr,
						    rpl_str(RPL_WHOISOPERATOR), me.name,
						    parv[0], name, buf);
				}
			}

			if (IsHelpOp(acptr) && !hideoper && !user->away)
				sendto_one(sptr, rpl_str(RPL_WHOISHELPOP), me.name, parv[0], name);

			if (acptr->umodes & UMODE_BOT)
				sendto_one(sptr, rpl_str(RPL_WHOISBOT), me.name, parv[0], name, ircnetwork);

			if (acptr->umodes & UMODE_SECURE)
				sendto_one(sptr, rpl_str(RPL_WHOISSECURE), me.name, parv[0], name,
					"is using a Secure Connection");

			if (!BadPtr(user->swhois) && !hideoper)
					sendto_one(sptr, ":%s %d %s %s :%s",
					    me.name, RPL_WHOISSPECIAL, parv[0],
					    name, acptr->user->swhois);

			/*
			 * display services account name if it's actually a services account name and
			 * not a legacy timestamp.  --nenolod
			 */
			if (!isdigit(*user->svid))
				sendto_one(sptr, rpl_str(RPL_WHOISLOGGEDIN), me.name, parv[0], name, user->svid);

			/*
			 * Umode +I hides an oper's idle time from regular users.
			 * -Nath.
			 */
			if (MyConnect(acptr) && (IsAnOper(sptr) || !(acptr->umodes & UMODE_HIDLE)))
			{
				sendto_one(sptr, rpl_str(RPL_WHOISIDLE),
				    me.name, parv[0], name,
				    TStime() - acptr->last, acptr->firsttime);
			}
		}
		if (!found)
			sendto_one(sptr, err_str(ERR_NOSUCHNICK),
			    me.name, parv[0], nick);
	}
	sendto_one(sptr, rpl_str(RPL_ENDOFWHOIS), me.name, parv[0], querybuf);

	return 0;
}
DLLFUNC int m_jumpserver(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
char *serv, *sslserv=NULL, *reason, *p, *p2;
int all=0, port=6667, sslport=6697;
char logbuf[512];

	if (!IsCoAdmin(sptr) && !IsAdmin(sptr) && !IsNetAdmin(sptr) && !IsSAdmin(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
		return 0;
	}

	if ((parc < 2) || BadPtr(parv[1]))
	{
#ifdef USE_SSL
		if (jss && jss->ssl_server)
			sendnotice(sptr, "JumpServer is \002ENABLED\002 to %s:%d (SSL: %s:%d) with reason '%s'",
				jss->server, jss->port, jss->ssl_server, jss->ssl_port, jss->reason);
		else
#endif
		if (jss)
			sendnotice(sptr, "JumpServer is \002ENABLED\002 to %s:%d with reason '%s'",
				jss->server, jss->port, jss->reason);
		else
			sendnotice(sptr, "JumpServer is \002DISABLED\002");
		return 0;
	}

	if ((parc > 1) && (!strcasecmp(parv[1], "OFF") || !strcasecmp(parv[1], "STOP")))
	{
		if (!jss)
		{
			sendnotice(sptr, "JUMPSERVER: No redirect active (already OFF)");
			return 0;
		}
		free_jss();
		snprintf(logbuf, sizeof(logbuf), "%s (%s@%s) turned JUMPSERVER OFF",
			sptr->name, sptr->user->username, sptr->user->realhost);
		sendto_realops("%s", logbuf);
		ircd_log(LOG_ERROR, "%s", logbuf);
		return 0;
	}

	if (parc < 4)
	{
		/* Waah, pretty verbose usage info ;) */
		sendnotice(sptr, "Use: /JUMPSERVER <server>[:port] <NEW|ALL> <reason>");
#ifdef USE_SSL
		sendnotice(sptr, " Or: /JUMPSERVER <server>[:port]/<sslserver>[:port] <NEW|ALL> <reason>");
#endif
		sendnotice(sptr, "if 'NEW' is chosen then only new (incoming) connections will be redirected");
		sendnotice(sptr, "if 'ALL' is chosen then all clients except opers will be redirected immediately (+incoming connections)");
		sendnotice(sptr, "Example: /JUMPSERVER irc2.test.net NEW This server will be upgraded, please use irc2.test.net for now");
		sendnotice(sptr, "And then for example 10 minutes later...");
		sendnotice(sptr, "         /JUMPSERVER irc2.test.net ALL This server will be upgraded, please use irc2.test.net for now");
		sendnotice(sptr, "Use: '/JUMPSERVER OFF' to turn off any redirects");
		return 0;
	}

	/* Parsing code follows...
	 * The parsing of the SSL stuff is still done even on non-SSL,
	 * but it's simply not used/applied :).
	 * Reason for this is to reduce non-SSL/SSL inconsistency issues.
	 */

	serv = parv[1];
	
	p = strchr(serv, '/');
	if (p)
	{
		*p = '\0';
		sslserv = p+1;
	}
	
	p = strchr(serv, ':');
	if (p)
	{
		*p++ = '\0';
		port = atoi(p);
		if ((port < 1) || (port > 65535))
		{
			sendnotice(sptr, "Invalid serverport specified (%d)", port);
			return 0;
		}
	}
	if (sslserv)
	{
		p = strchr(sslserv, ':');
		if (p)
		{
			*p++ = '\0';
			sslport = atoi(p);
			if ((sslport < 1) || (sslport > 65535))
			{
				sendnotice(sptr, "Invalid SSL serverport specified (%d)", sslport);
				return 0;
			}
		}
		if (!*sslserv)
			sslserv = NULL;
	}
	if (!strcasecmp(parv[2], "new"))
		all = 0;
	else if (!strcasecmp(parv[2], "all"))
		all = 1;
	else {
		sendnotice(sptr, "ERROR: Invalid action '%s', should be 'NEW' or 'ALL' (see /jumpserver help for usage)", parv[2]);
		return 0;
	}

	reason = parv[3];

	/* Free any old stuff (needed!) */
	if (jss)
		free_jss();

	jss = MyMallocEx(sizeof(JSS));

	/* Set it */
	jss->server = strdup(serv);
	jss->port = port;
#ifdef USE_SSL
	if (sslserv)
	{
		jss->ssl_server = strdup(sslserv);
		jss->ssl_port = sslport;
	}
#endif
	jss->reason = strdup(reason);

	/* Broadcast/log */
#ifdef USE_SSL
	if (sslserv)
		snprintf(logbuf, sizeof(logbuf), "%s (%s@%s) added JUMPSERVER redirect for %s to %s:%d [SSL: %s:%d] with reason '%s'",
			sptr->name, sptr->user->username, sptr->user->realhost,
			all ? "ALL CLIENTS" : "all new clients",
			jss->server, jss->port, jss->ssl_server, jss->ssl_port, jss->reason);
	else
#endif
		snprintf(logbuf, sizeof(logbuf), "%s (%s@%s) added JUMPSERVER redirect for %s to %s:%d with reason '%s'",
			sptr->name, sptr->user->username, sptr->user->realhost,
			all ? "ALL CLIENTS" : "all new clients",
			jss->server, jss->port, jss->reason);

	sendto_realops("%s", logbuf);
	ircd_log(LOG_ERROR, "%s", logbuf);

	if (all)
		redirect_all_clients();

	return 0;
}
Beispiel #10
0
/*
** m_whois
**      parv[0] = sender prefix
**      parv[1] = nickname masklist
*/
int     m_whois(struct Client *cptr,
                struct Client *sptr,
                int parc,
                char *parv[])
{
  static anUser UnknownUser =
  {
    NULL,       /* next */
    NULL,       /* channel */
    NULL,       /* invited */
	NULL,		/* silence */
    NULL,       /* away */
    0,          /* last */
    1,          /* refcount */
    0,          /* joined */
    "<Unknown>"         /* server */
  };
  static char rpl_oper[] = "an IRC Operator";
  static char rpl_locop[] = "an IRC Operator - Local IRC Operator";
  static char rpl_sadmin[] = "an IRC Operator - Services Administrator";
  static char rpl_admin[] = "an IRC Operator - Server Administrator";   
  static char rpl_tadmin[] = "an IRC Operator - Technical Administrator";
  static char rpl_nadmin[] = "an IRC Operator - Network Administrator"; 
  
  Link  *lp;
  anUser        *user;
  struct Client *acptr, *a2cptr;
  aChannel *chptr;
  char  *nick, *name;
  /* char  *tmp; */
  char  *p = NULL;
  int   found, len, mlen;
  static time_t last_used=0L;
  char *nick_match=NULL, *user_match=NULL, *host_match=NULL, *server_match=NULL;
  char *name_match=NULL;
  int found_mode;
  int hits = 0;
  char *mename = me.name;

  if(sptr->user && sptr->user->vlink)
    mename = sptr->user->vlink->name;
  
  if (parc < 2)
    {
      sendto_one(sptr, form_str(ERR_NONICKNAMEGIVEN),
                 mename, parv[0]);
      return 0;
    }

  if(parc > 2)
    {
      if (hunt_server(cptr,sptr,":%s WHOIS %s :%s", 1,parc,parv) !=
          HUNTED_ISME)
        return 0;
      parv[1] = parv[2];
    }

  if(!IsAnOper(sptr) && !MyConnect(sptr)) /* pace non local requests */
    {
      if((last_used + WHOIS_WAIT) > CurrentTime)
        {
          /* Unfortunately, returning anything to a non local
           * request =might= increase sendq to be usable in a split hack
           * Sorry gang ;-( - Dianora
           */
          return 0;
        }
      else
        {
          last_used = CurrentTime;
        }
    }

  /* Multiple whois from remote hosts, can be used
   * to flood a server off. One could argue that multiple whois on
   * local server could remain. Lets think about that, for now
   * removing it totally. 
   * -Dianora 
   */

  /*  for (tmp = parv[1]; (nick = strtoken(&p, tmp, ",")); tmp = NULL) */
  nick = parv[1];
  p = strchr(parv[1],',');
  if(p)
    *p = '\0';

    {
      int       invis, member, wilds;
      found = 0;
      (void)collapse(nick);
      wilds = (nick[0]=='$' || strchr(nick, '?') || strchr(nick, '*'));
      /*
      ** We're no longer allowing remote users to generate
      ** requests with wildcards.
      */
      if (wilds && !IsAnOper(sptr))
        {
          sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                     mename, parv[0], nick);
          return 0;
        }
      /*        continue; */

      /* If the nick doesn't have any wild cards in it,
       * then just pick it up from the hash table
       * - Dianora 
       */

      if(!wilds)
        {
          acptr = hash_find_client(nick,(struct Client *)NULL);
          if(!acptr)
            {
              sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                         mename, parv[0], nick);

              sendto_one(sptr, form_str(RPL_ENDOFWHOIS),
                         mename, parv[0], parv[1]);
						 
              return 0;
              /*              continue; */
            }
          if(IsStealth(acptr)) { 
	    sendto_one(sptr, form_str(ERR_NOSUCHNICK), mename,
	     parv[0], nick);
	     return 0; // Add by ^Stinger^ after the idea of Soldier (:
	  } 
	  if(!IsPerson(acptr))
            {
              sendto_one(sptr, form_str(RPL_ENDOFWHOIS),
                         mename, parv[0], parv[1]);
              return 0;
            }
            /*      continue; */

          user = acptr->user ? acptr->user : &UnknownUser;
          name = (!*acptr->name) ? "?" : acptr->name;
          invis = IsInvisible(acptr);
          member = (user->channel) ? 1 : 0;

          a2cptr = find_server(user->server);
          
          sendto_one(sptr, form_str(RPL_WHOISUSER), mename,
        	    parv[0], name, acptr->username, acptr->host, acptr->info);

	  if((IsOper(sptr) || (acptr == sptr)) && WhoisExtension)
	  {
		sendto_one(sptr, form_str(RPL_WHOISREALHOST), mename,
		    parv[0], name, acptr->realhost);
	  }

          mlen = strlen(mename) + strlen(parv[0]) + 6 +
            strlen(name);
			
          *buf = '\0';			
          if (IsSsl(acptr))
          {
              sendto_one(sptr, form_str(RPL_WHOISSECURE), mename, parv[0], parv[1]);
          }

		  if(((!IsPrivate(acptr) || IsOper(sptr)) || (acptr==sptr))
		  && !IsStealth(acptr))
          for (len = 0, *buf = '\0', lp = user->channel; lp;
               lp = lp->next)
            {
              chptr = lp->value.chptr;
              if (ShowChannel(sptr, chptr))
                {
                  if (len + strlen(chptr->chname)
                      > (size_t) BUFSIZE - 4 - mlen)
                    {
                      sendto_one(sptr,
                                 ":%s %d %s %s :%s",
                                 mename,
                                 RPL_WHOISCHANNELS,
                                 parv[0], name, buf);
                      *buf = '\0';
                      len = 0;
                    }

		  found_mode = user_channel_mode(acptr, chptr);
#ifdef HIDE_OPS
		  if(is_chan_op(sptr,chptr))
#endif
		    {
		      if(found_mode & CHFL_CHANOP)
			*(buf + len++) = '@';
#ifdef HALFOPS
                     else if (found_mode & CHFL_HALFOP)
                       *(buf + len++) = '%';
#endif
		      else if (found_mode & CHFL_VOICE)
			*(buf + len++) = '+';
		    }
                  if (len)
                    *(buf + len) = '\0';
                  (void)strcpy(buf + len, chptr->chname);
                  len += strlen(chptr->chname);
                  (void)strcat(buf + len, " ");
                  len++;
                }
            }
          if (buf[0] != '\0')
            sendto_one(sptr, form_str(RPL_WHOISCHANNELS),
                       mename, parv[0], name, buf);
          if(IsAnOper(sptr) || !HideServerOnWhois)
            {
#ifdef SERVERHIDE
            if (!(IsAnOper(sptr) || acptr == sptr))
              sendto_one(sptr, form_str(RPL_WHOISSERVER),
                       mename, parv[0], name, NetworkName,
                       NetworkDesc);
            else
#endif
            if(acptr->user && acptr->user->vlink)
              sendto_one(sptr, form_str(RPL_WHOISSERVER),
                     mename, parv[0], name, user->vlink->name,
                     user->vlink->passwd);
            else
              {
                if(!IsService(acptr) || IsAnOper(sptr) || !HideServicesServer)
                sendto_one(sptr, form_str(RPL_WHOISSERVER),
                     mename, parv[0], name, user->server,
                     a2cptr?a2cptr->info:"*Not On This Net*");
              }
	    } /* if(IsAnOper(sptr) || HideServerOnWhois) */
	  if (IsIdentified(acptr))
            sendto_one(sptr, form_str(RPL_WHOISIDENTIFIED),
                       mename, parv[0], name);

          if (IsHelper(acptr))
        	sendto_one(sptr, form_str(RPL_WHOISHELPOP),
                           mename, parv[0], name);
					   
          if(IsOper(sptr) && WhoisExtension)
	  {
	    sendto_one(sptr, form_str(RPL_WHOISMODE),
		mename, parv[0], name, get_mode_string(acptr));
	  }
	  
	  if (user->away)
            sendto_one(sptr, form_str(RPL_AWAY), mename,
                       parv[0], name, user->away);
	if(!IsHideOper(acptr) || IsOper(sptr))
	  {	
	    if (IsNetAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                      mename, parv[0], name, rpl_nadmin);
	    else if (IsTechAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                      mename, parv[0], name, rpl_tadmin);						   
            else if (IsSAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                      mename, parv[0], name, rpl_sadmin);						   
            else if (IsAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),  
                      mename, parv[0], name, rpl_admin);
            else if (IsOper(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR), 
            	mename, parv[0], name, rpl_oper);
            else if (IsLocOp(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),
            	mename, parv[0], name, rpl_locop);
	  }
#ifdef WHOIS_NOTICE
          if ((IsOper(acptr)) && ((acptr)->umodes & UMODE_SPY) &&
              (MyConnect(sptr)) && (IsPerson(sptr)) && (acptr != sptr) && !is_silenced(sptr, acptr))
            sendto_one(acptr,
                       ":%s NOTICE %s :*** Notice -- %s (%s@%s) is doing a /whois on you.",
                       me.name, acptr->name, parv[0], sptr->username,
                       sptr->realhost);
#endif /* #ifdef WHOIS_NOTICE */


          if ((acptr->user
#ifdef SERVERHIDE
              && IsAnOper(sptr)
#endif
              && MyConnect(acptr)))
            sendto_one(sptr, form_str(RPL_WHOISIDLE),
                       mename, parv[0], name,
                       CurrentTime - user->last,
                       acptr->firsttime);
					   
          sendto_one(sptr, form_str(RPL_ENDOFWHOIS), mename, parv[0], parv[1]);
          
          return 0;
          /*      continue; */
        }

      /* wild is true so here we go */
          if(nick[0]==':') /* real name match */
            {
              name_match =  &nick[1];
              nick_match = NULL;
            }
          else
	  if(nick[0]=='$') /* server name match */
	    {
	      server_match = &nick[1];
	      nick_match = NULL;
	    }
	  else
		{
		  host_match = strchr(nick,'@');
		  if(host_match)
			{
			  if(*host_match)
				*(host_match++) = '\0';						  
			  user_match=nick;		  		  
			  if(host_match=='\0')
				host_match="*";		  			
			  if(user_match=='\0')
			  user_match="*";		  
			}
		  else
			nick_match = nick;
		}
		
	  				
      for (acptr = GlobalClientList; acptr;
           acptr = acptr->next)
        {
          if (IsServer(acptr))
            continue;
          /*
           * I'm always last :-) and acptr->next == NULL!!
           */
          if (IsMe(acptr))
            break;
          /*
           * 'Rules' established for sending a WHOIS reply:
           *
           *
           * - if wildcards are being used dont send a reply if
           *   the querier isnt any common channels and the
           *   client in question is invisible and wildcards are
           *   in use (allow exact matches only);
           *
           * - only send replies about common or public channels
           *   the target user(s) are on;
           */

/* If its an unregistered client, ignore it, it can
   be "seen" on a /trace anyway  -Dianora */

          if(!IsRegistered(acptr))
            continue;

          user = acptr->user ? acptr->user : &UnknownUser;
          name = (!*acptr->name) ? "?" : acptr->name;
		  
		  if(  (server_match && !match(server_match, user->server))
		    || (nick_match && !match(nick, name)) 
			|| (host_match && !match(host_match, acptr->realhost)
			   && !match(host_match, acptr->host))
			|| (user_match && !match(user_match, acptr->username))
			|| (name_match &&  !match(name_match, acptr->info))
			)
        	  continue;
			  
		  ++hits;
			  
          a2cptr = find_server(user->server);
          
          sendto_one(sptr, form_str(RPL_WHOISUSER), mename,
                    parv[0], name,
                    acptr->username, 
					IsOper(sptr) ? acptr->realhost : acptr->host,					 
					acptr->info);
					
          found = 1;
          mlen = strlen(mename) + strlen(parv[0]) + 6 +
            strlen(name);
          for (len = 0, *buf = '\0', lp = user->channel; lp;
               lp = lp->next)
            {
              chptr = lp->value.chptr;
              if (ShowChannel(sptr, chptr))
                {
                  if (len + strlen(chptr->chname)
                      > (size_t) BUFSIZE - 4 - mlen)
                    {
                      sendto_one(sptr,
                                 ":%s %d %s %s :%s",
                                 mename,
                                 RPL_WHOISCHANNELS,
                                 parv[0], name, buf);
                      *buf = '\0';
                      len = 0;
                    }
		  found_mode = user_channel_mode(acptr, chptr);
#ifdef HIDE_OPS
                  if(is_chan_op(sptr,chptr))
#endif
		     {
		       if (found_mode & CHFL_CHANOP)
			 *(buf + len++) = '@';
#ifdef HALFOPS
                     else if (found_mode & CHFL_HALFOP)
                        *(buf + len++) = '%';
#endif                                            
		       else if (found_mode & CHFL_VOICE)
			 *(buf + len++) = '+';
		     }
                  if (len)
                    *(buf + len) = '\0';
                  (void)strcpy(buf + len, chptr->chname);
                  len += strlen(chptr->chname);
                  (void)strcat(buf + len, " ");
                  len++;
                }
            }
          if (buf[0] != '\0')
            sendto_one(sptr, form_str(RPL_WHOISCHANNELS),
                       mename, parv[0], name, buf);
         
#ifdef SERVERHIDE
          if (!(IsAnOper(sptr) || acptr == sptr))
            sendto_one(sptr, form_str(RPL_WHOISSERVER),
                       mename, parv[0], name, NetworkName,
                       NetworkDesc);
          else    
#endif
          sendto_one(sptr, form_str(RPL_WHOISSERVER),
                     mename, parv[0], name, user->server,
                     a2cptr?a2cptr->info:"*Not On This Net*");

          if (user->away)
            sendto_one(sptr, form_str(RPL_AWAY), mename,
                       parv[0], name, user->away);



  		  if (IsNetAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                           mename, parv[0], name, rpl_nadmin);
		  else if (IsTechAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                           mename, parv[0], name, rpl_tadmin);						   
          else if (IsSAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                           mename, parv[0], name, rpl_sadmin);						   
          else if (IsAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),  
                           mename, parv[0], name, rpl_admin);
          else if (IsAnOper(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR), 
                           mename, parv[0], name, rpl_oper);


#ifdef WHOIS_NOTICE
          if ((MyOper(acptr)) && ((acptr)->umodes & UMODE_SPY) &&
              (MyConnect(sptr)) && (IsPerson(sptr)) && (acptr != sptr))
            sendto_one(acptr,
                       ":%s NOTICE %s :*** Notice -- %s (%s@%s) is doing a /whois on you.",
                       mename, acptr->name, parv[0], sptr->username,
                       sptr->realhost);
#endif /* #ifdef WHOIS_NOTICE */

          if ((acptr->user
#ifdef SERVERHIDE
              && IsAnOper(sptr) 
#endif                 
              && MyConnect(acptr)))
            sendto_one(sptr, form_str(RPL_WHOISIDLE),
                       mename, parv[0], name,
                       CurrentTime - user->last,
                       acptr->firsttime);

		if(hits>50)
		  {
  			sendto_one(sptr,":%s NOTICE %s :Aborting /whois output as flood prevention",
				mename, sptr->name);			  
			break;
		  }
        }
		
      if (!found)	  
        sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                   mename, parv[0], nick);
	  else
		sendto_one(sptr,":%s NOTICE %s :This /whois matched \2%i\2 user(s)", 
			mename, sptr->name,hits);
      /*
      if (p)
        p[-1] = ',';
        */
    }

  sendto_one(sptr, form_str(RPL_ENDOFWHOIS), mename, parv[0], parv[1]);
  
  return 0;
}