예제 #1
0
/*
 * part_one_client
 *
 * inputs	- pointer to server
 * 		- pointer to source client to remove
 *		- char pointer of name of channel to remove from
 * output	- none
 * side effects	- remove ONE client given the channel name
 */
static void
part_one_client(struct Client *client_p, struct Client *source_p, char *name, char *reason)
{
    struct Channel *chptr;
    struct membership *msptr;
    char reason2[BUFSIZE];

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

    msptr = find_channel_membership(chptr, source_p);
    if(msptr == NULL) {
        sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name);
        return;
    }

    if(MyConnect(source_p) && !IsOper(source_p) && !IsExemptSpambot(source_p))
        check_spambot_warning(source_p, NULL);

    /*
     *  Remove user from the old channel (if any)
     *  only allow /part reasons in -m chans
     */
    if(reason[0] && (is_any_op(msptr) || !MyConnect(source_p) ||
                     ((can_send(chptr, source_p, msptr) > 0 && ConfigFileEntry.use_part_messages &&
                       (source_p->localClient->firsttime +
                        ConfigFileEntry.anti_spam_exit_message_time) < rb_current_time())))) {
        if(chptr->mode.mode & MODE_NOCOLOR && (!ConfigChannel.exempt_cmode_c || !is_any_op(msptr))) {
            rb_strlcpy(reason2, reason, BUFSIZE);
            strip_colour(reason2);
            reason = reason2;
        }
        sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                      ":%s PART %s :%s", use_id(source_p), chptr->chname, reason);
        sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :\"%s\"",
                             source_p->name, source_p->username,
                             source_p->host, chptr->chname, reason);
    } else {
        sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                      ":%s PART %s", use_id(source_p), chptr->chname);
        sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
                             source_p->name, source_p->username,
                             source_p->host, chptr->chname);
    }
    remove_user_from_channel(msptr);
}
예제 #2
0
static void
h_can_send(void *vdata)
{
    char *text, *filtered;
    hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;

    if(data->chptr->mode.mode & mymode &&
            ((strchr(ConfigChannel.exemptchanops, 'c') == NULL) ||
             !is_any_op(data->msptr)))
    {
        /* colour == 3 */
        text = ((char **)data->data)[3];

        /* Filtered == 0 */
        filtered = ((char **)data->data)[0];

        if (EmptyString(text))
        {
            if(data->cmd == COMMAND_PRIVMSG)
                sendto_one(data->client, form_str(ERR_NOTEXTTOSEND), me.name, data->client->name);
            data->approved = CAN_SEND_NO_NONOTIFY;
            return;
        }

        /* Copy coloured into filtered */
        rb_strlcpy(filtered, text, BUFSIZE);
    }

    return;
}
예제 #3
0
static int
m_cycle(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    char *p, *name;
    char *s = LOCAL_COPY(parv[1]);
    struct Channel *chptr;
    struct membership *msptr;

    name = rb_strtok_r(s, ",", &p);

    /* Finish the flood grace period... */
    if(MyClient(source_p) && !IsFloodDone(source_p))
        flood_endgrace(source_p);

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

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

        if(MyConnect(source_p) && !IsOper(source_p) && !IsExemptSpambot(source_p))
            check_spambot_warning(source_p, NULL);

        if((is_any_op(msptr) || !MyConnect(source_p) ||
            ((can_send(chptr, source_p, msptr) > 0 &&
              (source_p->localClient->firsttime +
               ConfigFileEntry.anti_spam_exit_message_time) < rb_current_time())))) {
            sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                          ":%s PART %s :Cycling", use_id(source_p), chptr->chname);
            sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :Cycling",
                                 source_p->name, source_p->username,
                                 source_p->host, chptr->chname);
        } else {
            sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                          ":%s PART %s", use_id(source_p), chptr->chname);
            sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
                                 source_p->name, source_p->username,
                                 source_p->host, chptr->chname);
        }

        remove_user_from_channel(msptr);

        chptr = NULL;
        msptr = NULL;

        name = rb_strtok_r(NULL, ",", &p);
    }

    user_join(client_p, source_p, parv[1], parc > 2 ? parv[2] : NULL);

    return 0;
}
예제 #4
0
static void
h_can_send(void *vdata)
{
	hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;

	if (!(data->cmd == COMMAND_NOTICE))
		return;
	
	if(data->chptr->mode.mode & mymode &&
	   ((strchr(ConfigChannel.exemptchanops, 'T') == NULL) ||
	    !is_any_op(data->msptr)))
	{
		sendto_one_numeric(data->client, 404,
				"%s :Cannot send to channel - Notices are disallowed (+T set)",
				data->chptr->chname);
		data->approved = CAN_SEND_NO_NONOTIFY;
	}
	return;
}
예제 #5
0
static void
h_can_send(void *vdata)
{
	char *text;
	size_t contor;
	int caps = 0;
	int len = 0;

	hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;

	if ((data->chptr->mode.mode & mymode) &&
	   ((strchr(ConfigChannel.exemptchanops, 'G') == NULL) ||
	    !is_any_op(data->msptr)))
	{
		/* 2 == unprintable */
		text = ((char **)data->data)[2];

		if(strlen(text) < 10)
			return;

		for(contor = 0; contor < strlen(text); contor++)
		{
			if(IsUpper(text[contor]) && !isdigit(text[contor]))
				caps++; 
			len++;
		}
		/* Added divide by 0 check --alxbl */ 
		if(len > 0 && ((caps * 100) / len) >= conf_threshold)
		{
			if(data->cmd == COMMAND_PRIVMSG)
				sendto_one_numeric(data->client, 404,
					"%s :Cannot send to channel - Your message contains more than %d%% capital letters (+G set)", 
					data->chptr->chname, conf_threshold);
			data->approved = CAN_SEND_NO_NONOTIFY;
			return;
		}
	}

	return;
}
예제 #6
0
static void
h_can_send(void *vdata)
{
    char text[BUFSIZE];
    hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;

    if(data->chptr->mode.mode & mymode && (!ConfigChannel.exempt_cmode_c || !is_any_op(data->msptr)))
    {
        strip_colour((char *)data->data, text, BUFSIZE);
        if (EmptyString(text))
        {
            if(data->cmd == COMMAND_PRIVMSG)
                sendto_one(data->client, form_str(ERR_NOTEXTTOSEND), me.name, data->client->name);
            data->approved = CAN_SEND_NO_NONOTIFY;
            return;
        }

        /* Copy it */
        rb_strlcpy(data->data, text, BUFSIZE);
    }

    return;
}
예제 #7
0
/*
 * mo_omode - MODE command handler
 * parv[1] - channel
 */
static int
mo_omode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;
	struct membership *msptr;
	char params[512];
	int i;
	int wasonchannel;
	/* admins only */
	if (!IsOperAdmin(source_p)) {
		sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin");
		return 0;
	}
	/* Now, try to find the channel in question */
	if (!IsChanPrefix(parv[1][0]) || !check_channel_name(parv[1])) {
		sendto_one_numeric(source_p, ERR_BADCHANNAME,
		                   form_str(ERR_BADCHANNAME), parv[1]);
		return 0;
	}
	chptr = find_channel(parv[1]);
	if (chptr == NULL) {
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
		                   form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return 0;
	}
	/* Now know the channel exists */
	msptr = find_channel_membership(chptr, source_p);
	wasonchannel = msptr != NULL;
	if (is_any_op(msptr)) {
		sendto_one_notice(source_p, ":Use a normal MODE you idiot");
		return 0;
	}
	params[0] = '\0';
	for (i = 2; i < parc; i++) {
		if (i != 2)
			rb_strlcat(params, " ", sizeof params);
		rb_strlcat(params, parv[i], sizeof params);
	}
	sendto_wallops_flags(UMODE_WALLOP, &me,
	                     "OMODE called for [%s] [%s] by %s!%s@%s",
	                     parv[1], params, source_p->name, source_p->username, source_p->host);
	ilog(L_MAIN, "OMODE called for [%s] [%s] by %s",
	     parv[1], params, get_oper_name(source_p));
	if (*chptr->chname != '&')
		sendto_server(NULL, NULL, NOCAPS, NOCAPS,
		              ":%s WALLOPS :OMODE called for [%s] [%s] by %s!%s@%s",
		              me.name, parv[1], params, source_p->name, source_p->username,
		              source_p->host);
#if 0
	set_channel_mode(client_p, source_p->servptr, chptr, msptr,
	                 parc - 2, parv + 2);
#else
	if (parc == 4 && !strcmp(parv[2], "+y") && !irccmp(parv[3], source_p->name)) {
		/* Ownering themselves */
		if (!wasonchannel) {
			sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
			                   form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname);
			return 0;
		}
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +y %s",
		                     me.name, parv[1], source_p->name);
		sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
		              ":%s TMODE %ld %s +y %s",
		              me.id, (long) chptr->channelts, parv[1],
		              source_p->id);
		msptr->flags |= CHFL_OWNER;
	} else if (parc == 4 && !strcmp(parv[2], "+a") && !irccmp(parv[3], source_p->name)) {
		/* Admining themselves */
		if (!wasonchannel) {
			sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
			                   form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname);
			return 0;
		}
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +a %s",
		                     me.name, parv[1], source_p->name);
		sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
		              ":%s TMODE %ld %s +a %s",
		              me.id, (long) chptr->channelts, parv[1],
		              source_p->id);
		msptr->flags |= CHFL_ADMIN;
	} else if (parc == 4 && !strcmp(parv[2], "+o") && !irccmp(parv[3], source_p->name)) {
		/* Opping themselves */
		if (!wasonchannel) {
			sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
			                   form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname);
			return 0;
		}
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s",
		                     me.name, parv[1], source_p->name);
		sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
		              ":%s TMODE %ld %s +o %s",
		              me.id, (long) chptr->channelts, parv[1],
		              source_p->id);
		msptr->flags |= CHFL_CHANOP;
	} else if (parc == 4 && !strcmp(parv[2], "+h") && !irccmp(parv[3], source_p->name)) {
		/* Halfopping themselves */
		if (!wasonchannel) {
			sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
			                   form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname);
			return 0;
		}
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +h %s",
		                     me.name, parv[1], source_p->name);
		sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
		              ":%s TMODE %ld %s +h %s",
		              me.id, (long) chptr->channelts, parv[1],
		              source_p->id);
		msptr->flags |= CHFL_HALFOP;
	} else if (ConfigChannel.use_owner) {
		/* I hope this is correct.
		 * -- Kabaka */
		/* Hack it so set_channel_mode() will accept */
		if (wasonchannel)
			msptr->flags |= CHFL_OWNER;
		else {
			add_user_to_channel(chptr, source_p, CHFL_CHANOP);
			msptr = find_channel_membership(chptr, source_p);
		}
		set_channel_mode(client_p, source_p, chptr, msptr,
		                 parc - 2, parv + 2);
		if (wasonchannel)
			msptr->flags &= ~CHFL_OWNER;
		else
			remove_user_from_channel(msptr);
	} else if (ConfigChannel.use_admin) {
		/* Hack it so set_channel_mode() will accept */
		if (wasonchannel)
			msptr->flags |= CHFL_ADMIN;
		else {
			add_user_to_channel(chptr, source_p, CHFL_CHANOP);
			msptr = find_channel_membership(chptr, source_p);
		}
		set_channel_mode(client_p, source_p, chptr, msptr,
		                 parc - 2, parv + 2);
		/* We know they were not opped before and they can't have opped
		 * themselves as set_channel_mode() does not allow that
		 * -- jilles */
		if (wasonchannel)
			msptr->flags &= ~CHFL_ADMIN;
		else
			remove_user_from_channel(msptr);
	} else {
		/* CHFL_ADMIN is only useful if admin is enabled
		 * so hack it with op if it is not. */
		if (wasonchannel)
			msptr->flags |= CHFL_CHANOP;
		else {
			add_user_to_channel(chptr, source_p, CHFL_CHANOP);
			msptr = find_channel_membership(chptr, source_p);
		}
		set_channel_mode(client_p, source_p, chptr, msptr,
		                 parc - 2, parv + 2);
		/* We know they were not opped before and they can't have opped
		 * themselves as set_channel_mode() does not allow that
		 * -- jilles */
		if (wasonchannel)
			msptr->flags &= ~CHFL_CHANOP;
		else
			remove_user_from_channel(msptr);
	}
#endif
	return 0;
}
예제 #8
0
static int
build_target_list(int p_or_n, char *command, struct Client *client_p,
                  struct Client *source_p, char *nicks_channels,
                  char *text)
{
  int type;
  char *p, *nick, *target_list, ncbuf[BUFSIZE];
  struct Channel *chptr=NULL;
  struct Client *target_p;

  /* Sigh, we can't mutilate parv[1] incase we need it to send to a hub */
  if (!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL))
  {
    strncpy(ncbuf, nicks_channels, BUFSIZE);
    target_list = ncbuf;
  }
  else
    target_list = nicks_channels; /* skip strcpy for non-lazyleafs */

  ntargets = 0;

  for (nick = strtoken(&p, target_list, ","); nick;
       nick = strtoken(&p, (char *)NULL, ","))
  {
    char *with_prefix;
    /*
     * channels are privmsg'd a lot more than other clients, moved up
     * here plain old channel msg?
     */

    if (IsChanPrefix(*nick))
    {
      /* ignore send of local channel to a server (should not happen) */
      if (IsServer(client_p) && *nick == '&')
        continue;

      if ((chptr = hash_find_channel(nick)) != NULL)
      {
        if (!duplicate_ptr(chptr))
        {
          if (ntargets >= ConfigFileEntry.max_targets)
	    {
	      sendto_one(source_p, form_str(source_p,ERR_TOOMANYTARGETS),
			 me.name, source_p->name, nick);
	      return (1);
	    }
          targets[ntargets].ptr = (void *)chptr;
          targets[ntargets++].type = ENTITY_CHANNEL;
        }
      }
      else
      {
        if (!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL))
          return -1;
        else if (p_or_n != NOTICE)
          sendto_one(source_p, form_str(source_p,ERR_NOSUCHNICK), me.name,
                     source_p->name, nick);
      }
      continue;
    }

    /* look for a privmsg to another client */
    if ((target_p = find_person(nick)) != NULL)
    {
      if (!duplicate_ptr(target_p))
      {
        if (ntargets >= ConfigFileEntry.max_targets)
	  {
	    sendto_one(source_p, form_str(source_p,ERR_TOOMANYTARGETS),
		       me.name, source_p->name, nick);
	    return (1);
	  }
        targets[ntargets].ptr = (void *)target_p;
        targets[ntargets].type = ENTITY_CLIENT;
        targets[ntargets++].flags = 0;
      }
      continue;
    }
    
    /* @#channel or +#channel message ? */

    type = 0;
    with_prefix = nick;
    /*  allow %+@ if someone wants to do that */
    for (;;)
    {
      if (*nick == '@')
        type |= MODE_CHANOP;
      else if (*nick == '%')
        type |= MODE_CHANOP | MODE_HALFOP;
      else if (*nick == '+')
        type |= MODE_CHANOP | MODE_HALFOP | MODE_VOICE;
      else
        break;
      nick++;
    }

    if (type != 0)
    {
      /* suggested by Mortiis */
      if (*nick == '\0')      /* if its a '\0' dump it, there is no recipient */
	{
	  sendto_one(source_p, form_str(source_p,ERR_NORECIPIENT),
		     me.name, source_p->name, command);
	  continue;
	}

      /* At this point, nick+1 should be a channel name i.e. #foo or &foo
       * if the channel is found, fine, if not report an error
       */

      if ((chptr = hash_find_channel(nick)) != NULL)
	{
	  if(!is_any_op(chptr, source_p) && !is_voiced(chptr, source_p))
	    {
	      sendto_one(source_p, form_str(source_p,ERR_CHANOPRIVSNEEDED), me.name,
			 source_p->name, with_prefix);
	      return(-1);
	    }

	  if (!duplicate_ptr(chptr))
	    {
	      if (ntargets >= ConfigFileEntry.max_targets)
		{
		  sendto_one(source_p, form_str(source_p,ERR_TOOMANYTARGETS),
			     me.name, source_p->name, nick);
		  return (1);
		}
	      targets[ntargets].ptr = (void *)chptr;
	      targets[ntargets].type = ENTITY_CHANOPS_ON_CHANNEL;
	      targets[ntargets++].flags = type;
	    }
	}
      else
	{
	  if (!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL))
	    return -1;
	  else if (p_or_n != NOTICE)
	    sendto_one(source_p, form_str(source_p,ERR_NOSUCHNICK), me.name,
		       source_p->name, nick);
	}
      continue;
    }

    if(IsOper(source_p) && ((*nick == '$') || strchr(nick, '@')))
    {
      handle_opers(p_or_n, command, client_p, source_p, nick, text);
    }
    else
    {
      if (!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL))
        return -1;
      else if(p_or_n != NOTICE)
        sendto_one(source_p, form_str(source_p,ERR_NOSUCHNICK),
	           me.name, source_p->name, nick);
    }
    /* continue; */
  }
  return (1);
}
예제 #9
0
/*
 * m_topic
 *      parv[1] = channel name
 *	parv[2] = new topic, if setting topic
 */
static int
m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Channel *chptr = NULL;
    struct membership *msptr;
    char *p = NULL;
    const char *name;
    int operspy = 0;

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

    name = parv[1];

    if(IsOperSpy(source_p) && parv[1][0] == '!') {
        name++;
        operspy = 1;

        if(EmptyString(name)) {
            sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
                       me.name, source_p->name, "TOPIC");
            return 0;
        }
    }

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

    if(!IsChannelName(name)) {
        sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
                           form_str(ERR_NOSUCHCHANNEL), name);
        return 0;
    }

    chptr = find_channel(name);

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

    /* setting topic */
    if(parc > 2) {
        char topic_info[USERHOST_REPLYLEN];

        msptr = find_channel_membership(chptr, source_p);

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

        if(MyClient(source_p) && !is_chanop_voiced(msptr) &&
           !IsOper(source_p) &&
           !add_channel_target(source_p, chptr)) {
            sendto_one(source_p, form_str(ERR_TARGCHANGE),
                       me.name, source_p->name, chptr->chname);
            return 0;
        }

        if(MyClient(source_p) && (chptr->mode.mode & MODE_TOPICLIMIT) && !is_any_op(msptr)) {
            if(IsOverride(source_p)) {
                sendto_wallops_flags(UMODE_WALLOP, &me,
                                     "%s is overriding TOPIC on [%s]",
                                     get_oper_name(source_p), chptr->chname);
                sendto_server(NULL, chptr, NOCAPS, NOCAPS,
                              ":%s WALLOPS :%s is overriding TOPIC on [%s]",
                              me.name, get_oper_name(source_p), chptr->chname);
            } else {
                sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                           me.name, source_p->name, parv[1]);
                return 0;
            }

        }

        if(ConfigChannel.host_in_topic)
            sprintf(topic_info, "%s!%s@%s",
                       source_p->name, source_p->username, source_p->host);
        else
            rb_strlcpy(topic_info, source_p->name, sizeof(topic_info));

        set_channel_topic(chptr, parv[2], topic_info, rb_current_time());

        sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                      ":%s TOPIC %s :%s",
                      use_id(source_p), chptr->chname,
                      chptr->topic == NULL ? "" : chptr->topic);
        sendto_channel_local(ALL_MEMBERS,
                             chptr, ":%s!%s@%s TOPIC %s :%s",
                             source_p->name, source_p->username,
                             source_p->host, chptr->chname,
                             chptr->topic == NULL ? "" : chptr->topic);

    } else if(MyClient(source_p)) {
        if(operspy)
            report_operspy(source_p, "TOPIC", chptr->chname);
        if(!IsMember(source_p, chptr) && SecretChannel(chptr) &&
           !operspy) {
            sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
                               form_str(ERR_NOTONCHANNEL), name);
            return 0;
        }
        if(chptr->topic == NULL)
            sendto_one(source_p, form_str(RPL_NOTOPIC),
                       me.name, source_p->name, name);
        else {
            sendto_one(source_p, form_str(RPL_TOPIC),
                       me.name, source_p->name, chptr->chname, chptr->topic);

            sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
                       me.name, source_p->name, chptr->chname,
                       chptr->topic_info, chptr->topic_time);
        }
    }

    return 0;
}
예제 #10
0
/*
 * m_topic
 *      parv[0] = sender prefix
 *      parv[1] = channel name
 *	parv[2] = new topic, if setting topic
 */
static void m_topic(struct Client *client_p,
                   struct Client *source_p,
                   int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  struct Channel *root_chan;
  char  *p = NULL;
#ifdef VCHANS
  struct Channel *vchan;
#endif
    
  if ((p = strchr(parv[1],',')))
    *p = '\0';

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

  if (parv[1] && IsChannelName(parv[1]))
    {
      chptr = hash_find_channel(parv[1]);

      if(chptr == NULL)
      {
        /* if chptr isn't found locally, it =could= exist
         * on the uplink. so forward reqeuest
         */
        if(!ServerInfo.hub && uplink && IsCapable(uplink, CAP_LL))
        {
          sendto_one(uplink, ":%s TOPIC %s %s",
                     source_p->name, parv[1],
                     ((parc > 2) ? parv[2] : ""));
          return;
        }
        else
        {
          sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
                     me.name, parv[0], parv[1]);
          return;
        }
      }

      root_chan = chptr;

#ifdef VCHANS
      if (HasVchans(chptr))
	{
	  vchan = map_vchan(chptr,source_p);
	  if(vchan != NULL)
	    chptr = vchan;
	}
      else if (IsVchan(chptr))
        root_chan = RootChan(chptr);
#endif
          
      /* setting topic */
      if (parc > 2)
	{
	  if (!IsMember(source_p, chptr))
	    {
	      sendto_one(source_p, form_str(ERR_NOTONCHANNEL), me.name, parv[0],
			 parv[1]);
	      return;
	    }
	  if ((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
	      is_any_op(chptr,source_p))
	    {
	      char topic_info[USERHOST_REPLYLEN]; 
              ircsprintf(topic_info, "%s!%s@%s",
			 source_p->name, source_p->username, source_p->host);
              set_channel_topic(chptr, parv[2], topic_info, CurrentTime);
	      
	      sendto_server(client_p, NULL, chptr, NOCAPS, NOCAPS, NOFLAGS,
                            ":%s TOPIC %s :%s",
                            parv[0], chptr->chname,
                            chptr->topic == NULL ? "" : chptr->topic);
	      if(chptr->mode.mode & MODE_HIDEOPS)
		{
		  sendto_channel_local(ONLY_CHANOPS_HALFOPS,
				       chptr, ":%s!%s@%s TOPIC %s :%s",
				       source_p->name,
				       source_p->username,
				       source_p->host,
				       root_chan->chname,
				       chptr->topic == NULL ? "" : chptr->topic);

		  sendto_channel_local(NON_CHANOPS,
				       chptr, ":%s TOPIC %s :%s",
				       me.name,
				       root_chan->chname,
				       chptr->topic == NULL ? "" : chptr->topic);
		}
	      else
		{
		  sendto_channel_local(ALL_MEMBERS,
				       chptr, ":%s!%s@%s TOPIC %s :%s",
				       source_p->name,
				       source_p->username,
				       source_p->host,
				       root_chan->chname, chptr->topic == NULL ? "" : chptr->topic);
		}
	    }
	  else
            sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                       me.name, parv[0], parv[1]);
	}
      else  /* only asking  for topic  */
	{
	  if (!IsMember(source_p, chptr) && SecretChannel(chptr))
	    {
	      sendto_one(source_p, form_str(ERR_NOTONCHANNEL), me.name, parv[0],
			 parv[1]);
	      return;
	    }
          if (chptr->topic == NULL)
	    sendto_one(source_p, form_str(RPL_NOTOPIC),
		       me.name, parv[0], parv[1]);
          else
	    {
              sendto_one(source_p, form_str(RPL_TOPIC),
                         me.name, parv[0],
                         root_chan->chname, chptr->topic);

                if(!(chptr->mode.mode & MODE_HIDEOPS) ||
                  is_any_op(chptr,source_p))
                {
                  sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
                             me.name, parv[0], root_chan->chname,
                             chptr->topic_info,
                             chptr->topic_time);
                }
	        /* client on LL needing the topic - if we have serverhide, say
	         * its the actual LL server that set the topic, not us the
	         * uplink -- fl_
	         */
	        else if(ConfigServerHide.hide_servers && !MyClient(source_p)
	                && IsCapable(client_p, CAP_LL) && ServerInfo.hub)
  	        {
	          sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
	  	             me.name, parv[0], root_chan->chname,
	  		     client_p->name, chptr->topic_time);
                }
  	        /* just normal topic hiding.. */
	        else
	 	{
                  sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
                             me.name, parv[0], root_chan->chname,
                             me.name,
                             chptr->topic_time);
                }
            }
        }
    }
  else
    {
      sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
                 me.name, parv[0], parv[1]);
    }
}
예제 #11
0
파일: m_part.c 프로젝트: Cloudxtreme/ircd-3
/*
 * part_one_client
 *
 * inputs	- pointer to server
 * 		- pointer to source client to remove
 *		- char pointer of name of channel to remove from
 * output	- none
 * side effects	- remove ONE client given the channel name 
 */
static void part_one_client(struct Client *client_p,
			    struct Client *source_p,
			    char *name,
                            char *reason)
{
  struct Channel *chptr;
  struct Channel *bchan;

  if ((chptr = hash_find_channel(name)) == NULL)
    {
      sendto_one(source_p, form_str(source_p,ERR_NOSUCHCHANNEL),
		 me.name, source_p->name, name);
      return;
    }

#ifdef VCHANS
  if (IsVchan(chptr) || HasVchans(chptr))
    {
      if(HasVchans(chptr))
        {
          /* Set chptr to actual channel, bchan to the base channel */
          bchan = chptr;
          chptr = map_vchan(bchan,source_p);
        }
      else
        {
          /* chptr = chptr; */
          bchan = find_bchan(chptr);
        }
    }
  else
#endif
    bchan = chptr; /* not a vchan */

  if (!chptr || !bchan || !IsMember(source_p, chptr))
    {
      sendto_one(source_p, form_str(source_p,ERR_NOTONCHANNEL),
                 me.name, source_p->name, name);
      return;
    }
  if (MyConnect(source_p) && !IsOper(source_p))
   check_spambot_warning(source_p, NULL);

  /*
   *  Remove user from the old channel (if any)
   *  only allow /part reasons in -m chans
   */
  if(reason[0] && (is_any_op(chptr, source_p) || !MyConnect(source_p) ||
     ((can_send(chptr, source_p) > 0 && 
      (source_p->firsttime + ConfigFileEntry.anti_spam_exit_message_time)
      < CurrentTime))))
    {
      /*strip_color(reason);*/
      reason = strip_color(reason, 1);

	  if (match("*http://*", reason) || match("*www*", reason))
		reason = "<spam removed>";

      sendto_server(client_p, NULL, chptr, CAP_UID, NOCAPS, NOFLAGS,
                    ":%s PART %s :%s", ID(source_p), chptr->chname,
                    reason);
      sendto_server(client_p, NULL, chptr, NOCAPS, CAP_UID, NOFLAGS,
                    ":%s PART %s :%s", source_p->name, chptr->chname,
                    reason);
      if (PaceChannel(chptr) && (chptr->parts < MAX_PACEJOIN))
		add_pace(chptr, source_p, bchan->chname, 0, 0);
      else
      	sendto_channel_local(ALL_MEMBERS,
                           chptr, ":%s!%s@%s PART %s :%s",
                           source_p->name,
                           source_p->username,
                           source_p->host,
                           bchan->chname,
                           reason);
    }
  else
    {
      sendto_server(client_p, NULL, chptr, CAP_UID, NOCAPS, NOFLAGS,
                    ":%s PART %s", ID(source_p), chptr->chname);
      sendto_server(client_p, NULL, chptr, NOCAPS, CAP_UID, NOFLAGS,
                    ":%s PART %s", source_p->name, chptr->chname);
      if (PaceChannel(chptr) && (chptr->parts < MAX_PACEJOIN))
		add_pace(chptr, source_p, bchan->chname, 0, 0);
      else
      	sendto_channel_local(ALL_MEMBERS,
                           chptr, ":%s!%s@%s PART %s",
                           source_p->name,
                           source_p->username,
                           source_p->host,
                           bchan->chname);
    }

  remove_user_from_channel(chptr, source_p);

  if (MyConnect(source_p))
	source_p->localClient->last_leave_time = CurrentTime;
}