Esempio n. 1
0
static void
mo_chghost(struct Client *client_p, struct Client *source_p,
           int parc, char *parv[])
{
  struct Client *target_p = NULL;

  if (MyClient(source_p) && !IsOperAdmin(source_p))
  {
    sendto_one(source_p, form_str(ERR_NOPRIVS),
               me.name, source_p->name, "CHGHOST");
    return;
  }

  if (EmptyString(parv[2]))
  {
    parv[2] = parv[1];
    target_p = source_p;

    if (!IsClient(target_p))
      return;
  }
  else {
    target_p = find_client(parv[1]);

    if (target_p == NULL || !IsClient(target_p))
    {
      sendto_one(source_p, form_str(ERR_NOSUCHNICK),
                 me.name, source_p->name, parv[1]);
      return;
    }
  }

  if (strlen(parv[2]) > HOSTLEN || !*parv[2] || !valid_hostname(parv[2]))
  {
    sendto_one(source_p, ":%s NOTICE %s :Invalid hostname",
               me.name, source_p->name);
    return;
  }

  if (IsUserHostIp(target_p))
    delete_user_host(target_p->username, target_p->host, !MyConnect(target_p));

  strlcpy(target_p->host, parv[2], sizeof(target_p->host));
  SetIPSpoof(target_p);

  add_user_host(target_p->username, target_p->host, !MyConnect(target_p));
  SetUserHost(target_p);

  if (MyClient(source_p))
  {
    sendto_server(client_p, NULL, NOCAPS, NOCAPS, ":%s ENCAP * CHGHOST %s %s",
                  source_p->name, target_p->name, parv[2]);
    sendto_one(source_p, ":%s NOTICE %s :%s changed to %s@%s",
               me.name, source_p->name, target_p->name, target_p->username,
               target_p->host);
  }

  if (MyConnect(target_p) && IsClient(source_p))
    sendto_one(target_p, ":%s NOTICE %s :You are now %s@%s",
               me.name, target_p->name, target_p->username, target_p->host);
}
Esempio n. 2
0
/*
** m_kick
**      parv[0] = sender prefix
**      parv[1] = channel
**      parv[2] = client to kick
**      parv[3] = kick comment
*/
static int
m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct membership *msptr;
	struct Client *who;
	struct Channel *chptr;
	int chasing = 0;
	char *comment;
	const char *name;
	char *p = NULL;
	const char *user;
	static char buf[BUFSIZE];

	if(MyClient(source_p) && !IsFloodDone(source_p))
		flood_endgrace(source_p);

	comment = LOCAL_COPY((EmptyString(parv[3])) ? parv[2] : parv[3]);
	if(strlen(comment) > (size_t) REASONLEN)
		comment[REASONLEN] = '\0';

	*buf = '\0';
	if((p = strchr(parv[1], ',')))
		*p = '\0';

	name = parv[1];

	chptr = find_channel(name);
	if(chptr == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name);
		return 0;
	}

	if(!IsServer(source_p))
	{
		msptr = find_channel_membership(chptr, source_p);

		if((msptr == NULL) && MyConnect(source_p))
		{
			sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
					   form_str(ERR_NOTONCHANNEL), name);
			return 0;
		}

		if(!is_chanop(msptr))
		{
			if(MyConnect(source_p))
			{
				sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
					   me.name, source_p->name, name);
				return 0;
			}

			/* If its a TS 0 channel, do it the old way */
			if(chptr->channelts == 0)
			{
				sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
					   get_id(&me, source_p), get_id(source_p, source_p), name);
				return 0;
			}
		}

		/* Its a user doing a kick, but is not showing as chanop locally
		 * its also not a user ON -my- server, and the channel has a TS.
		 * There are two cases we can get to this point then...
		 *
		 *     1) connect burst is happening, and for some reason a legit
		 *        op has sent a KICK, but the SJOIN hasn't happened yet or 
		 *        been seen. (who knows.. due to lag...)
		 *
		 *     2) The channel is desynced. That can STILL happen with TS
		 *        
		 *     Now, the old code roger wrote, would allow the KICK to 
		 *     go through. Thats quite legit, but lets weird things like
		 *     KICKS by users who appear not to be chanopped happen,
		 *     or even neater, they appear not to be on the channel.
		 *     This fits every definition of a desync, doesn't it? ;-)
		 *     So I will allow the KICK, otherwise, things are MUCH worse.
		 *     But I will warn it as a possible desync.
		 *
		 *     -Dianora
		 */
	}

	if((p = strchr(parv[2], ',')))
		*p = '\0';

	user = parv[2];		/* strtoken(&p2, parv[2], ","); */

	if(!(who = find_chasing(source_p, user, &chasing)))
	{
		return 0;
	}

	msptr = find_channel_membership(chptr, who);

	if(msptr != NULL)
	{
		if(MyClient(source_p) && IsService(who))
		{
			sendto_one(source_p, form_str(ERR_ISCHANSERVICE),
				   me.name, source_p->name, who->name, chptr->chname);
			return 0;
		}

		/* jdc
		 * - In the case of a server kicking a user (i.e. CLEARCHAN),
		 *   the kick should show up as coming from the server which did
		 *   the kick.
		 * - Personally, flame and I believe that server kicks shouldn't
		 *   be sent anyways.  Just waiting for some oper to abuse it...
		 */
		if(IsServer(source_p))
			sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s",
					     source_p->name, name, who->name, comment);
		else
			sendto_channel_local(ALL_MEMBERS, chptr,
					     ":%s!%s@%s KICK %s %s :%s",
					     source_p->name, source_p->username,
					     source_p->host, name, who->name, comment);

		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s KICK %s %s :%s",
			      use_id(source_p), chptr->chname, use_id(who), comment);
		sendto_server(client_p, chptr, NOCAPS, CAP_TS6,
			      ":%s KICK %s %s :%s",
			      source_p->name, chptr->chname, who->name, comment);
		remove_user_from_channel(msptr);
	}
	else if (MyClient(source_p))
		sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
				   form_str(ERR_USERNOTINCHANNEL), user, name);

	return 0;
}
Esempio n. 3
0
/*
 * ms_svsnick()
 *
 *     parv[0] = sender prefix
 *     parv[1] = oldnick
 *     parv[2] = newnick
 */
static void
ms_svsnick (struct Client *client_p, struct Client *source_p,
	    int parc, char *parv[])
{
  char oldnick[NICKLEN];
  char newnick[NICKLEN];
  struct Client *oldnickname;
  struct Client *newnickname;

  if (!IsServer (source_p))
    return;

  if (parc < 3 || !parv[1] || !parv[2])
    {
      sendto_one (source_p, form_str (ERR_NONICKNAMEGIVEN), me.name, parv[0]);
      return;
    }

  /* terminate nick to NICKLEN */
  strlcpy (oldnick, parv[1], NICKLEN);
  strlcpy (newnick, parv[2], NICKLEN);

  if (!clean_nick_name (oldnick))
    {
      sendto_one (source_p, form_str (ERR_ERRONEUSNICKNAME),
		  me.name, parv[0], oldnick);
      return;
    }

  /* check the nickname is ok */
  if (!clean_nick_name (newnick))
    {
      sendto_one (source_p, form_str (ERR_ERRONEUSNICKNAME),
		  me.name, parv[0], newnick);
      return;
    }

  if (!(oldnickname = find_client (oldnick)))
    {
      sendto_one (source_p, form_str (ERR_NOSUCHNICK), me.name,
		  source_p->name, oldnick);
      return;
    }

  if ((newnickname = find_client (newnick)))
    {
      sendto_one (source_p, form_str (ERR_NICKNAMEINUSE), me.name,
		  parv[0], newnick);
      return;
    }

  if (MyConnect (oldnickname))
    {
      if (!IsFloodDone (oldnickname))
	flood_endgrace (oldnickname);

      if ((newnickname = find_client (oldnick)))
	{
	  if (newnickname == oldnickname)
	    {
	      /* check the nick isnt exactly the same */
	      if (strcmp (oldnickname->name, newnick))
		{
		  change_local_nick (oldnickname->servptr, oldnickname,
				     newnick);
		  return;
		}
	      else
		{
		  /* client is doing :old NICK old
		   * ignore it..
		   */
		  return;
		}
	    }
	  /* if the client that has the nick isnt registered yet (nick but no
	   * user) then drop the unregged client
	   */
	  if (IsUnknown (newnickname))
	    {
	      /* the old code had an if(MyConnect(target_p)) here.. but I cant see
	       * how that can happen, m_nick() is local only --fl_
	       */

	      exit_client (NULL, newnickname, &me, "Overridden");
	      change_local_nick (oldnickname->servptr, oldnickname, newnick);
	      return;
	    }
	  else
	    {
	      sendto_one (source_p, form_str (ERR_NICKNAMEINUSE), me.name,
			  parv[0], newnick);
	      return;
	    }
	}
      else
	{
	  if (!ServerInfo.hub && uplink && IsCapable (uplink, CAP_LL))
	    {
	      /* The uplink might know someone by this name already. */
	      sendto_one (uplink, ":%s NBURST %s %s %s", me.name, newnick,
			  newnick, oldnickname->name);
	      return;
	    }
	  else
	    {
	      change_local_nick (oldnickname->servptr, oldnickname, newnick);
	      return;
	    }
	}
    }
  else
    {
      sendto_server (client_p, source_p, NULL, NOCAPS, NOCAPS, LL_ICLIENT,
		     ":%s SVSNICK %s %s", me.name, oldnick, newnick);
      return;
    }
}
Esempio n. 4
0
/* parse()
 *
 * given a raw buffer, parses it and generates parv, parc and sender
 */
void
parse(struct Client *client_p, char *pbuffer, char *bufend)
{
	struct Client *from = client_p;
	static char *para[MAXPARA + 2];
	static char *sender;

	char *ch;
	char *s;
	char *end;
	int i = 1;
	char *numeric = 0;
	struct Message *mptr;

	s_assert(MyConnect(client_p));
	if(IsAnyDead(client_p))
		return;

	for(ch = pbuffer; *ch == ' '; ch++)	/* skip spaces */
		/* null statement */ ;

	if(from->name != NULL)
		para[0] = LOCAL_COPY(from->name);
	else
		para[0] = NULL;

	if(*ch == ':')
	{
		ch++;

		/* point sender to the sender param */
		sender = ch;

		if((s = strchr(ch, ' ')))
		{
			*s = '\0';
			s++;
			ch = s;
		}

		if(*sender && IsServer(client_p))
		{
			from = find_any_client(sender);

			/* didnt find any matching client, issue a kill */
			if(from == NULL)
			{
				ServerStats.is_unpf++;
				remove_unknown(client_p, sender, pbuffer);
				return;
			}

			para[0] = LOCAL_COPY(from->name);

			/* fake direction, hmm. */
			if(from->from != client_p)
			{
				ServerStats.is_wrdi++;
				cancel_clients(client_p, from);
				return;
			}
		}
		while(*ch == ' ')
			ch++;
	}

	if(*ch == '\0')
	{
		ServerStats.is_empt++;
		return;
	}

	/* at this point there must be some sort of command parameter */

	/*
	 * Extract the command code from the packet.  Point s to the end
	 * of the command code and calculate the length using pointer
	 * arithmetic.	Note: only need length for numerics and *all*
	 * numerics must have parameters and thus a space after the command
	 * code. -avalon
	 */

	/* EOB is 3 chars long but is not a numeric */

	if(*(ch + 3) == ' ' &&	/* ok, lets see if its a possible numeric.. */
	   IsDigit(*ch) && IsDigit(*(ch + 1)) && IsDigit(*(ch + 2)))
	{
		mptr = NULL;
		numeric = ch;
		ServerStats.is_num++;
		s = ch + 3;	/* I know this is ' ' from above if */
		*s++ = '\0';	/* blow away the ' ', and point s to next part */
	}
	else
	{
		int ii = 0;

		if((s = strchr(ch, ' ')))
			*s++ = '\0';

		mptr = hash_find_data(HASH_COMMAND, ch);

		/* no command or its encap only, error */
		if(mptr == NULL || mptr->cmd == NULL)
		{
			/*
			 * Note: Give error message *only* to recognized
			 * persons. It's a nightmare situation to have
			 * two programs sending "Unknown command"'s or
			 * equivalent to each other at full blast....
			 * If it has got to person state, it at least
			 * seems to be well behaving. Perhaps this message
			 * should never be generated, though...	 --msa
			 * Hm, when is the buffer empty -- if a command
			 * code has been found ?? -Armin
			 */
			if(pbuffer[0] != '\0')
			{
				if(IsClient(from))
					sendto_one_numeric(from, s_RPL(ERR_UNKNOWNCOMMAND), ch);
			}
			ServerStats.is_unco++;
			return;
		}

		ii = bufend - ((s) ? s : ch);
		mptr->bytes += ii;
	}

	end = bufend - 1;

	/* XXX this should be done before parse() is called */
	if(*end == '\n')
		*end-- = '\0';
	if(*end == '\r')
		*end = '\0';


	/* ugh. so rb_string_to_array isn't brain damaged like the original one
	 * however..so accomdate the old behavior, pass &para[1] 
	 * and add + 1 to i...the rest of this mess can e fixed 
	 */
	if(s != NULL)
		i = rb_string_to_array(s, &para[1], MAXPARA) + 1; 

	if(mptr == NULL)
	{
		do_numeric(numeric, client_p, from, i, para);
		return;
	}

	if(handle_command(mptr, client_p, from, i,	/* XXX discards const!!! */
			  (const char **)(uintptr_t) para) < -1)
	{
		char *p;
		for(p = pbuffer; p <= end; p += 8)
		{
			/* HACK HACK */
			/* Its expected this nasty code can be removed
			 * or rewritten later if still needed.
			 */
			if((unsigned long)(p + 8) > (unsigned long)end)
			{
				for(; p <= end; p++)
				{
					ilog(L_MAIN, "%02x |%c", p[0], p[0]);
				}
			}
			else
				ilog(L_MAIN,
				     "%02x %02x %02x %02x %02x %02x %02x %02x |%c%c%c%c%c%c%c%c",
				     p[0], p[1], p[2], p[3], p[4], p[5],
				     p[6], p[7], p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
		}
	}

}
Esempio n. 5
0
/*
 * m_links - LINKS message handler
 *      parv[0] = sender prefix
 *      parv[1] = servername mask
 * or
 *      parv[0] = sender prefix
 *      parv[1] = server to query 
 *      parv[2] = servername mask
 */
int m_links(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  const char*    mask = "";
  struct Client* acptr;
  struct ConfItem* aconf;
  char           clean_mask[2 * HOSTLEN + 4];
  char*          p;
  int            bogus_server = 0;
  static time_t  last_used = 0L;

  if (parc > 2)
    {
      if (!IsServer(sptr) && !HasUmode(sptr,UMODE_REMOTEINFO))
	{
	  if (SeesOperMessages(sptr))
	    sendto_one(sptr,":%s NOTICE %s :You have no S umode", me.name, parv[0]);
	  else
	    sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
	  return 0;
	}

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

  assert(0 != mask);

  if(!NoFloodProtection(sptr))
    {
      /* reject non local requests */
      if(!MyClient(sptr))
        return 0;

      if(IsHoneypot(sptr) || (last_used + PACE_WAIT) > CurrentTime)
        {
          /* safe enough to give this on a local connect only */
          sendto_one(sptr,form_str(RPL_LOAD2HI),me.name,parv[0],"LINKS");
          return 0;
        }
      else
        {
          last_used = CurrentTime;
        }
    }

  /*
   * *sigh* Before the kiddies find this new and exciting way of 
   * annoying opers, lets clean up what is sent to all opers
   * -Dianora
   */

  {
    const char* s = mask;
    while (*s)
      {
	if (!IsServChar(*s)) {
	  bogus_server = 1;
	  break;
	}
	s++;
      }
  }

  if (bogus_server)
    {
      sendto_ops_flag(UMODE_SPY,
			  "BOGUS LINKS '%s' requested by %s (%s@%s) [%s]",
			  clean_string(clean_mask, (const unsigned char *) mask, 2 * HOSTLEN),
			  sptr->name, sptr->username,
			  sptr->host, sptr->user->server);
      return 0;
    }

  if (*mask)       /* only necessary if there is a mask */
    mask = collapse(clean_string(clean_mask, (const unsigned char *) mask, 2 * HOSTLEN));

  /* Here's a cute spacing hack for you -- asuffield */
  if (MyConnect(sptr))
    sendto_ops_flag(UMODE_SPY,
		    "LINKS %s%srequested by %s (%s@%s) [%s]",
		    mask, mask ? " " : "" , sptr->name, sptr->username,
		    sptr->host, sptr->user->server);

  for (aconf = ConfigItemList; aconf; aconf = aconf->next)
    {
      if (aconf->status != CONF_NOCONNECT_SERVER)
	continue;
      if ((aconf->flags & CONF_FLAGS_HIDDEN_SERVER) && !HasUmode(sptr, UMODE_AUSPEX))
	continue;
      acptr = find_server(aconf->name);
      if (!acptr)
	continue;
      if (!IsServer(acptr) && !IsMe(acptr))
        continue;
      if (*mask && !match(mask, acptr->name))
        continue;
      if (HasUmode(sptr,UMODE_AUSPEX))
         sendto_one(sptr, form_str(RPL_LINKS),
                    me.name, parv[0], acptr->name, acptr->serv->up,
                    HasUmode(sptr, UMODE_SEEROUTING) ? acptr->hopcount : 0,
		    acptr->info[0] ? acptr->info : "(Unknown Location)");
      else
        {
          if(acptr->info[0])
            {
              /* kludge, you didn't see this nor am I going to admit
               * that I coded this.
               */
              p = strchr(acptr->info,']');
              if(p)
                p += 2; /* skip the nasty [IP] part */
              else
                p = acptr->info;
            }
          else
	    {
	      static char unknown[] = "(Unknown Location)";
	      p = unknown;
	    }

#ifdef SERVERHIDE
          if (strlen(acptr->name) < 6 || strcmp(".quiet", (acptr->name)+(strlen(acptr->name)-6)) || strcmp(".local", (acptr->name)+(strlen(acptr->name)-6)) || HasUmode(sptr,UMODE_SEEROUTING))
            sendto_one(sptr, form_str(RPL_LINKS),
                      me.name, parv[0], acptr->name, HasUmode(sptr,UMODE_SEEROUTING) ? acptr->serv->up : NETWORK_NAME,
                       0, p);
#else
          sendto_one(sptr, form_str(RPL_LINKS),
                    me.name, parv[0], acptr->name, acptr->serv->up,
                    acptr->hopcount, p);
#endif
        }

    }
  
  sendto_one(sptr, form_str(RPL_ENDOFLINKS), me.name, parv[0],
             EmptyString(mask) ? "*" : mask);
  return 0;
}
Esempio n. 6
0
/*
 * mo_connect - CONNECT command handler
 *
 * Added by Jto 11 Feb 1989
 *
 * m_connect
 *      parv[1] = servername
 *      parv[2] = port number
 *      parv[3] = remote server
 */
static void
mo_connect(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	int port;
	int tmpport;
	struct server_conf *server_p;
	struct Client *target_p;

	/* always privileged with handlers */

	if(MyConnect(source_p) && !IsOperRemote(source_p) && parc > 3)
	{
		sendto_one(source_p, form_str(ERR_NOPRIVS),
			   me.name, source_p->name, "remote");
		return;
	}

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

	if((target_p = find_server(source_p, parv[1])))
	{
		sendto_one_notice(source_p, ":Connect: Server %s already exists from %s.", parv[1],
			target_p->from->name);
		return;
	}

	/*
	 * try to find the name, then host, if both fail notify ops and bail
	 */
	if((server_p = find_server_conf(parv[1])) == NULL)
	{
		sendto_one_notice(source_p, ":Connect: Host %s not listed in ircd.conf", parv[1]);
		return;
	}

	if(ServerConfSSL(server_p) && (!ircd_ssl_ok || !get_ssld_count()))
	{
		sendto_one_notice(source_p,
				  ":Connect: Server %s is set to use SSL/TLS but SSL/TLS is not configured.",
				  parv[1]);
		return;
	}

	/*
	 * Get port number from user, if given. If not specified,
	 * use the default form configuration structure. If missing
	 * from there, then use the precompiled default.
	 */
	port = 0;
	if(parc > 2 && !EmptyString(parv[2]))
		port = atoi(parv[2]);
	if(port == 0 && server_p->port)
		port = server_p->port;
	else if(port <= 0)
	{
		sendto_one_notice(source_p, ":Connect: illegal port number");
		return;
	}

	/*
	 * Notify all operators about remote connect requests
	 */

	ilog(L_SERVER, "CONNECT From %s : %s %s", source_p->name, parv[1], parc > 2 ? parv[2] : "");

	tmpport = server_p->port;
	server_p->port = port;

	/*
	 * at this point we should be calling connect_server with a valid
	 * C:line and a valid port in the C:line
	 */
	if(serv_connect(server_p, source_p))
	{
			sendto_one_notice(source_p, ":*** Connecting to %s.%d",
				server_p->name, server_p->port);
	}
	else
	{
		sendto_one_notice(source_p, ":*** Couldn't connect to %s.%d",
			server_p->name, server_p->port);
	}

	/*
	 * client is either connecting with all the data it needs or has been
	 * destroyed, so reset it back to the configured settings
	 */
	server_p->port = tmpport;
}
Esempio n. 7
0
/*
** m_part
**	parv[0] = sender prefix
**	parv[1] = channel
**	parv[2] = comment (added by Lefler)
*/
DLLFUNC CMD_FUNC(m_part)
{
	aChannel *chptr;
	Membership *lp;
	char *p = NULL, *name;
	char *commentx = (parc > 2 && parv[2]) ? parv[2] : NULL;
	char *comment;
	int n;
	
	if (parc < 2 || parv[1][0] == '\0')
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
		    me.name, parv[0], "PART");
		return 0;
	}

	if (MyClient(sptr))
	{
		if (IsShunned(sptr))
			commentx = NULL;
		if (STATIC_PART)
		{
			if (!strcasecmp(STATIC_PART, "yes") || !strcmp(STATIC_PART, "1"))
				commentx = NULL;
			else if (!strcasecmp(STATIC_PART, "no") || !strcmp(STATIC_PART, "0"))
				; /* keep original reason */
			else
				commentx = STATIC_PART;
		}
		if (commentx)
		{
			n = dospamfilter(sptr, commentx, SPAMF_PART, parv[1], 0, NULL);
			if (n == FLUSH_BUFFER)
				return n;
			if (n < 0)
				commentx = NULL;
		}
	}

	for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
	{
		chptr = get_channel(sptr, name, 0);
		if (!chptr)
		{
			sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
			    me.name, parv[0], name);
			continue;
		}
		if (check_channelmask(sptr, cptr, name))
			continue;

		/* 'commentx' is the general part msg, but it can be changed
		 * per-channel (eg some chans block badwords, strip colors, etc)
		 * so we copy it to 'comment' and use that in this for loop :)
		 */
		comment = commentx;

		if (!(lp = find_membership_link(sptr->user->channel, chptr)))
		{
			/* Normal to get get when our client did a kick
			   ** for a remote client (who sends back a PART),
			   ** so check for remote client or not --Run
			 */
			if (MyClient(sptr))
				sendto_one(sptr,
				    err_str(ERR_NOTONCHANNEL), me.name,
				    parv[0], name);
			continue;
		}

		if (!IsAnOper(sptr) && !is_chanownprotop(sptr, chptr)) {
#ifdef STRIPBADWORDS
			int blocked = 0;
#endif
			/* Banned? No comment allowed ;) */
			if (comment && is_banned(sptr, chptr, BANCHK_MSG))
				comment = NULL;
			/* And other things... */
			if ((chptr->mode.mode & MODE_NOCOLOR) && comment) {
				if (strchr((char *)comment, 3) || strchr((char *)comment, 27)) {
					comment = NULL;
				}
			}
			if ((chptr->mode.mode & MODE_MODERATED) && comment &&
				 !has_voice(sptr, chptr) && !is_halfop(sptr, chptr))
			{
				comment = NULL;
			}
			if ((chptr->mode.mode & MODE_STRIP) && comment) {
				comment = (char *)StripColors(comment);
			}
#ifdef STRIPBADWORDS
 #ifdef STRIPBADWORDS_CHAN_ALWAYS
			if (comment)
			{
				comment = (char *)stripbadwords_channel(comment, &blocked);
			}
 #else
			if ((chptr->mode.extmode & EXTMODE_STRIPBADWORDS) && comment) {
				comment = (char *)stripbadwords_channel(comment, &blocked);
			}
 #endif
#endif
			
		}
		/* +M and not +r? */
		if ((chptr->mode.mode & MODE_MODREG) && !IsRegNick(sptr) && !IsAnOper(sptr))
			comment = NULL;

		if (MyConnect(sptr))
		{
			Hook *tmphook;
			for (tmphook = Hooks[HOOKTYPE_PRE_LOCAL_PART]; tmphook; tmphook = tmphook->next) {
				comment = (*(tmphook->func.pcharfunc))(sptr, chptr, comment);
				if (!comment)
					break;
			}
		}

		/* Send to other servers... */
		if (!comment)
			sendto_serv_butone_token(cptr, parv[0],
			    MSG_PART, TOK_PART, "%s", chptr->chname);
		else
			sendto_serv_butone_token(cptr, parv[0],
			    MSG_PART, TOK_PART, "%s :%s", chptr->chname,
			    comment);

		if (1)
		{
			if ((chptr->mode.mode & MODE_AUDITORIUM) && !is_chanownprotop(sptr, chptr))
			{
				if (!comment)
				{
					sendto_chanops_butone(NULL,
					    chptr, ":%s!%s@%s PART %s",
					    sptr->name, sptr->user->username, GetHost(sptr),
					    chptr->chname);
					if (!is_chan_op(sptr, chptr) && MyClient(sptr))
						sendto_one(sptr, ":%s!%s@%s PART %s",
						    sptr->name, sptr->user->username, GetHost(sptr), chptr->chname);
				}
				else
				{
					sendto_chanops_butone(NULL,
					    chptr,
					    ":%s!%s@%s PART %s %s",
					    sptr->name,
					    sptr->user->username,
					    GetHost(sptr),
					    chptr->chname, comment);
					if (!is_chan_op(cptr, chptr) && MyClient(sptr))
						sendto_one(sptr,
						    ":%s!%s@%s PART %s %s",
						    sptr->name, sptr->user->username, GetHost(sptr),
						    chptr->chname, comment);
				}
			}
			else
			{


				if (!comment)

					sendto_channel_butserv(chptr,
					    sptr, PARTFMT, parv[0],
					    chptr->chname);
				else
					sendto_channel_butserv(chptr,
					    sptr, PARTFMT2, parv[0],
					    chptr->chname, comment);
			}
			if (MyClient(sptr))
				RunHook4(HOOKTYPE_LOCAL_PART, cptr, sptr, chptr, comment);
			else
				RunHook4(HOOKTYPE_REMOTE_PART, cptr, sptr, chptr, comment);

			remove_user_from_channel(sptr, chptr);
		}
	}
	return 0;
}
Esempio n. 8
0
static void
mo_chgident(struct Client *client_p, struct Client *source_p,
            int parc, char *parv[])
{
  struct Client *target_p = NULL;

  if (MyClient(source_p) && !HasUMode(source_p, UMODE_ADMIN))
  {
    sendto_one(source_p, form_str(ERR_NOPRIVS),
               me.name, source_p->name, "CHGIDENT");
    return;
  }

  if (EmptyString(parv[2]))
  {
    parv[2] = parv[1];
    target_p = source_p;

    if (!IsClient(target_p))
      return;
  }
  else
  {
    target_p = hash_find_client(parv[1]);

    if (target_p == NULL || !IsClient(target_p))
    {
      sendto_one(source_p, form_str(ERR_NOSUCHNICK),
                 me.name, source_p->name, parv[1]);
      return;
    }
  }

  if (strlen(parv[2]) > USERLEN || !*parv[2] || !valid_username(parv[2]))
  {
    sendto_one(source_p, ":%s NOTICE %s :Invalid username",
               me.name, source_p->name);
    return;
  }

  if (IsUserHostIp(target_p))
    delete_user_host(target_p->username, target_p->host, !MyConnect(target_p));

  strlcpy(target_p->username, parv[2], sizeof(target_p->username));

  add_user_host(target_p->username, target_p->host, !MyConnect(target_p));
  SetUserHost(target_p);

  if (MyClient(source_p))
  {
    sendto_server(client_p, NOCAPS, NOCAPS, ":%s ENCAP * CHGIDENT %s %s",
                  source_p->name, target_p->name, parv[2]);
    sendto_one(source_p, ":%s NOTICE %s :%s changed to %s@%s",
               me.name, source_p->name, target_p->name, target_p->username,
               target_p->host);
  }

  if (MyClient(target_p))
  {
    if (IsClient(source_p))
      sendto_one(target_p, ":%s NOTICE %s :You are now %s@%s",
                 me.name, target_p->name, target_p->username, target_p->host);

    clear_ban_cache_client(target_p);
  }
}