Esempio n. 1
0
static void
ms_topic(struct Client *client_p, struct Client *source_p,
         int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  const char *from, *to;
  char topic_info[USERHOST_REPLYLEN];

  if (IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
  {
    from = me.id;
    to = source_p->id;
  }
  else
  {
    from = me.name;
    to = source_p->name;
  }

  if (EmptyString(parv[1]))
  {
    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
               from, to, "TOPIC");
    return;
  }

  if ((chptr = hash_find_channel(parv[1])) == NULL)
  {
    sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
               from, to, parv[1]);
    return;
  }

  if (!IsClient(source_p))
    strlcpy(topic_info, source_p->name, sizeof(topic_info));
  else
    snprintf(topic_info, sizeof(topic_info), "%s!%s@%s", source_p->name,
             source_p->username, source_p->host);
  set_channel_topic(chptr, parv[2], topic_info, CurrentTime, 0);

  sendto_server(client_p, CAP_TS6, NOCAPS, ":%s TOPIC %s :%s",
                ID(source_p), chptr->chname,
                chptr->topic);
  sendto_server(client_p, NOCAPS, CAP_TS6, ":%s TOPIC %s :%s",
                source_p->name, chptr->chname,
                chptr->topic);

  if (!IsClient(source_p))
    sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s TOPIC %s :%s",
                         source_p->name,
                         chptr->chname, chptr->topic);

  else
    sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s TOPIC %s :%s",
                         source_p->name,
                         source_p->username,
                         source_p->host,
                         chptr->chname, chptr->topic);
}
Esempio n. 2
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,
                const char *name, char *reason)
{
  struct Channel *chptr = NULL;
  struct Membership *ms = NULL;

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

  if ((ms = find_channel_link(source_p, chptr)) == NULL)
  {
    sendto_one(source_p, form_str(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(msg_has_colors(reason) && (chptr->mode.mode & MODE_NOCOLOR)) 
    reason = strip_color(reason); 
  
  if (reason[0] && (!MyConnect(source_p) ||
      ((can_send(chptr, source_p, ms) &&
       (source_p->firsttime + ConfigFileEntry.anti_spam_exit_message_time)
        < CurrentTime))))
  {
    sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                  ":%s PART %s :%s", 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, NO, 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", 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, NO, chptr, ":%s!%s@%s PART %s",
                         source_p->name, source_p->username,
                         source_p->host, chptr->chname);
  }

  remove_user_from_channel(ms);
}
Esempio n. 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;
}
Esempio n. 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);
}
Esempio n. 5
0
/*
 * remove_a_mode
 *
 * inputs       -
 * output       - NONE
 * side effects - remove ONE mode from a channel
 */
static void remove_a_mode( int hide_or_not,
                           struct Channel *chptr, struct Channel *top_chptr,
                           struct Client *source_p, dlink_list *list, char flag)
{
  dlink_node *ptr;
  struct Client *target_p;
  char buf[BUFSIZE];
  char lmodebuf[MODEBUFLEN];
  char *lpara[MAXMODEPARAMS];
  char *chname;
  int count = 0;

  mbuf = lmodebuf;
  *mbuf++ = '-';

  lpara[0] = lpara[1] = lpara[2] = lpara[3] = "";

  chname = chptr->chname;

  ircsprintf(buf,":%s MODE %s ", me.name, chname);

  for (ptr = list->head; ptr && ptr->data; ptr = ptr->next)
    {
      target_p = ptr->data;
      lpara[count++] = target_p->name;

      *mbuf++ = flag;
      if (count >= MAXMODEPARAMS)
        {
          *mbuf   = '\0';
          sendto_channel_local(hide_or_not, chptr,
                               ":%s MODE %s %s %s %s %s %s",
                               me.name,
                               chname,
                               lmodebuf,
                               lpara[0], lpara[1], lpara[2], lpara[3] );

          mbuf = lmodebuf;
          *mbuf++ = '-';
          count = 0;
          lpara[0] = lpara[1] = lpara[2] = lpara[3] = "";
        }
    }

  if(count != 0)
    {
      *mbuf   = '\0';
      sendto_channel_local(hide_or_not, chptr,
                           ":%s MODE %s %s %s %s %s %s",
                           me.name,
                           chname,
                           lmodebuf,
                           lpara[0], lpara[1], lpara[2], lpara[3] );

    }
}
Esempio n. 6
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);
}
Esempio n. 7
0
void kick_list(struct Client *client_p, struct Client *source_p, struct Channel *chptr,
	       dlink_list *list,char *chname)
{
  struct Client *who;
  dlink_node *m;
  dlink_node *next_m;

  for (m = list->head; m; m = next_m)
    {
      next_m = m->next;
      who = m->data;
      sendto_channel_local(ALL_MEMBERS, chptr,
			   ":%s KICK %s %s :CLEARCHAN",
			   source_p->name, chname, who->name);
      sendto_server(NULL, source_p, chptr, NOCAPS, NOCAPS, LL_ICLIENT,
                    ":%s KICK %s %s :CLEARCHAN", source_p->name,
                    chname, who->name);
      remove_user_from_channel(chptr, who);
    }

  /* Join the user themselves to the channel down here, so they dont see a nicklist 
   * or people being kicked */
  sendto_one(source_p, ":%s!%s@%s JOIN %s",
	     source_p->name,
	     source_p->username,
	     source_p->host,
	     chname);

  channel_member_names(source_p, chptr, chname, 1);

}
Esempio n. 8
0
/*
 * set_topic
 *
 * inputs	- source_p pointer
 *		- channel pointer
 *		- topicts to set
 *		- who to set as who doing the topic
 *		- topic
 * output	- none
 * Side effects	- simply propagates topic as needed
 * little helper function, could be removed
 */
static void
set_topic(struct Client *source_p, struct Channel *chptr, time_t topicts,
          const char *topicwho, const char *topic)
{
  int new_topic = strcmp(chptr->topic ? chptr->topic : "", topic);

  set_channel_topic(chptr, topic, topicwho, topicts);

  /* Only send TOPIC to channel if it's different */
  if (new_topic)
    sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s TOPIC %s :%s",
                         ConfigServerHide.hide_servers ? me.name : source_p->name,
                         chptr->chname, chptr->topic == NULL ? "" : chptr->topic);

  sendto_server(source_p, chptr, CAP_TBURST, NOCAPS,
                ":%s TBURST %lu %s %lu %s :%s",
                me.name, (unsigned long)chptr->channelts, chptr->chname,
                (unsigned long)chptr->topic_time,
                chptr->topic_info == NULL ? "" : chptr->topic_info,
                chptr->topic == NULL ? "" : chptr->topic);
  sendto_server(source_p, chptr, CAP_TB, CAP_TBURST,
                ":%s TB %s %lu %s :%s",
                me.name, chptr->chname,
                (unsigned long)chptr->topic_time, 
                chptr->topic_info == NULL ? "" : chptr->topic_info,
                chptr->topic == NULL ? "" : chptr->topic);
}
Esempio n. 9
0
static void do_join_0(struct Client *client_p, struct Client *source_p)
{
  struct Channel *chptr=NULL;
  dlink_node   *lp;

  /* Finish the flood grace period... */
  if(MyClient(source_p) && !IsFloodDone(source_p))
      flood_endgrace(source_p);
          
          
  sendto_server(client_p, NULL, NOCAPS, NOCAPS, 
                ":%s JOIN 0", source_p->name);

  if (source_p->user->channel.head &&
      MyConnect(source_p) && !IsOper(source_p))
   check_spambot_warning(source_p, NULL);

  while ((lp = source_p->user->channel.head))
    {
      chptr = lp->data;
      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(chptr, source_p);
    }
}
Esempio n. 10
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;
}
Esempio n. 11
0
/*! \brief TOPIC command handler
 *
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *      - parv[0] = command
 *      - parv[1] = channel name
 *      - parv[2] = topic text
 */
static int
ms_topic(struct Client *source_p, int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  char topic_info[USERHOST_REPLYLEN];

  if (EmptyString(parv[1]))
  {
    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "TOPIC");
    return 0;
  }

  if ((chptr = hash_find_channel(parv[1])) == NULL)
  {
    sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]);
    return 0;
  }

  if (!IsClient(source_p))
    strlcpy(topic_info, source_p->name, sizeof(topic_info));
  else
    snprintf(topic_info, sizeof(topic_info), "%s!%s@%s", source_p->name,
             source_p->username, source_p->host);
  channel_set_topic(chptr, parv[2], topic_info, CurrentTime, 0);

  sendto_server(source_p, 0, 0, ":%s TOPIC %s :%s",
                source_p->id, chptr->name,
                chptr->topic);

  if (!IsClient(source_p))
    sendto_channel_local(0, chptr, ":%s TOPIC %s :%s",
                        (IsHidden(source_p) || ConfigServerHide.hide_servers) ? me.name : source_p->name,
                         chptr->name, chptr->topic);

  else
    sendto_channel_local(0, chptr, ":%s!%s@%s TOPIC %s :%s",
                         source_p->name,
                         source_p->username,
                         source_p->host,
                         chptr->name, chptr->topic);
  return 0;
}
Esempio n. 12
0
/*
 * ms_topic
 *      parv[0] = sender prefix
 *      parv[1] = channel name
 *	parv[2] = topic_info
 *	parv[3] = topic_info time
 *	parv[4] = new channel topic
 *
 * Let servers always set a topic
 */
static void ms_topic(struct Client *client_p,
                    struct Client *source_p,
                    int parc,
                    char *parv[])
{
  struct Channel *chptr = NULL;
  
  if (!IsServer(source_p))
  {
    m_topic(client_p, source_p, parc, parv);
    return;
  }

  if( parc < 5 )
    return;

  if (parv[1] && IsChannelName(parv[1]))
    {
      if ((chptr = hash_find_channel(parv[1])) == NULL)
	return;
      
      set_channel_topic(chptr, parv[4], parv[2], atoi(parv[3]));

      if(ConfigServerHide.hide_servers)
	{
	  sendto_channel_local(ALL_MEMBERS,
			       chptr, ":%s TOPIC %s :%s",
			       me.name,
			       parv[1],
			       chptr->topic == NULL ? "" : chptr->topic);

	}
      else
	{
	  sendto_channel_local(ALL_MEMBERS,
			       chptr, ":%s TOPIC %s :%s",
			       source_p->name,
			       parv[1], chptr->topic == NULL ? "" : chptr->topic);
	}
    }
}
Esempio n. 13
0
static int
mo_forcepart(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Client *target_p;
	struct Channel *chptr;
	struct membership *msptr;

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

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

	/* if target_p == NULL then let the oper know */
	if((target_p = find_client(parv[1])) == NULL)
	{
		sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, parv[1]);
		return 0;
	}

	if(!IsClient(target_p))
		return 0;


	if((chptr = find_channel(parv[2])) == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				   form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return 0;
	}

	if((msptr = find_channel_membership(chptr, target_p)) == NULL)
	{
		sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
			   me.name, source_p->name, parv[1], parv[2]);
		return 0;
	}

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

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


	remove_user_from_channel(msptr);

	return 0;
}
Esempio n. 14
0
static int
me_roleplay(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Channel *chptr;

    /* Don't segfault if we get ROLEPLAY with an invalid channel.
     * This shouldn't happen but it's best to be on the safe side. */
    if((chptr = find_channel(parv[1])) == NULL)
        return 0;

    sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%[email protected] PRIVMSG %s :%s (%s)", parv[2], source_p->name, parv[1], parv[3], source_p->name);
    return 0;
}
Esempio n. 15
0
/*
 * ms_topic
 *      parv[1] = channel name
 *	parv[2] = topic_info
 *	parv[3] = topic_info time
 *	parv[4] = new channel topic
 *
 * Let servers always set a topic
 */
static int
ms_topic(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;

	if((chptr = find_channel(parv[1])) == NULL)
		return 0;

	set_channel_topic(chptr, parv[4], parv[2], atoi(parv[3]));

	sendto_channel_local(ALL_MEMBERS, chptr, ":%s TOPIC %s :%s",
			     source_p->name, parv[1],
			     chptr->topic == NULL ? "" : chptr->topic);

	return 0;
}
Esempio n. 16
0
static void
set_topic(struct Client *source_p, struct Channel *chptr, 
          time_t newtopicts, char *topicwho, char *topic)
{
  set_channel_topic(chptr, topic, topicwho, newtopicts);

  sendto_channel_local(ALL_MEMBERS, chptr, ":%s TOPIC %s :%s", source_p->name,
		       chptr->chname, chptr->topic == NULL ? "" : chptr->topic);

#ifdef TBURST_PROPAGATE
  sendto_server(source_p, NULL, chptr, CAP_TBURST, NOCAPS, NOFLAGS,
		":%s TBURST %ld %s %ld %s :%s",
		me.name, (unsigned long)chptr->channelts, chptr->chname,
		(unsigned long)chptr->topic_time, 
                chptr->topic_info == NULL ? "" : chptr->topic_info,
                chptr->topic == NULL ? "" : chptr->topic);
#endif
}
Esempio n. 17
0
int
show_privmsg(struct hook_privmsg_data *data)
{
  struct Channel *acptr;
  struct Client *from_p;

  from_p = find_client(data->from);

  acptr = get_or_create_channel(from_p, TARGET_CHANNEL, NULL);

  sendto_realops_flags(UMODE_ALL, L_ALL, "debug: intercepted pm %s %s %s %s",
                 data->type, data->from, data->to, data->text);

  sendto_channel_local(ALL_MEMBERS, acptr, MSGFORMAT, me.name, TARGET_CHANNEL, 
                 data->type, data->from,
                 data->to, data->text);
 
  return 0;
}
Esempio n. 18
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;
}
Esempio n. 19
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;
}
Esempio n. 20
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;
}
Esempio n. 21
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;
}
Esempio n. 22
0
/* mo_ojoin()
 *      parv[0] = sender prefix
 *      parv[1] = channels separated by commas (#ifdef OJOIN_MULTIJOIN)
 */
static void
mo_ojoin(struct Client *client_p, struct Client *source_p,
         int parc, char *parv[])
{
    struct Channel *chptr;
    char *name = parv[1], modeletter;
#ifdef OJOIN_MULTIJOIN
    char *t;
#endif
    short move_me = 1;
    unsigned int tmp_flags;

    /* admins only */
    if (!IsAdmin(source_p))
    {
        sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
                   me.name, source_p->name);
        return;
    }

#ifdef OJOIN_MULTIJOIN
    for (name = strtoken (&t, name, ","); name;
            name = strtoken (&t, NULL, ","))
    {
#endif

        move_me = 1;

        switch (*name)
        {
#ifndef DISABLE_CHAN_OWNER
        case '!':
            tmp_flags = CHFL_CHANOWNER;
            modeletter = 'u';
            name++;
            break;
#endif
        case '@':
            tmp_flags = CHFL_CHANOP;
            modeletter = 'o';
            name++;
            break;
        case '+':
            tmp_flags = CHFL_VOICE;
            modeletter = 'v';
            name++;
            break;
        case '%':
            tmp_flags = CHFL_HALFOP;
            modeletter = 'h';
            name++;
            break;
        case '#':
        case '&':
            tmp_flags = 0;
            modeletter = '\0';
            break;

        /* We're not joining a channel, or we don't know the mode,
        * what ARE we joining? */
        default:
            sendto_one (source_p, form_str(ERR_NOSUCHCHANNEL),
                        me.name, source_p->name, name);

#ifdef OJOIN_MULTIJOIN
            continue;
#else
            return;
#endif
        }

        /* Error checking here */

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

        else if (IsMember(source_p, chptr))
        {
            sendto_one(source_p, ":%s NOTICE %s :Please part %s before using OJOIN",
                       me.name, source_p->name, name);
        }

        else
        {
            if (move_me == 1)
                name--;

            add_user_to_channel(chptr, source_p, tmp_flags);

            if (chptr->chname[0] == '#')
            {
                sendto_server(client_p, CAP_TS6, NOCAPS,
                              ":%s SJOIN %lu %s + :%c%s",
                              me.id, (unsigned long)chptr->channelts, chptr->chname,
                              (modeletter != '\0') ? *name : ' ',
                              source_p->id);
                sendto_server(client_p, NOCAPS, CAP_TS6,
                              ":%s SJOIN %lu %s + :%c%s", me.name,
                              (unsigned long)chptr->channelts,
                              chptr->chname, (modeletter != '\0') ? *name : ' ',
                              source_p->name);
            }

            sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s",
                                 source_p->name,
                                 source_p->username,
                                 GET_CLIENT_HOST(source_p),
                                 chptr->chname);

            if (modeletter != '\0')
            {
                sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +%c %s",
                                     me.name, chptr->chname, modeletter, source_p->name);
            }

            /* send the topic... */
            if (chptr->topic != NULL)
            {
                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);
            }

            source_p->localClient->last_join_time = CurrentTime;
            channel_member_names(source_p, chptr, 1);
        }
#ifdef OJOIN_MULTIJOIN
    }
#endif
}
Esempio n. 23
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;
}
Esempio n. 24
0
/*
 * ms_bmask()
 *
 * inputs	- parv[0] = SID
 *		  parv[1] = TS
 *		  parv[2] = channel name
 *		  parv[3] = type of ban to add ('b' 'I' or 'e')
 *		  parv[4] = space delimited list of masks to add
 * outputs	- none
 * side effects	- propgates unchanged bmask line to CAP_TS6 servers,
 *		  sends plain modes to the others.  nothing is sent
 *		  to the server the issuing server is connected through
 */
static void
ms_bmask(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
  static char modebuf[BUFSIZE];
  static char parabuf[BUFSIZE];
  static char banbuf[BUFSIZE];
  struct Channel *chptr;
  char *s, *t, *mbuf, *pbuf;
  long mode_type;
  int mlen;
  int plen = 0;
  int tlen;
  int modecount = 0;
  int needcap = NOCAPS;

  if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
    return;

  if((chptr = hash_find_channel(parv[2])) == NULL)
    return;

  /* TS is higher, drop it. */
  if(atol(parv[1]) > chptr->channelts)
    return;

  switch(parv[3][0])
  {
    case 'b':
      mode_type = CHFL_BAN;
      break;

    case 'e':
      mode_type = CHFL_EXCEPTION;
      needcap = CAP_EX;
      break;

    case 'I':
      mode_type = CHFL_INVEX;
      needcap = CAP_IE;
      break;

    /* maybe we should just blindly propagate this? */
    default:
      return; 
  }

  parabuf[0] = '\0';
  s = banbuf;
  strlcpy(s, parv[4], sizeof(banbuf));

  /* only need to construct one buffer, for non-ts6 servers */
  mlen = ircsprintf(modebuf, ":%s MODE %s +",
                    source_p->name, chptr->chname);
  mbuf = modebuf + mlen;
  pbuf = parabuf;

  if((t = strchr(s, ' ')) != NULL)
    *t++ = '\0';

  while(s != NULL)
  {
    tlen = strlen(s);

    /* I dont even want to begin parsing this.. */
    if(tlen > MODEBUFLEN)
      break;

    if(tlen && add_id(source_p, chptr, s, mode_type))
    {
      /* this new one wont fit.. */
      if(mlen + MAXMODEPARAMS + plen + tlen > BUFSIZE - 4 ||
         modecount >= MAXMODEPARAMS)
      {
        *mbuf = '\0';
        *(pbuf - 1) = '\0';
        sendto_channel_local(ALL_MEMBERS, chptr, "%s %s",
                             modebuf, parabuf);
        sendto_server(client_p, NULL, chptr, needcap, CAP_TS6, NOFLAGS,
                      "%s %s",
                      modebuf, parabuf);

        mbuf = modebuf + mlen;
        pbuf = parabuf;
        plen = modecount = 0;
      }

      *mbuf++ = parv[3][0];
      plen = ircsprintf(pbuf, "%s ", s);
      pbuf += plen;
      modecount++;
    }

    s = t;

    if(s != NULL)
    {
      /* trailing space marking the end. */
      if(*s == '\0')
        break;

      if((t = strchr(s, ' ')) != NULL)
        *t++ = '\0';
    }
  }

  if(modecount)
  {
    *mbuf = *(pbuf - 1) = '\0';
    sendto_channel_local(ALL_MEMBERS, chptr, "%s %s", modebuf, parabuf);
    sendto_server(client_p, NULL, chptr, needcap, CAP_TS6, NOFLAGS,
                  "%s %s", modebuf, parabuf);
  }

  /* assumption here is that since the server sent BMASK, they are TS6, so they have an ID */
  sendto_server(client_p, NULL, chptr, CAP_TS6|needcap, NOCAPS, NOFLAGS,
                ":%s BMASK %lu %s %s :%s",
                 source_p->id, (unsigned long)chptr->channelts, chptr->chname,
                 parv[3], parv[4]);
}
Esempio n. 25
0
/*
 * m_lljoin
 *      parv[0] = sender prefix
 *      parv[1] = channel
 *      parv[2] = nick ("!nick" == cjoin)
 *      parv[3] = vchan/key (optional)
 *      parv[4] = key (optional)
 *
 * If a lljoin is received, from our uplink, join
 * the requested client to the given channel, or ignore it
 * if there is an error.
 *
 *   Ok, the way this works. Leaf client tries to join a channel, 
 * it doesn't exist so the join does a cburst request on behalf of the
 * client, and aborts that join. The cburst sjoin's the channel if it
 * exists on the hub, and sends back an LLJOIN to the leaf. Thats where
 * this is now..
 *
 */
static void ms_lljoin(struct Client *client_p,
                     struct Client *source_p,
                     int parc,
                     char *parv[])
{
  char *chname = NULL;
  char *nick = NULL;
  char *key = NULL;
  char *vkey = NULL;
  int  flags;
  int  i;
  struct Client *target_p;
  struct Channel *chptr, *vchan_chptr, *root_vchan;
#ifdef VCHANS
  int cjoin = 0;
  int  vc_ts;
  char *pvc = NULL;
#endif

  if(uplink && !IsCapable(uplink,CAP_LL))
    {
      sendto_realops_flags(FLAGS_ALL, L_ALL,
			   "*** LLJOIN requested from non LL server %s",
			   client_p->name);
      return;
    }

  chname = parv[1];
  if(chname == NULL)
    return;

  nick = parv[2];
  if(nick == NULL)
    return;

#ifdef VCHANS
  if (nick[0] == '!')
  {
    cjoin = 1;
    nick++;
  }
 
  if(parc > 4)
  {
    key = parv[4];
    vkey = parv[3];
  }
#endif
  else if(parc >3)
  {
    key = vkey = parv[3];
  }

  flags = 0;

  target_p = find_client(nick);

  if( !target_p || !target_p->user )
    return;

  if( !MyClient(target_p) )
    return;

  chptr = hash_find_channel(chname);

#ifdef VCHANS
  if (cjoin)
  {
    if(!chptr) /* Uhm, bad! */
    {
      sendto_realops_flags(FLAGS_ALL, L_ALL,
        "LLJOIN %s %s called by %s, but root chan doesn't exist!",
        chname, nick, client_p->name);
      return;
    }
    flags = CHFL_CHANOP;

    if(! (vchan_chptr = cjoin_channel(chptr, target_p, chname)))
      return;

    root_vchan = chptr;
    chptr = vchan_chptr;
  }
  else
#endif
  {
#ifdef VCHANS
    if (chptr)
    {
      vchan_chptr = select_vchan(chptr, target_p, vkey, chname);
    }
    else
#endif
    {
      chptr = vchan_chptr = get_or_create_channel(target_p, chname, NULL);
      flags = CHFL_CHANOP;
    }
   
#ifdef VCHANS
    if (vchan_chptr != chptr)
    {
      root_vchan = chptr;
      chptr = vchan_chptr;
    }
    else
#endif
      root_vchan = chptr;

    if(!chptr || !root_vchan)
      return;

    if (chptr->users == 0)
      flags = CHFL_CHANOP;
    else
      flags = 0;

    /* XXX in m_join.c :( */
    /* check_spambot_warning(target_p, chname); */

    /* They _could_ join a channel twice due to lag */
    if(chptr)
    {
      if (IsMember(target_p, chptr))    /* already a member, ignore this */
        return;
    }
    else
    {
      sendto_one(target_p, form_str(ERR_UNAVAILRESOURCE),
                 me.name, nick, root_vchan->chname);
      return;
    }

    if( (i = can_join(target_p, chptr, key)) )
    {
      sendto_one(target_p,
                 form_str(i), me.name, nick, root_vchan->chname);
      return;
    }
  }

  if ((target_p->user->joined >= ConfigChannel.max_chans_per_user) &&
      (!IsOper(target_p) || (target_p->user->joined >= 
                             ConfigChannel.max_chans_per_user*3)))
    {
      sendto_one(target_p, form_str(ERR_TOOMANYCHANNELS),
		 me.name, nick, root_vchan->chname );
      return; 
    }
  
  if(flags == CHFL_CHANOP)
    {
      chptr->channelts = CurrentTime;
      /*
       * XXX - this is a rather ugly hack.
       *
       * Unfortunately, there's no way to pass
       * the fact that it is a vchan through SJOIN...
       */
      /* Prevent users creating a fake vchan */
#ifdef VCHANS
      if (chname[0] == '#' && chname[1] == '#')
        {
          if ((pvc = strrchr(chname+3, '_')))
          {
            /*
             * OK, name matches possible vchan:
             * ##channel_blah
             */
            pvc++; /*  point pvc after last _ */
            vc_ts = atol(pvc);
            /*
             * if blah is the same as the TS, up the TS
             * by one, to prevent this channel being
             * seen as a vchan
             */
            if (vc_ts == CurrentTime)
              chptr->channelts++;
          }
        }
#endif

      sendto_one(uplink,
		 ":%s SJOIN %lu %s + :@%s",
		 me.name,
		 (unsigned long) chptr->channelts,
		 chptr->chname,
		 nick);
    }

  /* a user can create a channel with halfops..? */
#if 0
  else if ((flags == CHFL_HALFOP) && (IsCapable(uplink, CAP_HOPS)))
    {
      sendto_one(uplink,
		 ":%s SJOIN %lu %s + :%%%s",
		 me.name,
		 (unsigned long) chptr->channelts,
		 chptr->chname,
		 nick);
    }
#endif
  else
    {
      sendto_one(uplink,
		 ":%s SJOIN %lu %s + :%s",
		 me.name,
		 (unsigned long) chptr->channelts,
		 chptr->chname,
		 nick);
    }

  add_user_to_channel(chptr, target_p, flags);

#ifdef VCHANS
  if ( chptr != root_vchan )
    add_vchan_to_client_cache(target_p,root_vchan,chptr);
#endif
 
  sendto_channel_local(ALL_MEMBERS, chptr,
		       ":%s!%s@%s JOIN :%s",
		       target_p->name,
		       target_p->username,
		       target_p->host,
		       root_vchan->chname);
  
  if( flags & CHFL_CHANOP )
  {
    chptr->mode.mode |= MODE_TOPICLIMIT;
    chptr->mode.mode |= MODE_NOPRIVMSGS;
      
    sendto_channel_local(ALL_MEMBERS,chptr,
                         ":%s MODE %s +nt",
                         me.name, root_vchan->chname);
    sendto_one(uplink, 
               ":%s MODE %s +nt",
               me.name, chptr->chname);
  }

  channel_member_names(target_p, chptr, chname, 1);
}
Esempio n. 26
0
/*
 *
 *      parc    number of arguments ('sender' counted as one!)
 *      parv[0] pointer to 'sender' (may point to empty string) (not used)
 *      parv[1]..parv[parc-1]
 *              pointers to additional parameters, this is a NULL
 *              terminated list (parv[parc] == NULL).
 *
 * *WARNING*
 *      Numerics are mostly error reports. If there is something
 *      wrong with the message, just *DROP* it! Don't even think of
 *      sending back a neat error message -- big danger of creating
 *      a ping pong error message...
 */
static void
do_numeric(char numeric[], struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	struct Client *target_p;
	struct Channel *chptr;

	if(parc < 2 || !IsServer(source_p))
		return;

	/* Remap low number numerics. */
	if(numeric[0] == '0')
		numeric[0] = '1';

	/*
	 * Prepare the parameter portion of the message into 'buffer'.
	 * (Because the buffer is twice as large as the message buffer
	 * for the socket, no overflow can occur here... ...on current
	 * assumptions--bets are off, if these are changed --msa)
	 * Note: if buffer is non-empty, it will begin with SPACE.
	 */
	if(parc > 1)
	{
		char *t = buffer;	/* Current position within the buffer */
		int i;
		int tl;		/* current length of presently being built string in t */
		for (i = 2; i < (parc - 1); i++)
		{
			tl = ircsprintf(t, " %s", parv[i]);
			t += tl;
		}
		ircsprintf(t, " :%s", parv[parc - 1]);
	}

	if((target_p = find_client(parv[1])) != NULL)
	{
		if(IsMe(target_p))
		{
			/*
			 * We shouldn't get numerics sent to us,
			 * any numerics we do get indicate a bug somewhere..
			 */
			/* ugh.  this is here because of nick collisions.  when two servers
			 * relink, they burst each other their nicks, then perform collides.
			 * if there is a nick collision, BOTH servers will kill their own
			 * nicks, and BOTH will kill the other servers nick, which wont exist,
			 * because it will have been already killed by the local server.
			 *
			 * unfortunately, as we cant guarantee other servers will do the
			 * "right thing" on a nick collision, we have to keep both kills.  
			 * ergo we need to ignore ERR_NOSUCHNICK. --fl_
			 */
			/* quick comment. This _was_ tried. i.e. assume the other servers
			 * will do the "right thing" and kill a nick that is colliding.
			 * unfortunately, it did not work. --Dianora
			 */
			if(atoi(numeric) != ERR_NOSUCHNICK)
				sendto_realops_flags(UMODE_ALL, L_ADMIN,
						     "*** %s(via %s) sent a %s numeric to me: %s",
						     source_p->name, client_p->name, numeric,
						     buffer);
			return;
		}
		else if(target_p->from == client_p)
		{
			/* This message changed direction (nick collision?)
			 * ignore it.
			 */
			return;
		}

		/* csircd will send out unknown umode flag for +a (admin), drop it here. */
		if((atoi(numeric) == ERR_UMODEUNKNOWNFLAG) && MyClient(target_p))
			return;

		/* Fake it for server hiding, if its our client */
		if(ConfigServerHide.hide_servers && MyClient(target_p) && !IsOper(target_p))
			sendto_one(target_p, ":%s %s %s%s", me.name, numeric, parv[1], buffer);
		else
			sendto_one(target_p, ":%s %s %s%s", source_p->name, numeric, parv[1],
				   buffer);
		return;
	}
	else if((chptr = hash_find_channel(parv[1])) != NULL)
		sendto_channel_local(ALL_MEMBERS, chptr,
				     ":%s %s %s %s",
				     source_p->name, numeric, chptr->chname, buffer);
}
Esempio n. 27
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;
}
Esempio n. 28
0
static int
m_displaymsg(struct Client *source_p, const char *channel, int underline, int action, const char *nick, const char *text)
{
    struct Channel *chptr;
    struct membership *msptr;
    char nick2[NICKLEN+1];
    char nick3[NICKLEN+1];
    char text2[BUFSIZE];

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

    if(!(msptr = find_channel_membership(chptr, source_p))) {
        sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
                           form_str(ERR_NOTONCHANNEL), chptr->chname);
        return 0;
    }

    if(!(chptr->mode.mode & chmode_flags['N'])) {
        sendto_one_numeric(source_p, 573, "%s :Roleplay commands are not enabled on this channel.", chptr->chname);
        return 0;
    }

    if(!can_send(chptr, source_p, msptr)) {
        sendto_one_numeric(source_p, 573, "%s :Cannot send to channel.", chptr->chname);
        return 0;
    }

    /* enforce flood stuff on roleplay commands */
    if(flood_attack_channel(0, source_p, chptr, chptr->chname))
        return 0;

    /* enforce target change on roleplay commands */
    if(!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;
    }

    rb_strlcpy(nick3, nick, sizeof(nick3));

    if(underline)
        snprintf(nick2, sizeof(nick2), "\x1F%s\x1F", strip_unprintable(nick3));
    else
        snprintf(nick2, sizeof(nick2), "%s", strip_unprintable(nick3));

    /* don't allow nicks to be empty after stripping
     * this prevents nastiness like fake factions, etc. */
    if(EmptyString(nick3)) {
        sendto_one_numeric(source_p, 573, "%s :No visible non-stripped characters in nick.", chptr->chname);
        return 0;
    }

    if(action)
        snprintf(text2, sizeof(text2), "\1ACTION %s\1", text);
    else
        snprintf(text2, sizeof(text2), "%s", text);

    sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%[email protected] PRIVMSG %s :%s (%s)", nick2, source_p->name, channel, text2, source_p->name);
    sendto_match_servs(source_p, "*", CAP_ENCAP, NOCAPS, "ENCAP * ROLEPLAY %s %s :%s",
                       channel, nick2, text2);
    return 0;
}
Esempio n. 29
0
/*! \brief BMASK command handler
 *
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *      - parv[0] = command
 *      - parv[1] = timestamp
 *      - parv[2] = channel name
 *      - parv[3] = type of ban to add ('b' 'I' or 'e')
 *      - parv[4] = space delimited list of masks to add
 */
static int
ms_bmask(struct Client *source_p, int parc, char *parv[])
{
  char modebuf[IRCD_BUFSIZE] = "";
  char parabuf[IRCD_BUFSIZE] = "";
  char banbuf[IRCD_BUFSIZE] = "";
  struct Channel *chptr = NULL;
  char *s, *t, *mbuf, *pbuf;
  unsigned int mode_type = 0;
  int mlen = 0, tlen = 0;
  int modecount = 0;

  if ((chptr = hash_find_channel(parv[2])) == NULL)
    return 0;

  /* TS is higher, drop it. */
  if (atol(parv[1]) > chptr->channelts)
    return 0;

  switch (*parv[3])
  {
    case 'b':
      mode_type = CHFL_BAN;
      break;
    case 'e':
      mode_type = CHFL_EXCEPTION;
      break;
    case 'I':
      mode_type = CHFL_INVEX;
      break;
    default:
      return 0;
  }

  strlcpy(banbuf, parv[4], sizeof(banbuf));
  s = banbuf;

  mlen = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s +",
                  (IsHidden(source_p) || ConfigServerHide.hide_servers) ? me.name : source_p->name,
                  chptr->chname);
  mbuf = modebuf + mlen;
  pbuf = parabuf;

  do
  {
    if ((t = strchr(s, ' ')))
      *t++ = '\0';
    tlen = strlen(s);

    /* I don't even want to begin parsing this.. */
    if (tlen > MODEBUFLEN)
      break;

    if (tlen && *s != ':' && add_id(source_p, chptr, s, mode_type))
    {
      /* this new one wont fit.. */
      if (mbuf - modebuf + 2 + pbuf - parabuf + tlen > IRCD_BUFSIZE - 2 ||
          modecount >= MAXMODEPARAMS)
      {
        *mbuf = *(pbuf - 1) = '\0';

        sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", modebuf, parabuf);
        mbuf = modebuf + mlen;
        pbuf = parabuf;
        modecount = 0;
      }

      *mbuf++ = *parv[3];
      pbuf += sprintf(pbuf, "%s ", s);
      ++modecount;
    }

    s = t;
  } while (s);

  if (modecount)
  {
    *mbuf = *(pbuf - 1) = '\0';
    sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", modebuf, parabuf);
  }

  sendto_server(source_p, NOCAPS, NOCAPS, ":%s BMASK %lu %s %s :%s",
                source_p->id, (unsigned long)chptr->channelts, chptr->chname,
                parv[3], parv[4]);
  return 0;
}
Esempio n. 30
0
/*
** mo_ojoin
**      parv[1] = channel
*/
static int
mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr;
	int move_me = 0;

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

	if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+' || *parv[1] == '!'
	   || *parv[1] == '~')
	{
		parv[1]++;
		move_me = 1;
	}
	else
	{
		sendto_one_notice(source_p, ":Unrecognized op prefix '%c'", *parv[1]);
		return 0;
	}

	if((chptr = find_channel(parv[1])) == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				   form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return 0;
	}

	if(IsMember(source_p, chptr))
	{
		sendto_one_notice(source_p, ":Please part %s before using OJOIN", parv[1]);
		return 0;
	}

	if(move_me == 1)
		parv[1]--;

	/* only sends stuff for #channels remotely */

	if(*parv[1] == '!')
	{
		if(!ConfigChannel.use_admin)
		{
			sendto_one_notice(source_p,
					  ":This server's configuration file does not support admin prefix");
			return 0;
		}

		add_user_to_channel(chptr, source_p, CHFL_ADMIN);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :!%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s",
				     source_p->name,
				     source_p->username, source_p->host, chptr->chname);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +a %s",
				     me.name, chptr->chname, source_p->name);

	}
	else if(*parv[1] == '@')
	{
		add_user_to_channel(chptr, source_p, CHFL_CHANOP);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :@%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s",
				     me.name, chptr->chname, source_p->name);

	}
	else if(*parv[1] == '%')
	{
		if(!ConfigChannel.use_halfop)
		{
			sendto_one_notice(source_p,
					  ":This server's configuration file does not support halfop prefix");
			return 0;
		}

		add_user_to_channel(chptr, source_p, CHFL_HALFOP);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :%s%s",
			      me.id, (long) chptr->channelts, chptr->chname, "%", source_p->id);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s",
				     source_p->name,
				     source_p->username, source_p->host, chptr->chname);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +h %s",
				     me.name, chptr->chname, source_p->name);
	}
	else if(*parv[1] == '+')
	{
		add_user_to_channel(chptr, source_p, CHFL_VOICE);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :+%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +v %s",
				     me.name, chptr->chname, source_p->name);
	}
	else if(*parv[1] == '~')
	{
		if(!ConfigChannel.use_founder)
		{
			sendto_one_notice(source_p,
					  ":This server's configuration file does not support founder prefix");
			return 0;
		}

		add_user_to_channel(chptr, source_p, CHFL_FOUNDER);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :~%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +u %s",
				     me.name, chptr->chname, source_p->name);
	}
	else
	{
		add_user_to_channel(chptr, source_p, CHFL_PEON);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s JOIN %ld %s +",
			      source_p->id, (long) chptr->channelts, chptr->chname);
		send_channel_join(chptr, source_p);
	}

	/* send the topic... */
	if(chptr->topic != NULL)
	{
		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);
	}

	source_p->localClient->last_join_time = rb_current_time();
	channel_member_names(chptr, source_p, 1);

	sendto_realops_snomask(SNO_GENERAL, L_ALL,
			       "OJOIN called for %s by %s!%s@%s",
			       parv[1], source_p->name, source_p->username, source_p->host);
	ilog(L_MAIN, "OJOIN called for %s by %s", parv[1], get_oper_name(source_p));


	return 0;
}