Пример #1
0
/*
** m_away
**      parv[1] = away message
*/
static int
m_away(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    if(MyClient(source_p) && source_p->localClient->next_away &&
       !IsFloodDone(source_p))
        flood_endgrace(source_p);

    if(!IsClient(source_p))
        return 0;

    if(parc < 2 || EmptyString(parv[1])) {
        /* Marking as not away */
        if(source_p->user->away != NULL) {
            /* we now send this only if they were away before --is */
            sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
                          ":%s AWAY", use_id(source_p));
            free_away(source_p);

            sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, NOCAPS, ":%s!%s@%s AWAY",
                                                source_p->name, source_p->username, source_p->host);
        }
        if(MyConnect(source_p))
            sendto_one_numeric(source_p, RPL_UNAWAY, form_str(RPL_UNAWAY));
        return 0;
    }

    /* Rate limit this because it is sent to common channels. */
    if (MyClient(source_p)) {
        if(!IsOper(source_p) &&
           source_p->localClient->next_away > rb_current_time()) {
            sendto_one(source_p, form_str(RPL_LOAD2HI),
                       me.name, source_p->name, "AWAY");
            return 0;
        }
        if(source_p->localClient->next_away < rb_current_time() -
           ConfigFileEntry.away_interval)
            source_p->localClient->next_away = rb_current_time();
        else
            source_p->localClient->next_away = rb_current_time() +
                                               ConfigFileEntry.away_interval;
    }


    if(source_p->user->away == NULL)
        allocate_away(source_p);
    if(strncmp(source_p->user->away, parv[1], AWAYLEN - 1)) {
        rb_strlcpy(source_p->user->away, parv[1], AWAYLEN);
        sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
                      ":%s AWAY :%s", use_id(source_p), source_p->user->away);
    }

    if(MyConnect(source_p))
        sendto_one_numeric(source_p, RPL_NOWAWAY, form_str(RPL_NOWAWAY));

    sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, NOCAPS, ":%s!%s@%s AWAY :%s",
                                        source_p->name, source_p->username, source_p->host,
                                        source_p->user->away);

    return 0;
}
Пример #2
0
/* Disable this because of the abuse potential -- jilles
 * No, make it toggleable via ./configure. --nenolod
 */
static int
mo_chghost(struct Client *client_p, struct Client *source_p,
           int parc, const char *parv[])
{
    struct Client *target_p;

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

    if (!(target_p = find_named_person(parv[1]))) {
        sendto_one_numeric(source_p, ERR_NOSUCHNICK,
                           form_str(ERR_NOSUCHNICK), parv[1]);
        return 0;
    }

    if (!clean_host(parv[2])) {
        sendto_one_notice(source_p, ":Hostname %s is invalid", parv[2]);
        return 0;
    }

    do_chghost(source_p, target_p, parv[2], 0);

    sendto_server(NULL, NULL,
                  CAP_EUID | CAP_TS6, NOCAPS, ":%s CHGHOST %s %s",
                  use_id(source_p), use_id(target_p), parv[2]);
    sendto_server(NULL, NULL,
                  CAP_TS6, CAP_EUID, ":%s ENCAP * CHGHOST %s :%s",
                  use_id(source_p), use_id(target_p), parv[2]);
    return 0;
}
Пример #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
/*
 * 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;

	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_chanop(msptr) || !MyConnect(source_p) ||
			 ((can_send(chptr, source_p, msptr) > 0 &&
			   (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time)
			   < CurrentTime))))
	{
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
				":%s PART %s :%s",
				use_id(source_p), chptr->chname, reason);
		sendto_server(client_p, chptr, NOCAPS, CAP_TS6,
				":%s PART %s :%s",
				source_p->name, 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_server(client_p, chptr, NOCAPS, CAP_TS6,
				":%s PART %s",
				source_p->name, 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);
}
Пример #5
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);
}
Пример #6
0
static int mo_privs(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Client *target_p;

	if (parc < 2 || EmptyString(parv[1]))
		target_p = source_p;
	else
	{
		target_p = find_named_person(parv[1]);
		if (target_p == NULL)
		{
			sendto_one_numeric(source_p, ERR_NOSUCHNICK,
					   form_str(ERR_NOSUCHNICK), parv[1]);
			return 0;
		}
	}

	if (MyClient(target_p))
		show_privs(source_p, target_p);
	else
		sendto_one(target_p, ":%s ENCAP %s PRIVS %s",
				get_id(source_p, target_p),
				target_p->servptr->name,
				use_id(target_p));
	return 0;
}
Пример #7
0
/*
 * ms_wallops (write to *all* opers currently online)
 *      parv[1] = message text
 */
static int
ms_wallops(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	const char *prefix = "";

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

	if (IsPerson(source_p))
	{
		if (!strncmp(parv[1], "OPERWALL - ", 11) ||
				!strncmp(parv[1], "LOCOPS - ", 9) ||
				!strncmp(parv[1], "SLOCOPS - ", 10) ||
				!strncmp(parv[1], "ADMINWALL - ", 12))
			prefix = "WALLOPS - ";
	}

	sendto_wallops_flags(UMODE_WALLOP, source_p, "%s%s", prefix, parv[1]);

	sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s WALLOPS :%s", 
		      use_id(source_p), parv[1]);

	return 0;
}
Пример #8
0
/*
** m_away
**      parv[0] = sender prefix
**      parv[1] = away message
*/
static int
m_away(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	if(MyClient(source_p) && !IsFloodDone(source_p))
		flood_endgrace(source_p);

	if(!IsClient(source_p))
		return 0;

	if(parc < 2 || EmptyString(parv[1]))
	{
		/* Marking as not away */
		if(source_p->user->away != NULL)
		{
			/* we now send this only if they were away before --is */
			sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
				      ":%s AWAY", use_id(source_p));
			sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s AWAY", source_p->name);
			free_away(source_p);
		}
		if(MyConnect(source_p))
			sendto_one(source_p, form_str(RPL_UNAWAY), me.name, source_p->name);
		return 0;
	}


	if(source_p->user->away == NULL)
	{
		allocate_away(source_p);
		rb_strlcpy(source_p->user->away, parv[1], AWAYLEN);
		sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
			      ":%s AWAY :%s", use_id(source_p), source_p->user->away);
		sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
			      ":%s AWAY :%s", source_p->name, source_p->user->away);

	}
	else
	{
		rb_strlcpy(source_p->user->away, parv[1], AWAYLEN);
	}

	if(MyConnect(source_p))
		sendto_one(source_p, form_str(RPL_NOWAWAY), me.name, source_p->name);

	return 0;
}
Пример #9
0
/*
** m_away
**      parv[1] = away message
*/
static int
m_away(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	if(MyClient(source_p) && !IsFloodDone(source_p))
		flood_endgrace(source_p);

	if(!IsClient(source_p))
		return 0;

	if(parc < 2 || EmptyString(parv[1]))
	{
		/* Marking as not away */
		if(source_p->user->away != NULL)
		{
			/* we now send this only if they were away before --is */
			sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
				      ":%s AWAY", use_id(source_p));
			free_away(source_p);

			sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, NOCAPS, ":%s!%s@%s AWAY",
							    source_p->name, source_p->username, source_p->host);
		}
		if(MyConnect(source_p))
			sendto_one_numeric(source_p, RPL_UNAWAY, form_str(RPL_UNAWAY));
		return 0;
	}

	if(source_p->user->away == NULL)
		allocate_away(source_p);
	if(strncmp(source_p->user->away, parv[1], AWAYLEN - 1))
	{
		rb_strlcpy(source_p->user->away, parv[1], AWAYLEN);
		sendto_server(client_p, NULL, CAP_TS6, NOCAPS, 
			      ":%s AWAY :%s", use_id(source_p), source_p->user->away);
	}
	
	if(MyConnect(source_p))
		sendto_one_numeric(source_p, RPL_NOWAWAY, form_str(RPL_NOWAWAY));

	sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, NOCAPS, ":%s!%s@%s AWAY :%s",
					    source_p->name, source_p->username, source_p->host,
					    source_p->user->away);

	return 0;
}
Пример #10
0
/*
 * ms_operwall - OPERWALL message handler
 *  (write to *all* local opers currently online)
 *      parv[1] = message text
 */
static int
ms_operwall(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s OPERWALL :%s",
		      use_id(source_p), parv[1]);
	sendto_wallops_flags(UMODE_OPERWALL, source_p, "OPERWALL - %s", parv[1]);

	return 0;
}
Пример #11
0
			inline Uint32 use_typeless_id(const Uint32 typeless_id)
			{
				Uint32 id;

				id = get_id(typeless_id);

				use_id(id);

				return id;
			}
Пример #12
0
/* m_tb()
 *
 * parv[1] - channel
 * parv[2] - topic ts
 * parv[3] - optional topicwho/topic
 * parv[4] - topic
 */
static int
ms_tb(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr;
	const char *newtopic;
	const char *newtopicwho;
	time_t newtopicts;

	chptr = find_channel(parv[1]);

	if(chptr == NULL)
		return 0;

	newtopicts = atol(parv[2]);

	if(parc == 5)
	{
		newtopic = parv[4];
		newtopicwho = parv[3];
	}
	else
	{
		newtopic = parv[3];
		newtopicwho = source_p->name;
	}

	if(EmptyString(newtopic))
		return 0;

	if(chptr->topic == NULL || (chptr->topic != NULL && chptr->topic->topic_time > newtopicts))
	{
		/* its possible the topicts is a few seconds out on some
		 * servers, due to lag when propagating it, so if theyre the
		 * same topic just drop the message --fl
		 */
		if(chptr->topic != NULL && strcmp(chptr->topic->topic, newtopic) == 0)
			return 0;

		set_channel_topic(chptr, newtopic, newtopicwho, newtopicts);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s TOPIC %s :%s",
				     source_p->name, chptr->chname, newtopic);
		sendto_server(client_p, chptr, CAP_TB | CAP_TS6, NOCAPS,
			      ":%s TB %s %ld %s%s:%s",
			      use_id(source_p), chptr->chname, (long)chptr->topic->topic_time,
			      ConfigChannel.burst_topicwho ? chptr->topic->topic_info : "",
			      ConfigChannel.burst_topicwho ? " " : "", chptr->topic->topic);
		sendto_server(client_p, chptr, CAP_TB, CAP_TS6,
			      ":%s TB %s %ld %s%s:%s",
			      source_p->name, chptr->chname, (long)chptr->topic->topic_time,
			      ConfigChannel.burst_topicwho ? chptr->topic->topic_info : "",
			      ConfigChannel.burst_topicwho ? " " : "", chptr->topic->topic);
	}

	return 0;
}
Пример #13
0
/*
 * ms_chghost
 * parv[1] = target
 * parv[2] = host
 */
static int
ms_chghost(struct Client *client_p, struct Client *source_p,
           int parc, const char *parv[])
{
    struct Client *target_p;

    if (!(target_p = find_person(parv[1])))
        return -1;

    if (do_chghost(source_p, target_p, parv[2], 0)) {
        sendto_server(client_p, NULL,
                      CAP_EUID | CAP_TS6, NOCAPS, ":%s CHGHOST %s %s",
                      use_id(source_p), use_id(target_p), parv[2]);
        sendto_server(client_p, NULL,
                      CAP_TS6, CAP_EUID, ":%s ENCAP * CHGHOST %s :%s",
                      use_id(source_p), use_id(target_p), parv[2]);
    }

    return 0;
}
Пример #14
0
static void
send_signon(struct Client *client_p, struct Client *target_p,
            const char *nick, const char *user, const char *host,
            unsigned int newts, const char *login)
{
    sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s SIGNON %s %s %s %ld %s",
                  use_id(target_p), nick, user, host,
                  (long) target_p->tsinfo, *login ? login : "******");

    strcpy(target_p->user->suser, login);

    change_nick_user_host(target_p, nick, user, host, newts, "Signing %s (%s)", *login ?  "in" : "out", nick);
}
Пример #15
0
/*
 * ms_wallops (write to *all* opers currently online)
 *      parv[1] = message text
 */
static int
ms_wallops(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    if (IsClient(source_p))
        sendto_wallops_flags(UMODE_OPERWALL, source_p, "OPERWALL - %s", parv[1]);
    else
        sendto_wallops_flags(UMODE_WALLOP, source_p, "%s", parv[1]);

    sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s WALLOPS :%s",
                  use_id(source_p), parv[1]);
    sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s WALLOPS :%s", source_p->name, parv[1]);

    return 0;
}
Пример #16
0
static void
distribute_hostchange(struct Client *client)
{
	if (irccmp(client->host, client->orighost))
		sendto_one_numeric(client, RPL_HOSTHIDDEN, "%s :is now your hidden host",
			client->host);
	else
		sendto_one_numeric(client, RPL_HOSTHIDDEN, "%s :hostname reset",
			client->host);

	sendto_server(NULL, NULL,
		CAP_EUID | CAP_TS6, NOCAPS, ":%s CHGHOST %s :%s",
		use_id(&me), use_id(client), client->host);
	sendto_server(NULL, NULL,
		CAP_TS6, CAP_EUID, ":%s ENCAP * CHGHOST %s :%s",
		use_id(&me), use_id(client), client->host);
	sendto_server(NULL, NULL,
		NOCAPS, CAP_TS6, ":%s ENCAP * CHGHOST %s :%s",
		me.name, client->name, client->host);
	if (irccmp(client->host, client->orighost))
		SetDynSpoof(client);
	else
		ClearDynSpoof(client);
}
Пример #17
0
static int mo_dehelper(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
	struct Client *target_p;

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

	if(!(target_p = find_named_person(parv[1])))
	{
		sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), me.name, parv[1]);
		return 0;
	}

	if(MyClient(target_p))
		do_dehelper(source_p, target_p);
	else
		sendto_one(target_p, ":%s ENCAP %s DEHELPER %s",
				use_id(source_p), target_p->servptr->name, use_id(target_p));

	return 0;
}
Пример #18
0
/*
 * mo_operwall (write to *all* opers currently online)
 *      parv[1] = message text
 */
static int
mo_operwall(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	if(!IsOperOperwall(source_p))
	{
		sendto_one(source_p, form_str(ERR_NOPRIVS),
			   me.name, source_p->name, "operwall");
		return 0;
	}

	sendto_wallops_flags(UMODE_OPERWALL, source_p, "OPERWALL - %s", parv[1]);
	sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s OPERWALL :%s", 
		      use_id(source_p), parv[1]);

	return 0;
}
Пример #19
0
static void
forcepart_channels(struct Client *client_p, struct Client *source_p, struct Client *target_p, const char *channels, const char *reason)
{
    struct Channel *chptr = NULL;
    struct membership *msptr = NULL;
    char *name;
    char *p = NULL;
    char *chanlist;

    chanlist = LOCAL_COPY(channels);
    for(name = rb_strtok_r(chanlist, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
    {
        if((chptr = find_channel(name)) == NULL)
        {
            sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
                               form_str(ERR_NOSUCHCHANNEL), name);
            continue;
        }

        if((msptr = find_channel_membership(chptr, target_p)) == NULL)
        {
            sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
                               form_str(ERR_USERNOTINCHANNEL),
                               target_p->name, name);
            continue;
        }

        sendto_server(target_p, chptr, NOCAPS, NOCAPS,
                      ":%s PART %s :%s", use_id(target_p), chptr->chname, reason);

        sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s",
                             target_p->name, target_p->username,
                             target_p->host, chptr->chname, reason);

        remove_user_from_channel(msptr);
    }

    return;
}
Пример #20
0
/*
 * ms_wallops (write to *all* opers currently online)
 *      parv[1] = message text
 */
static int
ms_wallops(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	const char *prefix = "";

	if (IsPerson(source_p))
	{
		if (!strncmp(parv[1], "OPERWALL - ", 11) ||
				!strncmp(parv[1], "LOCOPS - ", 9) ||
				!strncmp(parv[1], "SLOCOPS - ", 10))
			prefix = "WALLOPS - ";
	}

	sendto_wallops_flags(UMODE_WALLOP, source_p, "%s%s", prefix, parv[1]);

	sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s WALLOPS :%s", 
		      use_id(source_p), parv[1]);
	sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s WALLOPS :%s", 
		      source_p->name, parv[1]);

	return 0;
}
Пример #21
0
static int
change_nick(struct Client *client_p, const char *newnick)
{
	char note[NICKLEN + 10];

	client_p->tsinfo = rb_current_time();

	monitor_signoff(client_p);

	invalidate_bancache_user(client_p);

	sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
			"Forced nick change: From %s to %s [%s@%s]",
			client_p->name, newnick, client_p->username,
			client_p->host);

	sendto_common_channels_local(client_p, NOCAPS, ":%s!%s@%s NICK :%s",
				client_p->name, client_p->username,
				client_p->host, newnick);

	add_history(client_p, 1);
	sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
			use_id(client_p), newnick, (long) client_p->tsinfo);

	del_from_client_hash(client_p->name, client_p);
	strcpy(client_p->name, newnick);
	add_to_client_hash(client_p->name, client_p);

	monitor_signon(client_p);

	del_all_accepts(client_p);

	rb_snprintf(note, NICKLEN + 10, "Nick: %s", client_p->name);
	rb_note(client_p->localClient->F, note);
	return 0;
}
Пример #22
0
static int
m_remove(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);

	*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(get_channel_access(source_p, msptr, MODE_ADD) < CHFL_CHANOP)
		{
			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;
		}

		if(MyClient(source_p))
		{
			hook_data_channel_approval hookdata;

			hookdata.client = source_p;
			hookdata.chptr = chptr;
			hookdata.msptr = msptr;
			hookdata.target = who;
			hookdata.approved = 1;
			hookdata.dir = MODE_ADD;	/* ensure modules like override speak up */

			call_hook(h_can_kick, &hookdata);

			if (!hookdata.approved)
				return 0;
		}

		comment = LOCAL_COPY((EmptyString(parv[3])) ? who->name : parv[3]);
		if(strlen(comment) > (size_t) REASONLEN)
			comment[REASONLEN] = '\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...
		 */
		sendto_channel_local(ALL_MEMBERS, chptr,
				     ":%s!%s@%s PART %s :requested by %s (%s)",
				     who->name, who->username,
				     who->host, name, source_p->name, comment);

		sendto_server(client_p, chptr, CAP_REMOVE, NOCAPS,
			      ":%s REMOVE %s %s :%s",
			      use_id(source_p), chptr->chname, use_id(who), comment);
		sendto_server(client_p, chptr, NOCAPS, CAP_REMOVE,
			      ":%s KICK %s %s :%s",
			      use_id(source_p), chptr->chname, use_id(who), 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;
}
Пример #23
0
/* m_knock
 *    parv[1] = channel
 *
 *  The KNOCK command has the following syntax:
 *   :<sender> KNOCK <channel>
 *
 *  If a user is not banned from the channel they can use the KNOCK
 *  command to have the server NOTICE the channel operators notifying
 *  they would like to join.  Helpful if the channel is invite-only, the
 *  key is forgotten, or the channel is full (INVITE can bypass each one
 *  of these conditions.  Concept by Dianora <*****@*****.**> and written by
 *  <anonymous>
 */
static int
m_knock(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Channel *chptr;
    char *p, *name;

    if(MyClient(source_p) && ConfigChannel.use_knock == 0) {
        sendto_one(source_p, form_str(ERR_KNOCKDISABLED),
                   me.name, source_p->name);
        return 0;
    }

    name = LOCAL_COPY(parv[1]);

    /* dont allow one knock to multiple chans */
    if((p = strchr(name, ',')))
        *p = '\0';

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

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

    if(IsMember(source_p, chptr)) {
        if(MyClient(source_p))
            sendto_one(source_p, form_str(ERR_KNOCKONCHAN),
                       me.name, source_p->name, name);
        return 0;
    }

    if(!((chptr->mode.mode & MODE_INVITEONLY) || (*chptr->mode.key) ||
         (chptr->mode.limit &&
          rb_dlink_list_length(&chptr->members) >= (unsigned long)chptr->mode.limit))) {
        sendto_one_numeric(source_p, ERR_CHANOPEN,
                           form_str(ERR_CHANOPEN), name);
        return 0;
    }

    /* cant knock to a +p channel */
    if(HiddenChannel(chptr)) {
        sendto_one_numeric(source_p, ERR_CANNOTSENDTOCHAN,
                           form_str(ERR_CANNOTSENDTOCHAN), name, "channel does not accept knocks");
        return 0;
    }


    if(MyClient(source_p)) {
        /* don't allow a knock if the user is banned */
        if(is_banned(chptr, source_p, NULL, NULL, NULL) == CHFL_BAN ||
           is_quieted(chptr, source_p, NULL, NULL, NULL) == CHFL_BAN) {
            sendto_one_numeric(source_p, ERR_CANNOTSENDTOCHAN,
                               form_str(ERR_CANNOTSENDTOCHAN), name, "you are banned from this channel");
            return 0;
        }

        /* local flood protection:
         * allow one knock per user per knock_delay
         * allow one knock per channel per knock_delay_channel
         */
        if(!IsOper(source_p) &&
           (source_p->localClient->last_knock + ConfigChannel.knock_delay) > rb_current_time()) {
            sendto_one(source_p, form_str(ERR_TOOMANYKNOCK),
                       me.name, source_p->name, name, "user");
            return 0;
        } else if((chptr->last_knock + ConfigChannel.knock_delay_channel) > rb_current_time()) {
            sendto_one(source_p, form_str(ERR_TOOMANYKNOCK),
                       me.name, source_p->name, name, "channel");
            return 0;
        }

        /* ok, we actually can send the knock, tell client */
        source_p->localClient->last_knock = rb_current_time();

        sendto_one(source_p, form_str(RPL_KNOCKDLVR),
                   me.name, source_p->name, name);
    }

    chptr->last_knock = rb_current_time();

    if(ConfigChannel.use_knock)
        sendto_channel_local(chptr->mode.mode & MODE_FREEINVITE ? ALL_MEMBERS : ONLY_CHANOPS,
                             chptr, form_str(RPL_KNOCK),
                             me.name, name, name, source_p->name,
                             source_p->username, source_p->host);

    sendto_server(client_p, chptr, CAP_KNOCK|CAP_TS6, NOCAPS,
                  ":%s KNOCK %s", use_id(source_p), name);
    sendto_server(client_p, chptr, CAP_KNOCK, CAP_TS6,
                  ":%s KNOCK %s", source_p->name, name);
    return 0;
}
Пример #24
0
/*
** m_away
**      parv[0] = sender prefix
**      parv[1] = away message
*/
static int
m_away(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	char *away;
	char *awy2 = LOCAL_COPY(parv[1]);

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

	if(!IsClient(source_p))
		return 0;

	away = source_p->user->away;

	if(parc < 2 || !*awy2)
	{
		/* Marking as not away */

		if(away)
		{
			/* we now send this only if they were away before --is */
			sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
				      ":%s AWAY", use_id(source_p));
			sendto_server(client_p, NULL, NOCAPS, CAP_TS6, 
				      ":%s AWAY", source_p->name);
			MyFree(away);
			source_p->user->away = NULL;
		}
		if(MyConnect(source_p))
			sendto_one(source_p, form_str(RPL_UNAWAY),
				   me.name, source_p->name);
		return 0;
	}

	/* Marking as away */

	if(MyConnect(source_p) && !IsOper(source_p) &&
	   (CurrentTime - source_p->user->last_away) < ConfigFileEntry.pace_wait)
	{
		sendto_one(source_p, form_str(RPL_LOAD2HI), 
			   me.name, source_p->name, "AWAY");
		return 0;
	}

	source_p->user->last_away = CurrentTime;

	if(strlen(awy2) > (size_t) TOPICLEN)
		awy2[TOPICLEN] = '\0';

	/* we now send this only if they weren't away already --is */
	if(!away)
	{
		sendto_server(client_p, NULL, CAP_TS6, NOCAPS, 
			      ":%s AWAY :%s", use_id(source_p), awy2);
		sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
			      ":%s AWAY :%s", source_p->name, awy2);
	}
	else
		MyFree(away);

	DupString(away, awy2);

	source_p->user->away = away;

	if(MyConnect(source_p))
		sendto_one(source_p, form_str(RPL_NOWAWAY), me.name, source_p->name);

	return 0;
}
Пример #25
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);

	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)
	{
		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(((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
					get_channel_access(source_p, chptr, msptr, MODE_ADD, NULL) >= CHFL_CHANOP) &&
				(!MyClient(source_p) ||
				 can_send(chptr, source_p, msptr)))
		{
			char topic[TOPICLEN + 1];
			char topic_info[USERHOST_REPLYLEN];
			rb_strlcpy(topic, parv[2], sizeof(topic));
			rb_sprintf(topic_info, "%s!%s@%s",
					source_p->name, source_p->username, source_p->host);

			if (ConfigChannel.strip_topic_colors)
				strip_colour(topic);

			set_channel_topic(chptr, topic, 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
			sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
					get_id(&me, source_p),
					get_id(source_p, source_p), name);
	}
	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,
					(unsigned long)chptr->topic_time);
		}
	}

	return 0;
}
Пример #26
0
/* ms_etb()
 *
 * parv[1] - channel ts
 * parv[2] - channel
 * parv[3] - topic ts
 * parv[4] - topicwho
 * parv[5] - topic
 */
static int
ms_etb(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Channel *chptr;
    const char *newtopic;
    const char *newtopicwho;
    time_t channelts, newtopicts;
    struct Client *fakesource_p, *source_server_p;
    int textchange, can_use_tb, member;

    channelts = atol(parv[1]);
    chptr = find_channel(parv[2]);

    if(chptr == NULL)
        return 0;

    newtopicts = atol(parv[3]);

    /* Hide connecting server on netburst -- jilles */
    if (IsServer(source_p) && ConfigServerHide.flatten_links &&
        !HasSentEob(source_p))
        fakesource_p = &me;
    else
        fakesource_p = source_p;

    newtopicwho = parv[4];
    newtopic = parv[parc - 1];

    if(chptr->topic == NULL || chptr->channelts > channelts ||
       (chptr->channelts == channelts && chptr->topic_time < newtopicts)) {
        textchange = chptr->topic == NULL || strcmp(chptr->topic, newtopic);
        can_use_tb = textchange && !EmptyString(newtopic) &&
                     (chptr->topic == NULL || chptr->topic_time > newtopicts);

        set_channel_topic(chptr, newtopic, newtopicwho, newtopicts);
        newtopic = chptr->topic ? chptr->topic : "";
        if (chptr->topic_info)
            newtopicwho = chptr->topic_info;

        /* Do not send a textually identical topic to clients,
         * but do propagate the new topicts/topicwho to servers.
         */
        if(textchange) {
            if (IsPerson(fakesource_p))
                sendto_channel_local(ALL_MEMBERS, chptr,
                                     ":%s!%s@%s TOPIC %s :%s",
                                     fakesource_p->name,
                                     fakesource_p->username,
                                     fakesource_p->host,
                                     chptr->chname,
                                     newtopic);
            else
                sendto_channel_local(ALL_MEMBERS, chptr,
                                     ":%s TOPIC %s :%s",
                                     fakesource_p->name,
                                     chptr->chname, newtopic);
        }
        /* Propagate channelts as given, because an older channelts
         * forces any change.
         */
        sendto_server(client_p, chptr, CAP_EOPMOD|CAP_TS6, NOCAPS,
                      ":%s ETB %ld %s %ld %s :%s",
                      use_id(source_p), (long)channelts, chptr->chname,
                      (long)newtopicts, newtopicwho, newtopic);
        source_server_p = IsServer(source_p) ? source_p : source_p->servptr;
        if (can_use_tb)
            sendto_server(client_p, chptr, CAP_TB|CAP_TS6, CAP_EOPMOD,
                          ":%s TB %s %ld %s :%s",
                          use_id(source_server_p),
                          chptr->chname, (long)newtopicts,
                          newtopicwho, newtopic);
        else if (IsPerson(source_p) && textchange) {
            member = IsMember(source_p, chptr);
            if (!member)
                sendto_server(client_p, chptr, CAP_TS6, CAP_EOPMOD,
                              ":%s SJOIN %ld %s + :@%s",
                              use_id(source_server_p),
                              (long)chptr->channelts,
                              chptr->chname, use_id(source_p));
            if (EmptyString(newtopic) ||
                newtopicts >= rb_current_time() - 60)
                sendto_server(client_p, chptr, CAP_TS6, CAP_EOPMOD,
                              ":%s TOPIC %s :%s",
                              use_id(source_p),
                              chptr->chname, newtopic);
            else {
                sendto_server(client_p, chptr, CAP_TS6, CAP_EOPMOD,
                              ":%s TOPIC %s :%s",
                              use_id(source_p),
                              chptr->chname, "");
                sendto_server(client_p, chptr, CAP_TB|CAP_TS6, CAP_EOPMOD,
                              ":%s TB %s %ld %s :%s",
                              use_id(source_server_p),
                              chptr->chname, (long)newtopicts,
                              newtopicwho, newtopic);
            }
            if (!member)
                sendto_server(client_p, chptr, CAP_TS6, CAP_EOPMOD,
                              ":%s PART %s :Topic set for %s",
                              use_id(source_p),
                              chptr->chname, newtopicwho);
        } else if (textchange) {
            /* Should not send :server ETB if not all servers
             * support EOPMOD.
             */
            sendto_server(client_p, chptr, CAP_TS6, CAP_EOPMOD,
                          ":%s NOTICE %s :*** Notice -- Dropping topic change for %s",
                          me.id, chptr->chname, chptr->chname);
        }
    }

    return 0;
}
Пример #27
0
/*
** m_kick
**      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;
	char text[10];
	const char *user;
	static char buf[BUFSIZE];
	int is_override = 0;

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

	*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;
	}

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

	if(!(who = find_chasing(source_p, user, &chasing)))
	{
		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(!can_kick_deop(msptr, find_channel_membership(chptr, who)))
		{
			if(MyConnect(source_p))
			{
				if(IsOverride(source_p))
					is_override = 1;
				else
				{
					sendto_one(source_p, ":%s 482 %s %s :You do not have the proper privileges to kick this user",
							me.name, source_p->name, name);
					return 0;
				}
			}

			/* If its a TS 0 channel, do it the old way */
			else 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';

	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;
		}

		if(MyClient(source_p) && chptr->mode.mode & MODE_NOKICK)
		{
			sendto_one_numeric(source_p, ERR_NOKICK,
					form_str(ERR_NOKICK),
					chptr->chname);
			return 0;
		}

		if (MyClient(source_p) && chptr->mode.mode & MODE_NOOPERKICK && IsOper(who))
		{
			sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
					"Overriding KICK from %s on %s in %s (channel is +M)",
					source_p->name, who->name, chptr->chname);
			sendto_one_numeric(source_p, ERR_ISCHANSERVICE,
					"%s %s :Cannot kick IRC operators from that channel.",
					who->name, chptr->chname);
			return 0;
		}

		if(MyClient(source_p))
		{
			hook_data_channel_approval hookdata;

			hookdata.client = source_p;
			hookdata.chptr = chptr;
			hookdata.target = who;
			hookdata.approved = 1;

			call_hook(h_can_kick, &hookdata);

			if (!hookdata.approved)
				return 0;
		}

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

		if(is_override)
		{
			sendto_wallops_flags(UMODE_WALLOP, &me,
					"%s is overriding KICK [%s] on [%s] [%s]",
					get_oper_name(source_p), who->name, chptr->chname, comment);
			sendto_server(NULL, chptr, NOCAPS, NOCAPS,
					":%s WALLOPS :%s is overriding KICK [%s] on [%s] [%s]",
					me.name, get_oper_name(source_p), who->name, chptr->chname, comment);
		}

		/* 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);
		remove_user_from_channel(msptr);

		rb_snprintf(text, sizeof(text), "K%s", who->id);

		/* we don't need to track NOREJOIN stuff unless it's our client being kicked */
		if(MyClient(who) && chptr->mode.mode & MODE_NOREJOIN)
			channel_metadata_time_add(chptr, text, rb_current_time(), "KICKNOREJOIN");
	}
	else if (MyClient(source_p))
		sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
				   form_str(ERR_USERNOTINCHANNEL), user, name);

	return 0;
}
Пример #28
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;
    int halfop = 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);

    *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) && !is_halfop(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;
            }
        }
        halfop = !is_chanop(msptr) && is_halfop(msptr);

        /* 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];

    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;
        }

        if (halfop && (is_chanop(msptr) || is_halfop(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;
            }
        }

        comment = LOCAL_COPY_N((EmptyString(parv[3])) ? who->name : parv[3], REASONLEN);

        /* 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,
                                 IsCloaked(source_p) ? source_p->virthost : 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;
}
Пример #29
0
/*
 * m_topic
 *      parv[0] = sender prefix
 *      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;

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

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

	if(!IsChannelName(parv[1]))
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				   form_str(ERR_NOSUCHCHANNEL), 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;
	}

	/* setting topic */
	if(parc > 2)
	{
		msptr = find_channel_membership(chptr, source_p);

		if(msptr == NULL)
		{
			sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
					form_str(ERR_NOTONCHANNEL), parv[1]);
			return 0;
		}

		if((chptr->mode.mode & MODE_TOPICLIMIT) == 0 || is_chanop(msptr) || !MyClient(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, chptr, CAP_TS6, NOCAPS,
					":%s TOPIC %s :%s",
					use_id(source_p), chptr->chname,
					chptr->topic == NULL ? "" : chptr->topic);
			sendto_server(client_p, chptr, NOCAPS, CAP_TS6,
					":%s TOPIC %s :%s",
					source_p->name, 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
			sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
					me.name, source_p->name, parv[1]);
	}
	else if(MyClient(source_p))
	{
		if(!IsMember(source_p, chptr) && SecretChannel(chptr))
		{
			sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
					form_str(ERR_NOTONCHANNEL), parv[1]);
			return 0;
		}
		if(chptr->topic == NULL)
			sendto_one(source_p, form_str(RPL_NOTOPIC),
					me.name, source_p->name, parv[1]);
		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;
}
Пример #30
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(IsOperAuspex(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];
		char topic[BUFSIZE];

		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) == 0 ||
					is_chanop(msptr)) &&
				 can_send(chptr, source_p, msptr)))
		{
			if(IsOverride(source_p))
				sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
						"%s is overriding TOPIC on [%s]",
						get_oper_name(source_p), chptr->chname);
			else
			{
				sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
						get_id(&me, source_p),
						get_id(source_p, source_p), name);
				return 0;
			}
		}

		rb_strlcpy(topic, parv[2], BUFSIZE);
		strip_colour(topic);

		rb_sprintf(topic_info, "%s!%s@%s",
				source_p->name, source_p->username, source_p->host);
		set_channel_topic(chptr, topic, 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;
}