Ejemplo n.º 1
0
/*
 * m_kick - generic message handler
 *
 * parv[0] = sender prefix
 * parv[1] = channel
 * parv[2] = client to kick
 * parv[parc-1] = kick comment
 */
int m_kick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Client *who;
  struct Channel *chptr;
  struct Membership *member = 0;
  char *name, *comment;

  ClrFlag(sptr, FLAG_TS8);

  if (parc < 3 || *parv[1] == '\0')
    return need_more_params(sptr, "KICK");

  name = parv[1];

  /* simple checks */
  if (!(chptr = get_channel(sptr, name, CGT_NO_CREATE)))
    return send_reply(sptr, ERR_NOSUCHCHANNEL, name);

  if (!is_chan_op(sptr, chptr)  && !is_half_op(sptr, chptr))
    return send_reply(sptr, ERR_CHANOPRIVSNEEDED, name);

  if (!(who = find_chasing(sptr, parv[2], 0)))
    return 0; /* find_chasing sends the reply for us */

  /* Don't allow the channel service to be kicked */
  /*
   * ASUKA_X:
   * Allow +X'ed users to kick +k'ed, but not U-lined services.
   * --Bigfoot
   */
  if (IsChannelService(who) && IsService(cli_user(who)->server))
    return send_reply(sptr, ERR_ISCHANSERVICE, cli_name(who), chptr->chname, "a network service");

  if (IsChannelService(who) && !IsXtraOp(sptr) && (who!=sptr))
    return send_reply(sptr, ERR_ISCHANSERVICE, cli_name(who), chptr->chname, "an IRC operator");

  /* Don't allow halfops to kick chanops */
  if (is_chan_op(who, chptr) && is_half_op(sptr, chptr) && !is_chan_op(sptr, chptr))
     return send_reply(sptr, ERR_HALFCANTKICKOP, name);

  /* Prevent kicking opers from local channels -DM- */
  if (IsLocalChannel(chptr->chname) && HasPriv(who, PRIV_DEOP_LCHAN))
    return send_reply(sptr, ERR_ISOPERLCHAN, cli_name(who), chptr->chname);

  /* check if kicked user is actually on the channel */
  if (!(member = find_member_link(chptr, who)) || IsZombie(member))
    return send_reply(sptr, ERR_USERNOTINCHANNEL, cli_name(who), chptr->chname);

  /* We rely on ircd_snprintf to truncate the comment */
  comment = EmptyString(parv[parc - 1]) ? parv[0] : parv[parc - 1];

  if (!IsLocalChannel(name))
    sendcmdto_serv_butone(sptr, CMD_KICK, cptr, "%H %C :%s", chptr, who,
			  comment);

  sendcmdto_channel_butserv_butone((IsServer(sptr) ? &me : sptr), CMD_KICK,
				   chptr, NULL, 0, "%H %C :%s", chptr, who,
				   comment);

  make_zombie(member, who, cptr, sptr, chptr);

  return 0;
}
Ejemplo n.º 2
0
/*
 * ms_svshost - SVSHOST command handler
 *      parv[0] = sender prefix
 *      parv[1] = remote server
 *      parv[2] = client nick
 *      parv[3] = vhost to spoof
 */
static void ms_svshost(struct Client* client_p, struct Client* source_p,
                      int parc, char* parv[])
{
  char *flag;
  struct Client *victim;
  struct Channel *chptr, *top_chptr, *banchans[100];
  static char comment[] = "Spoofing with vhost...";
  static char urbanned[] = "You are banned";
  char modebuf[MODEBUFLEN], parabuf[MODEBUFLEN];
  int hide_or_not;
  dlink_node *ptr;
  int i, num = 0;
  
  if (ServerInfo.gateway && get_bridge_token(client_p))
  	return;

  if (hunt_server(client_p, source_p, ":%s SVSHOST %s %s :%s", 
		  1, parc, parv) != HUNTED_ISME)
    return;

  if (!find_z_conf(parv[0]))
    return;
    
  victim = find_client(parv[2]);
  if (victim && !IsServer(victim) && MyConnect(victim))
  {
  	extern int introduce_client(struct Client *, struct Client *,
  		struct User *, char *);
  
  	sendto_server(NULL, victim, NULL, NOCAPS, NOCAPS,
		NOFLAGS, ":%s QUIT :%s", victim->name, comment);

/*	sendto_common_channels_local(victim, ":%s!%s@%s QUIT :%s",
		victim->name, victim->username, victim->host, comment);*/
		
/*	++current_serial;	not needed i suppose */

	if (victim->user->channel.head)
	for (ptr = victim->user->channel.head; ptr; ptr = ptr->next) {
		chptr = (struct Channel *)ptr->data;
		
		sendto_channel_local_butone(victim, ALL_MEMBERS, 
			chptr, ":%s!%s@%s QUIT :%s",
			victim->name, victim->username,
			victim->host, comment);
	}
	
	strncpy(victim->host, parv[3], HOSTLEN)[HOSTLEN] = 0;
	
	sendto_one(victim, ":%s NOTICE %s :*** Notice -- Spoofing your host as %s",
		me.name, victim->name, victim->host);
	
	if (victim->user->channel.head)
	for (ptr = victim->user->channel.head; ptr; ptr = ptr->next) {
		chptr = (struct Channel *)ptr->data;
		
#ifdef VCHANS
		top_chptr = RootChan(chptr);
#else
		top_chptr = chptr;
#endif		
		if (is_banned(chptr, victim) & (CHFL_BAN|CHFL_DENY)) {
			sendto_one(victim, ":%s KICK %s %s :%s",
				me.name, top_chptr->chname, victim->name,
				urbanned);
			
			/*remove_user_from_channel(chptr, victim);*/
			banchans[num++] = chptr;
			continue;
		}
		
		if (is_chan_op(chptr, victim)) 
			flag = "+o";
#ifdef HALFOPS			
		else if (is_half_op(chptr, victim)) 
			flag = "+h";
#endif			
		else if (is_voiced(chptr, victim))
			flag = "+v";
		else flag = "";
#ifdef REQUIRE_OANDV
		if (find_user_link(&chptr->chanops_voiced, victim))
			flag = "+ov";
#endif
		sendto_channel_local_butone(victim, ALL_MEMBERS, 
			chptr, ":%s!%s@%s JOIN :%s",
			victim->name, victim->username,
			victim->host, top_chptr->chname);
			
#ifdef ANONOPS
		if (chptr->mode.mode & MODE_HIDEOPS)
			hide_or_not = ONLY_CHANOPS_HALFOPS;
		else
#endif
			hide_or_not = ALL_MEMBERS;
			
		if (flag[0])
		sendto_channel_local_butone(victim, hide_or_not,
			chptr, ":%s MODE %s %s %s %s",
			me.name, top_chptr->chname, flag,
			victim->name, flag[2]? victim->name : "");		
	}
	
	for (i=0; i < num; i++)
		remove_user_from_channel(banchans[i], victim);
	
	introduce_client(NULL, victim, victim->user, victim->name);
	
	victim->lazyLinkClientExists = 0;	/* force introducing to LL servers below... */
	
	if (victim->user->channel.head)
	for (ptr = victim->user->channel.head; ptr; ptr = ptr->next) {
		chptr = (struct Channel *)ptr->data;
		
		if (is_chan_op(chptr, victim)) 
			flag = "@";
#ifdef HALFOPS			
		else if (is_half_op(chptr, victim)) 
			flag = "%";
#endif			
		else if (is_voiced(chptr, victim))
			flag = "+";
		else flag = "";
#ifdef REQUIRE_OANDV
		if (find_user_link(&chptr->chanops_voiced, victim))
			flag = "@+";
#endif
		channel_modes(chptr, victim, modebuf, parabuf);
		sendto_server(NULL, victim, chptr, NOCAPS, NOCAPS,
			LL_ICLIENT|LL_ICHAN, ":%s SJOIN %lu %s %s %s :%s%s",
			me.name, (unsigned long)chptr->channelts,
			chptr->chname, modebuf, parabuf, 
			flag, victim->name);
	}
  }
}
Ejemplo n.º 3
0
void checkClient(struct Client *sptr, struct Client *acptr)
{
   struct Channel *chptr;
   struct Membership *lp;
   char outbuf[BUFSIZE];
   char *privs;
   time_t nowr;

   /* Header */
   send_reply(sptr, RPL_DATASTR, " ");
   send_reply(sptr, RPL_CHKHEAD, "user", acptr->cli_name);
   send_reply(sptr, RPL_DATASTR, " ");

   ircd_snprintf(0, outbuf, sizeof(outbuf), "           Nick:: %s (%s%s)", acptr->cli_name, NumNick(acptr));
   send_reply(sptr, RPL_DATASTR, outbuf);

   if (MyUser(acptr))
   {  
      ircd_snprintf(0, outbuf, sizeof(outbuf),  "      Signed on:: %s", myctime(acptr->cli_firsttime));
      send_reply(sptr, RPL_DATASTR, outbuf);
   }

   ircd_snprintf(0, outbuf, sizeof(outbuf), "      Timestamp:: %s (%d)", myctime(acptr->cli_lastnick), acptr->cli_lastnick);
   send_reply(sptr, RPL_DATASTR, outbuf);

   ircd_snprintf(0, outbuf, sizeof(outbuf), "  User/Hostmask:: %s@%s (%s)", acptr->cli_user->username, acptr->cli_user->host,
   ircd_ntoa((const char*) &(cli_ip(acptr))));
   send_reply(sptr, RPL_DATASTR, outbuf);

   if (((feature_int(FEAT_HOST_HIDING_STYLE) == 1) ? HasHiddenHost(acptr) : IsHiddenHost(acptr)) || IsSetHost(acptr))
   {
      ircd_snprintf(0, outbuf, sizeof(outbuf), " Real User/Host:: %s@%s", acptr->cli_user->realusername, acptr->cli_user->realhost);
      send_reply(sptr, RPL_DATASTR, outbuf);
   }

   ircd_snprintf(0, outbuf, sizeof(outbuf), "      Real Name:: %s%c", cli_info(acptr), COLOR_OFF);
   send_reply(sptr, RPL_DATASTR, outbuf);

   if (IsService(cli_user(acptr)->server)) {
     if (acptr)
       send_reply(sptr, RPL_DATASTR, "         Status:: Network Service");
     else if (IsAdmin(acptr))
       send_reply(sptr, RPL_DATASTR, "         Status:: IRC Administrator (service)");
     else if (IsAnOper(acptr))
       send_reply(sptr, RPL_DATASTR, "         Status:: IRC Operator (service)");
     else 
       send_reply(sptr, RPL_DATASTR, "         Status:: Client (service)");
   } else if (IsAdmin(acptr)) {
     send_reply(sptr, RPL_DATASTR, "         Status:: IRC Administrator");
   } else if (IsAnOper(acptr)) {
     send_reply(sptr, RPL_DATASTR, "         Status:: IRC Operator");
   } else {
     send_reply(sptr, RPL_DATASTR, "         Status:: Client");
   }

   if (MyUser(acptr)) {
     ircd_snprintf(0, outbuf, sizeof(outbuf), "          Class:: %s", get_client_class(acptr));
     send_reply(sptr, RPL_DATASTR, outbuf);
   }

   privs = client_print_privs(acptr);
   if (strlen(privs) > 1)
     client_check_privs(acptr, sptr);

   ircd_snprintf(0, outbuf, sizeof(outbuf), "   Connected to:: %s", cli_name(acptr->cli_user->server));
   send_reply(sptr, RPL_DATASTR, outbuf);

   if (cli_version(acptr)) {
     if (strlen(cli_version(acptr)) > 0) {
       ircd_snprintf(0, outbuf, sizeof(outbuf), "   CTCP Version:: %s", cli_version(acptr));
       send_reply(sptr, RPL_DATASTR, outbuf);
     }
   }

   if (cli_user(acptr) && !EmptyString(cli_user(acptr)->swhois)) {
     ircd_snprintf(0, outbuf, sizeof(outbuf), "         SWHOIS:: %s", cli_user(acptr)->swhois);
     send_reply(sptr, RPL_DATASTR, outbuf);
   }

   if (cli_webirc(acptr)) {
     if (strlen(cli_webirc(acptr)) > 0) {
       ircd_snprintf(0, outbuf, sizeof(outbuf), "         WebIRC:: %s", cli_webirc(acptr));
       send_reply(sptr, RPL_DATASTR, outbuf);
     }
   }

   if (cli_sslclifp(acptr) && (strlen(cli_sslclifp(acptr)) > 0)) {
     ircd_snprintf(0, outbuf, sizeof(outbuf), "SSL Fingerprint:: %s", cli_sslclifp(acptr));
     send_reply(sptr, RPL_DATASTR, outbuf);
   }

   if (MyUser(acptr))
     get_eflags(sptr, acptr);

   /* +s (SERV_NOTICE) is not relayed to us from remote servers,
    * so we cannot tell if a remote client has that mode set.
    * And hacking it onto the end of the output of umode_str is EVIL BAD AND WRONG
    * (and breaks if the user is +r) so we won't do that either.
    */

   if (strlen(umode_str(acptr)) < 1)
      strcpy(outbuf, "       Umode(s):: <none>");
   else
      ircd_snprintf(0, outbuf, sizeof(outbuf), "       Umode(s):: +%s", umode_str(acptr));

   send_reply(sptr, RPL_DATASTR, outbuf);

   if (acptr->cli_user->joined == 0)
      send_reply(sptr, RPL_DATASTR, "     Channel(s):: <none>");
   else if (acptr->cli_user->joined > 50) 
   {

      /* NB. As a sanity check, we DO NOT show the individual channels the
       *     client is on if it is on > 50 channels.  This is to prevent the ircd
       *     barfing ala Uworld when someone does /quote check Q :).. (I shouldn't imagine
       *     an Oper would want to see every single channel 'x' client is on anyway if
       *     they are on *that* many).
       */

      ircd_snprintf(0, outbuf, sizeof(outbuf), "     Channel(s):: - (total: %u)", acptr->cli_user->joined);
      send_reply(sptr, RPL_DATASTR, outbuf);
   }
   else
   {
      char chntext[BUFSIZE];
      int len = strlen("     Channel(s):: ");
      int mlen = strlen(me.cli_name) + len + strlen(sptr->cli_name);
      *chntext = '\0';

      strcpy(chntext, "     Channel(s):: ");
      for (lp = acptr->cli_user->channel; lp; lp = lp->next_channel) {
         chptr = lp->channel;
         if (len + strlen(chptr->chname) + mlen > BUFSIZE - 5) {
            send_reply(sptr, RPL_DATASTR, chntext);
            *chntext = '\0';
            strcpy(chntext, "     Channel(s):: ");
            len = strlen(chntext);
         }
         if (IsDeaf(acptr))
            *(chntext + len++) = '-';
         if (is_chan_op(acptr, chptr))
            *(chntext + len++) = '@';
         if (is_half_op(acptr, chptr))
            *(chntext + len++) = '%';
         if (IsOper(sptr) && !ShowChannel(sptr,chptr))
            *(chntext + len++) = '*';
         if (IsZombie(lp))
            *(chntext + len++) = '!';
         if (len)
            *(chntext + len) = '\0';

         strcpy(chntext + len, chptr->chname);
         len += strlen(chptr->chname);
         strcat(chntext + len, " ");
         len++;
      }

      if (chntext[0] != '\0')
        send_reply(sptr, RPL_DATASTR, chntext);
   }

   /* If client processing command ISN'T target (or a registered
    * Network Service), show idle time since the last time we
    * parsed something.
    */
   if (MyUser(acptr) && !(IsService(acptr) == -1) && !(strCasediff(acptr->cli_name, sptr->cli_name) == 0)) {
      nowr = CurrentTime - acptr->cli_user->last;
      ircd_snprintf(0, outbuf, sizeof(outbuf), "       Idle for:: %d days, %02ld:%02ld:%02ld",
         nowr / 86400, (nowr / 3600) % 24, (nowr / 60) % 60, nowr % 60);
      send_reply(sptr, RPL_DATASTR, outbuf);
   }

   /* Away message (if applicable) */
   if (acptr->cli_user->away) {
      ircd_snprintf(0, outbuf, sizeof(outbuf), "   Away message:: %s", acptr->cli_user->away);
      send_reply(sptr, RPL_DATASTR, outbuf);
   }

   /* If local user.. */

   if (MyUser(acptr)) {
      send_reply(sptr, RPL_DATASTR, " ");
      ircd_snprintf(0, outbuf, sizeof(outbuf), "          Ports:: %d -> %d (client -> server)",
         cli_port(acptr), cli_listener(acptr)->port);
      send_reply(sptr, RPL_DATASTR, outbuf);
      if (feature_bool(FEAT_CHECK_EXTENDED)) {
        /* Note: sendq = receiveq for a client (it makes sense really) */
        ircd_snprintf(0, outbuf, sizeof(outbuf), "      Data sent:: %u.%0.3u Kb (%u protocol messages)",
           cli_receiveK(acptr), cli_receiveB(acptr), cli_receiveM(acptr));
        send_reply(sptr, RPL_DATASTR, outbuf);                          
        ircd_snprintf(0, outbuf, sizeof(outbuf), "  Data received:: %u.%0.3u Kb (%u protocol messages)",
           cli_sendK(acptr), cli_sendB(acptr), cli_sendM(acptr));                                       
        send_reply(sptr, RPL_DATASTR, outbuf);
        ircd_snprintf(0, outbuf, sizeof(outbuf), "  receiveQ size:: %d bytes (max. %d bytes)",
           DBufLength(&(cli_recvQ(acptr))), feature_int(FEAT_CLIENT_FLOOD));
        send_reply(sptr, RPL_DATASTR, outbuf);
        ircd_snprintf(0, outbuf, sizeof(outbuf), "     sendQ size:: %d bytes (max. %d bytes)",
           DBufLength(&(cli_sendQ(acptr))), get_sendq(acptr));                                
        send_reply(sptr, RPL_DATASTR, outbuf);                
      }
   }
   
   /* Send 'END OF CHECK' message */
   send_reply(sptr, RPL_ENDOFCHECK, " ");
}
Ejemplo n.º 4
0
signed int checkHostmask(struct Client *sptr, char *hoststr, int flags) {
  struct Client *acptr;
  struct Channel *chptr;
  struct Membership *lp;
  int count = 0, found = 0, cidr_check_bits = 0;
  char outbuf[BUFSIZE];
  char targhost[NICKLEN + USERLEN + HOSTLEN + 3], curhost[NICKLEN + USERLEN + HOSTLEN + 3];
  char nickm[NICKLEN + 1], userm[USERLEN + 1], hostm[HOSTLEN + 1];
  char *p = NULL;
  struct in_addr cidr_check;

  strcpy(nickm,"*");
  strcpy(userm,"*");
  strcpy(hostm,"*");

  if (!strchr(hoststr, '!') && !strchr(hoststr, '@'))
    ircd_strncpy(hostm,hoststr,HOSTLEN);
  else {
    if ((p = strchr(hoststr, '@'))) {
      *p++ = '\0';
      if (*p) ircd_strncpy(hostm,p, HOSTLEN);
    }

    /* Get the nick!user mask */
    if ((p = strchr(hoststr, '!'))) {
      *p++ = '\0';
      if (*p) ircd_strncpy(userm,p,USERLEN);
      if (*hoststr) ircd_strncpy(nickm,hoststr,NICKLEN);
    }
    else if (*hoststr) {
      /* Durz: We should only do the following *IF* the hoststr has not already been
       * copied into hostm (ie. neither ! or @ specified).. otherwise, when we do
       * /quote check *.barrysworld.com - we end up with targhost as: *!*.barryswo@*.barrysworld.com
       */
      ircd_strncpy(userm,hoststr,USERLEN);
    }
  }
  
  if ((p = strchr(hostm, '/')) || inet_aton(hostm, &cidr_check)) {
    if (p)
      *p = '\0';
    if (inet_aton(hostm, &cidr_check)) {
      cidr_check_bits = p ? atoi(p + 1) : 32;
      if ((cidr_check_bits >= 0) && (cidr_check_bits <= 32)) {
        flags |= CHECK_CIDRMASK;
        cidr_check.s_addr &= NETMASK(cidr_check_bits);
      }
    }
    if (p)
      *p = '/';
  }

  /* Copy formatted string into "targhost" buffer */
  ircd_snprintf(0, targhost, sizeof(targhost),  "%s!%s@%s", nickm, userm, hostm);

  targhost[sizeof(targhost) - 1] = '\0';

  /* Note: we have to exclude the last client struct as it is not a real client
   * structure, and therefore any attempt to access elements in it would cause
   * a segfault.
   */

  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
    /* Dont process if acptr is a unregistered client, a server or a ping */
    if (!IsRegistered(acptr) || IsServer(acptr))
      continue;

    if (IsMe(acptr))   /* Always the last acptr record */
      break;

    if(count > feature_int(FEAT_MAX_CHECK_OUTPUT)) { /* sanity stuff */
      ircd_snprintf(0, outbuf, sizeof(outbuf), "More than %d results, truncating...", count);
      send_reply(sptr, RPL_DATASTR, outbuf);
      send_reply(sptr, RPL_ENDOFCHECK, " ");
      break;
    }

    /* Copy host info into buffer */
    curhost[0] = '\0';
    ircd_snprintf(0, curhost, sizeof(curhost), "%s!%s@%s", acptr->cli_name, acptr->cli_user->realusername, acptr->cli_user->realhost);

    if (flags & CHECK_CIDRMASK) {
      if (((cli_ip(acptr).s_addr & NETMASK(cidr_check_bits)) == cidr_check.s_addr) && !match(nickm, acptr->cli_name) 
            && (!match(userm, acptr->cli_user->realusername) || !match(userm, acptr->cli_user->username)))
        found = 1;
    }
    else {
      if(match((const char*)targhost,(const char*)curhost) == 0)
        found = 1;
      else {
        curhost[0] = '\0';
        ircd_snprintf(0, curhost, sizeof(curhost), "%s!%s@%s", acptr->cli_name, acptr->cli_user->username, acptr->cli_user->host);

        if(match((const char*)targhost,(const char*)curhost) == 0)
          found = 1;
      }
    }

    if (found == 1) {
      found = 0;  /* reset that so it doesn't get crazy go nuts */

      /* Show header if we've found at least 1 record */
      if (count == 0) {
        /* Output header */ 
        send_reply(sptr, RPL_DATASTR, " ");
        send_reply(sptr, RPL_CHKHEAD, "host", targhost);

        send_reply(sptr, RPL_DATASTR, " ");
        ircd_snprintf(0, outbuf, sizeof(outbuf),  "%s   %-*s%-*s%s", "No.", (NICKLEN + 2 ), "Nick",
                (USERLEN + 2), "User", "Host");
        send_reply(sptr, RPL_DATASTR, outbuf);
      }

      ircd_snprintf(0, outbuf, sizeof(outbuf), "%-4d  %-*s%-*s%s", (count+1), (NICKLEN + 2),
            acptr->cli_name, (USERLEN + 2), acptr->cli_user->realusername, 
            (flags & CHECK_SHOWIPS) ? ircd_ntoa((const char*)&(cli_ip(acptr))) : acptr->cli_user->realhost);
      send_reply(sptr, RPL_DATASTR, outbuf);

      /* Show channel output (if applicable) - the 50 channel limit sanity check
       * is specifically to prevent coredumping when someone lamely tries to /check
       * Q or some other channel service...
       */
      if (flags & CHECK_CHECKCHAN) {
        if (acptr->cli_user->joined > 0 && acptr->cli_user->joined <= 50) {
          char chntext[BUFSIZE];
          int len = strlen("      on channels: ");
          int mlen = strlen(me.cli_name) + len + strlen(sptr->cli_name);
          *chntext = '\0';

          strcpy(chntext, "      on channels: ");
          for (lp = acptr->cli_user->channel; lp; lp = lp->next_channel) {
            chptr = lp->channel;
            if (len + strlen(chptr->chname) + mlen > BUFSIZE - 5) {
              send_reply(sptr, RPL_DATASTR, chntext);
              *chntext = '\0';
              strcpy(chntext, "      on channels: ");
              len = strlen(chntext);
            }
            if (IsDeaf(acptr))
              *(chntext + len++) = '-';
            if (is_chan_op(acptr, chptr))
              *(chntext + len++) = '@';
            if (is_half_op(acptr, chptr))
              *(chntext + len++) = '%';
            if (IsOper(sptr) && !ShowChannel(sptr,chptr))
              *(chntext + len++) = '*';
            else if (has_voice(acptr, chptr))
              *(chntext + len++) = '+';
            else if (IsZombie(lp))
              *(chntext + len++) = '!';
            if (len)
              *(chntext + len) = '\0';

            strcpy(chntext + len, chptr->chname);
            len += strlen(chptr->chname);
            strcat(chntext + len, " ");
            len++;
          }
          if (chntext[0] != '\0')
            send_reply(sptr, RPL_DATASTR, chntext);

          send_reply(sptr, RPL_DATASTR, " ");
        }
      }
      count++;
    }
  }

  if (count > 0) {
    send_reply(sptr, RPL_DATASTR, " ");

    ircd_snprintf(0, outbuf, sizeof(outbuf), "Matching records found:: %d", count);
    send_reply(sptr, RPL_DATASTR, outbuf);

    send_reply(sptr, RPL_ENDOFCHECK, " ");
  }

  return count;
}
Ejemplo n.º 5
0
/*
 * m_invite - generic message handler
 *
 *   parv[0] - sender prefix
 *   parv[1] - user to invite
 *   parv[2] - channel name
 *
 * - INVITE now is accepted only if who does it is chanop (this of course
 *   implies that channel must exist and he must be on it).
 *
 * - On the other side it IS processed even if channel is NOT invite only
 *   leaving room for other enhancements like inviting banned ppl.  -- Nemesi
 *
 * - Invite with no parameters now lists the channels you are invited to.
 *                                                         - Isomer 23 Oct 99
 */
int m_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client *acptr;
  struct Channel *chptr;
  
  if (parc < 2 ) { 
    /*
     * list the channels you have an invite to.
     */
    struct SLink *lp;
    for (lp = cli_user(sptr)->invited; lp; lp = lp->next)
      send_reply(cptr, RPL_INVITELIST, lp->value.chptr->chname);
    send_reply(cptr, RPL_ENDOFINVITELIST);
    return 0;
  }
  
  if (parc < 3 || EmptyString(parv[2]))
    return need_more_params(sptr, "INVITE");

  if (!(acptr = FindUser(parv[1]))) {
    send_reply(sptr, ERR_NOSUCHNICK, parv[1]);
    return 0;
  }

  if (is_silenced(sptr, acptr) && !is_silence_exempted(sptr, acptr))
    return 0;

  clean_channelname(parv[2]);

  if (!IsChannelPrefix(*parv[2]))
    return 0;

  /* bad channel name */
  if (!IsChannelName(parv[2]) || HasCntrl(parv[2])) {
    send_reply(sptr, ERR_NOSUCHCHANNEL, parv[2]);
    return 0;
  }

  if (!(chptr = FindChannel(parv[2]))) {
    send_reply(sptr, ERR_NOTONCHANNEL, parv[2]);
    return 0;
  }

  if (!find_channel_member(sptr, chptr)) {
    send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
    return 0;
  }

  if (find_channel_member(acptr, chptr)) {
    send_reply(sptr, ERR_USERONCHANNEL, cli_name(acptr), chptr->chname);
    return 0;
  }

  if (!is_chan_op(sptr, chptr) && !is_half_op(sptr, chptr)) {
    send_reply(sptr, ERR_CHANOPRIVSNEEDED, chptr->chname);
    return 0;
  }

  /* If we get here, it was a VALID and meaningful INVITE */

  if (IsAccountOnly(acptr) && !IsAccount(sptr) && !IsOper(sptr)) {
    send_reply(sptr, ERR_ACCOUNTONLY, cli_name(acptr), "INVITE");
    return 0;
  }

  if (IsPrivDeaf(acptr) && !IsOper(sptr)) {
    send_reply(sptr, ERR_PRIVDEAF, cli_name(sptr), "INVITE",
               cli_name(acptr));
    return 0;
  }

  if (IsCommonChansOnly(acptr) && !IsAnOper(sptr) && !common_chan_count(acptr, sptr, 1)) {
    send_reply(sptr, ERR_COMMONCHANSONLY, cli_name(acptr), "INVITE");
    return 0;
  }

  if (check_target_limit(sptr, acptr, cli_name(acptr), 0))
    return 0;

  send_reply(sptr, RPL_INVITING, cli_name(acptr), chptr->chname);

  if (cli_user(acptr)->away)
    send_reply(sptr, RPL_AWAY, cli_name(acptr), cli_user(acptr)->away);

  if (MyConnect(acptr)) {
    add_invite(acptr, chptr);
    sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%H", cli_name(acptr), chptr);
  } else {
    sendcmdto_one(sptr, CMD_INVITE, acptr, "%s %H %Tu", cli_name(acptr), chptr,
                  chptr->creationtime);
  }

  if (!IsLocalChannel(chptr->chname) || MyConnect(acptr)) {
    if (feature_bool(FEAT_ANNOUNCE_INVITES)) {
      /* Announce to channel operators. */
      sendcmdto_channel_butserv_butone(feature_bool(FEAT_HIS_HIDEWHO) ? &his : &me, 
				       get_error_numeric(RPL_ISSUEDINVITE)->str,
                                       NULL, chptr, sptr, SKIP_NONOPS,
                                       "%H %C %C :%C has been invited by %C",
                                       chptr, acptr, sptr, acptr, sptr);
      /* Announce to servers with channel operators. */
      sendcmdto_channel_servers_butone(sptr, NULL, TOK_INVITE, chptr, acptr, SKIP_NONOPS,
                                       "%s %H %Tu", cli_name(acptr),
                                       chptr, chptr->creationtime);
    }
  }

  return 0;
}