Пример #1
0
static int
ms_tmode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Channel *chptr = NULL;
    struct membership *msptr;

    /* Now, try to find the channel in question */
    if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2])) {
        sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]);
        return 0;
    }

    chptr = find_channel(parv[2]);

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

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

    if(IsServer(source_p)) {
        set_channel_mode(client_p, source_p, chptr, NULL, parc - 3, parv + 3);
    } else {
        msptr = find_channel_membership(chptr, source_p);

        set_channel_mode(client_p, source_p, chptr, msptr, parc - 3, parv + 3);
    }

    return 0;
}
Пример #2
0
static int
ms_mlock(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;

	/* Now, try to find the channel in question */
	if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
	{
		sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]);
		return 0;
	}

	chptr = find_channel(parv[2]);

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

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

	if(IsServer(source_p))
		set_channel_mlock(client_p, source_p, chptr, parv[3], TRUE);

	return 0;
}
Пример #3
0
/*
 * m_mode - MODE command handler
 * parv[0] - sender
 * parv[1] - channel
 */
int m_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Channel* chptr;
  static char     modebuf[MODEBUFLEN];
  static char     parabuf[MODEBUFLEN];
  char *mename = me.name;

  if(sptr->user && sptr->user->vlink)
    mename = sptr->user->vlink->name;
     
  /* Now, try to find the channel in question */
  if (parc > 1)
    {
      if( IsChanPrefix(parv[1][0]) )
        {
          /* Don't do any of this stuff at all
           * unless it looks like a channel name 
           */

          if (!check_channel_name(parv[1]))
            { 
              sendto_one(sptr, form_str(ERR_BADCHANNAME),
                         mename, parv[0], (unsigned char *)parv[1]);
              return 0;
            }

          chptr = hash_find_channel(parv[1], NullChn);
          if (!chptr)
            return user_mode(cptr, sptr, parc, parv);
        }
      else
        {
          /* if here, it has to be a non-channel name */
          return user_mode(cptr, sptr, parc, parv);
        }
    }
  else
    {
      sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
                 mename, parv[0], "MODE");
      return 0;
    }

  if (parc < 3)
    {
      *modebuf = *parabuf = '\0';
      modebuf[1] = '\0';
      channel_modes(sptr, modebuf, parabuf, chptr, 0);
      sendto_one(sptr, form_str(RPL_CHANNELMODEIS), mename, parv[0],
                 chptr->chname, modebuf, parabuf);
      sendto_one(sptr, form_str(RPL_CREATIONTIME), mename, parv[0],
                 chptr->chname, chptr->channelts);
      return 0;
    }

  set_channel_mode(cptr, sptr, chptr, parc - 2, parv + 2);

  return 0;
}
Пример #4
0
/*
 * ms_tmode()
 *
 * inputs	- parv[0] = UID
 *		  parv[1] = TS
 *		  parv[2] = channel name
 *		  parv[3] = modestring
 */
static void
ms_tmode(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  struct Membership *member;

  if (!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
  {
    sendto_one(source_p, form_str(ERR_BADCHANNAME),
               ID_or_name(&me, client_p), ID_or_name(source_p, client_p), parv[2]);
    return;
  }

  if ((chptr = hash_find_channel(parv[2])) == NULL)
  {
    sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
               ID_or_name(&me, client_p), ID_or_name(source_p, client_p), parv[2]);
    return;
  }

  if (atol(parv[1]) > chptr->channelts)
    return;

  if (IsServer(source_p))
    set_channel_mode(client_p, source_p, chptr, NULL, parc - 3, parv + 3, chptr->chname);
  else
  {
    member = find_channel_link(source_p, chptr);

    /* XXX are we sure we just want to bail here? */
    if (has_member_flags(member, CHFL_DEOPPED))
      return;

    set_channel_mode(client_p, source_p, chptr, member, parc - 3, parv + 3, chptr->chname);
  }
}
Пример #5
0
/*
 * m_mode - MODE command handler
 * parv[0] - sender
 * parv[1] - channel
 */
static void
m_mode(struct Client *client_p, struct Client *source_p,
       int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  struct Membership *member;
  static char modebuf[MODEBUFLEN];
  static char parabuf[MODEBUFLEN];

  if (parv[1][0] == '\0')
  {
    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
               me.name, source_p->name, "MODE");
    return;
  }

  /* Now, try to find the channel in question */
  if (!IsChanPrefix(parv[1][0]))
  {
    /* if here, it has to be a non-channel name */
    set_user_mode(client_p, source_p, parc, parv);
    return;
  }

  if (!check_channel_name(parv[1]))
  { 
    sendto_one(source_p, form_str(ERR_BADCHANNAME),
               me.name, source_p->name, parv[1]);
    return;
  }

  chptr = hash_find_channel(parv[1]);

  if (chptr == NULL)
  {
      /* if chptr isn't found locally, it =could= exist
       * on the uplink. So ask.
       */
      
      /* LazyLinks */
      /* only send a mode upstream if a local client sent this request
       * -davidt
       */
      if (MyClient(source_p) && !ServerInfo.hub && uplink &&
	   IsCapable(uplink, CAP_LL))
	{
	  sendto_one(uplink, ":%s MODE %s %s",
                     ID_or_name(source_p, uplink),
		     parv[1], (parv[2] ? parv[2] : ""));
	  return;
	}
      else
	{
	  sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
		     me.name, parv[0], parv[1]);
	  return;
	}
    }

  /* Now known the channel exists */
  if (parc < 3)
  {
    channel_modes(chptr, source_p, modebuf, parabuf);
    sendto_one(source_p, form_str(RPL_CHANNELMODEIS),
               me.name, parv[0], parv[1], modebuf, parabuf);
    sendto_one(source_p, form_str(RPL_CREATIONTIME),
               me.name, parv[0], parv[1], chptr->channelts);
  }
  /* bounce all modes from people we deop on sjoin
   * servers have always gotten away with murder,
   * including telnet servers *g* - Dianora
   *
   * XXX Is it worth the bother to make an ms_mode() ? - Dianora
   */
  else if (IsServer(source_p))
  {
    set_channel_mode(client_p, source_p, chptr, NULL, parc - 2, parv + 2,
                     chptr->chname);
  }
  else
  {
    member = find_channel_link(source_p, chptr);

    if (!has_member_flags(member, CHFL_DEOPPED))
    {
      /* Finish the flood grace period... */
      if (MyClient(source_p) && !IsFloodDone(source_p))
      {
        if (!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0')))
          flood_endgrace(source_p);
      }

      set_channel_mode(client_p, source_p, chptr, member, parc - 2, parv + 2,
                       chptr->chname);
    }
  }
}
Пример #6
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]);
}
Пример #7
0
/*
 * m_lljoin
 *      parv[0] = sender prefix
 *      parv[1] = channel
 *      parv[2] = nick ("!nick" == cjoin)
 *      parv[3] = 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;
  int  flags;
  int  i;
  struct Client *target_p;
  struct Channel *chptr;

  if (uplink && !IsCapable(uplink,CAP_LL))
  {
      sendto_realops_flags(UMODE_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;

  if (parc >3)
    key = parv[3];

  flags = 0;

  target_p = find_person(client_p, nick);

  if (!target_p)
    return;

  if (!MyClient(target_p))
    return;

  if (!check_channel_name(chname, 0))
  {
    sendto_gnotice_flags(UMODE_DEBUG, L_ALL, me.name, &me, NULL,
                         "*** Too long or invalid channel name from %s: %s",
                         target_p->name, chname);
    return;
  }

  chptr = make_channel(chname);
  flags = CHFL_CHANOP;
   
  if(!chptr)
    return;

  if (dlink_list_length(&chptr->members) == 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, chptr->chname);
    return;
  }

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

  if ((dlink_list_length(&target_p->channel) >= ConfigChannel.max_chans_per_user) &&
      (!IsOper(target_p) || (dlink_list_length(&target_p->channel) >=
                             ConfigChannel.max_chans_per_user*3)))
  {
      sendto_one(target_p, form_str(ERR_TOOMANYCHANNELS),
		 me.name, nick, chptr->chname );
      return; 
  }
  
  if (flags == CHFL_CHANOP)
  {
      chptr->channelts = CurrentTime;

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

  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, YES);

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

  channel_member_names(target_p, chptr, 1);
}
Пример #8
0
static void
ms_cburst(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	char *name;
	char *nick;
	const char *key;
	struct Channel *chptr;

	if(parc < 2 || *parv[1] == '\0')
		return;

	name = parv[1];

	if(parc > 2)
		nick = parv[2];
	else
		nick = NULL;

	if(parc > 3)
		key = parv[3];
	else
		key = "";

#ifdef DEBUGLL
	sendto_realops_flags(UMODE_ALL, L_ALL, "CBURST called by %s for %s %s %s",
			     client_p->name, name, nick ? nick : "", key ? key : "");
#endif
	if((chptr = hash_find_channel(name)) == NULL)
	{
		if((!nick) || (nick && *nick != '!'))
		{
			if(!check_channel_name(name, 0))
			{
				sendto_realops_flags(UMODE_DEBUG, L_ALL,
						     "*** Too long or invalid channel name from %s: %s",
						     client_p->name, name);
				return;
			}

			chptr = make_channel(name);
			chptr->channelts = (time_t) (-1);	/* highest possible TS so its always
								 * over-ruled
								 */
		}
		else if(nick && *nick == '!')
		{
			sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), me.name, nick + 1, name);
			return;
		}
	}

	if(IsCapable(client_p, CAP_LL))
	{
		burst_channel(client_p, chptr);

		if(nick)
			sendto_one(client_p, ":%s LLJOIN %s %s %s", me.name, name, nick, key);
	}
	else
	{
		sendto_realops_flags(UMODE_ALL, L_ALL,
				     "*** CBURST request received from non LL capable server! [%s]",
				     client_p->name);
	}
}
Пример #9
0
/* Join a channel, ignoring forwards, +ib, etc. It notifes source_p of any errors joining
 * NB: this assumes a local user.
 */
void user_join_override(struct Client * client_p, struct Client * source_p, struct Client * target_p, const char * channels)
{
	static char jbuf[BUFSIZE];
	struct ConfItem *aconf;
	struct Channel *chptr = NULL;
	char *name;
	const char *modes;
	char *p = NULL;
	int flags;
	char *chanlist;

	jbuf[0] = '\0';

	if(channels == NULL)
		return;

	/* rebuild the list of channels theyre supposed to be joining. */
	chanlist = LOCAL_COPY(channels);
	for(name = rb_strtok_r(chanlist, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
	{
		/* check the length and name of channel is ok */
		if(!check_channel_name_loc(target_p, name) || (strlen(name) > LOC_CHANNELLEN))
		{
			sendto_one_numeric(source_p, ERR_BADCHANNAME,
					   form_str(ERR_BADCHANNAME), (unsigned char *) name);
			continue;
		}

		/* join 0 parts all channels */
		if(*name == '0' && (name[1] == ',' || name[1] == '\0') && name == chanlist)
		{
			(void) strcpy(jbuf, "0");
			continue;
		}

		/* check it begins with # or & */
		else if(!IsChannelName(name))
		{
			sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
					   form_str(ERR_NOSUCHCHANNEL), name);
			continue;
		}

		/* see if its resv'd */
		if(!IsExemptResv(target_p) && (aconf = hash_find_resv(name)))
		{
			sendto_one_numeric(source_p, ERR_BADCHANNAME,
					   form_str(ERR_BADCHANNAME), name);

			/* dont update tracking for jupe exempt users, these
			 * are likely to be spamtrap leaves
			 */
			if(IsExemptJupe(source_p))
				aconf->port--;

			continue;
		}

		if(splitmode && !IsOper(target_p) && (*name != '&') &&
		   ConfigChannel.no_join_on_split)
		{
			sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
				   me.name, source_p->name, name);
			continue;
		}

		if(*jbuf)
			(void) strcat(jbuf, ",");
		(void) rb_strlcat(jbuf, name, sizeof(jbuf));
	}

	for(name = rb_strtok_r(jbuf, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
	{
		/* JOIN 0 simply parts all channels the user is in */
		if(*name == '0' && !atoi(name))
		{
			if(target_p->user->channel.head == NULL)
				continue;

			do_join_0(&me, target_p);
			continue;
		}
		
		if((chptr = find_channel(name)) != NULL)
		{
			if(IsMember(target_p, chptr))
			{
				/* debugging is fun... */
				sendto_one_notice(source_p, ":*** Notice -- %s is already in %s",
					 target_p->name, chptr->chname);
				return;
			}

			add_user_to_channel(chptr, target_p, CHFL_PEON);
			if (chptr->mode.join_num && rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
			{
				chptr->join_count = 0;
				chptr->join_delta = rb_current_time();
			}
			chptr->join_count++;

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

			sendto_server(target_p, chptr, CAP_TS6, NOCAPS,
				      ":%s JOIN %ld %s +",
				      get_id(target_p, client_p), (long) chptr->channelts,
				      chptr->chname);

			del_invite(chptr, target_p);

			if(chptr->topic != NULL)
			{
				sendto_one(target_p, form_str(RPL_TOPIC), me.name,
				   target_p->name, chptr->chname, chptr->topic);
				sendto_one(target_p, form_str(RPL_TOPICWHOTIME),
					   me.name, source_p->name, chptr->chname,
					   chptr->topic_info, chptr->topic_time);
			}

			channel_member_names(chptr, target_p, 1);
		}
		else
		{
			hook_data_channel_activity hook_info;
			char statusmodes[5] = "";

			if(!check_channel_name(name))
			{
				sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name,
					   source_p->name, (unsigned char *) name);
				return;
			}

			/* channel name must begin with & or # */
			if(!IsChannelName(name))
			{
				sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name,
					   source_p->name, (unsigned char *) name);
				return;
			}

			/* name can't be longer than CHANNELLEN */
			if(strlen(name) > CHANNELLEN)
			{
				sendto_one_notice(source_p, ":Channel name is too long");
				return;
			}

			chptr = get_or_create_channel(target_p, name, NULL);

			flags = CHFL_CHANOP;
			
			add_user_to_channel(chptr, target_p, flags);
			if (chptr->mode.join_num &&
					rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
			{
				chptr->join_count = 0;
				chptr->join_delta = rb_current_time();
			}
			chptr->join_count++;
			
			sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
					     target_p->name, target_p->username,
					     target_p->host, chptr->chname);
		
				chptr->mode.mode |= MODE_TOPICLIMIT;
				chptr->mode.mode |= MODE_NOPRIVMSGS;

			modes = channel_modes(chptr, &me);
			sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s",
					     me.name, chptr->chname, modes);

			strcat(statusmodes, "@");

			sendto_server(target_p, chptr, CAP_TS6, NOCAPS,
				      ":%s SJOIN %ld %s %s :%s%s",
				      me.id, (long) chptr->channelts,
				      chptr->chname, modes, statusmodes,
				      get_id(target_p, client_p));

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

			/* Call channel join hooks */
			hook_info.client = source_p;
			hook_info.chptr = chptr;
			hook_info.key = chptr->mode.key;
			call_hook(h_channel_join, &hook_info);

			/* we do this to let the oper know that a channel was created, this will be
			 * seen from the server handling the command instead of the server that
			 * the oper is on.
			 */
			sendto_one_notice(source_p, ":*** Notice -- Creating channel %s", chptr->chname);
		}
	}		


	return;
}
Пример #10
0
/* Join a channel, ignoring forwards, +ib, etc. It notifes source_p of any errors joining
 * NB: this assumes a local user.
 */
void user_join_override(struct Client * client_p, struct Client * source_p, struct Client * target_p, const char * channels)
{
	static char jbuf[BUFSIZE];
	struct Channel *chptr = NULL;
	char *name;
	const char *modes;
	char *p = NULL;
	int flags;
	char *chanlist;

	jbuf[0] = '\0';

	if(channels == NULL)
		return;

	/* rebuild the list of channels theyre supposed to be joining.
	 * this code has a side effect of losing keys, but..
	 */
	chanlist = LOCAL_COPY(channels);
	for(name = rb_strtok_r(chanlist, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
	{
		/* check the length and name of channel is ok */
		if(!check_channel_name_loc(target_p, name) || (strlen(name) > LOC_CHANNELLEN))
		{
			sendto_one_numeric(source_p, ERR_BADCHANNAME,
					   form_str(ERR_BADCHANNAME), (unsigned char *) name);
			continue;
		}

		/* join 0 parts all channels */
		if(*name == '0' && (name[1] == ',' || name[1] == '\0') && name == chanlist)
		{
			(void) strcpy(jbuf, "0");
			continue;
		}

		/* check it begins with # or &, and local chans are disabled */
		else if(!IsChannelName(name) ||
		       (!ConfigChannel.use_local_channels && name[0] == '&'))
		{
			sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
					   form_str(ERR_NOSUCHCHANNEL), name);
			continue;
		}

		if(*jbuf)
			(void) strcat(jbuf, ",");
		(void) rb_strlcat(jbuf, name, sizeof(jbuf));
	}

	for(name = rb_strtok_r(jbuf, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
	{
		/* JOIN 0 simply parts all channels the user is in */
		if(*name == '0' && !atoi(name))
		{
			if(target_p->user->channel.head == NULL)
				continue;

			do_join_0(&me, target_p);
			continue;
		}
		
		if((chptr = find_channel(name)) != NULL)
		{
			if(IsMember(target_p, chptr))
			{
			/* debugging is fun... */
				sendto_one_notice(source_p, ":*** Notice -- %s is already in %s",
					 target_p->name, chptr->chname);
				return;
			}

			add_user_to_channel(chptr, target_p, CHFL_PEON);
			if (chptr->mode.join_num && rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
			{
				chptr->join_count = 0;
				chptr->join_delta = rb_current_time();
			}
			chptr->join_count++;

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

			sendto_server(target_p, chptr, CAP_TS6, NOCAPS,
				      ":%s JOIN %ld %s +",
				      get_id(target_p, client_p), (long) chptr->channelts,
				      chptr->chname);

			del_invite(chptr, target_p);

			if(chptr->topic != NULL)
			{
				sendto_one(target_p, form_str(RPL_TOPIC), me.name,
				   target_p->name, chptr->chname, chptr->topic);
				sendto_one(target_p, form_str(RPL_TOPICWHOTIME),
					   me.name, source_p->name, chptr->chname,
					   chptr->topic_info, chptr->topic_time);
			}

			channel_member_names(chptr, target_p, 1);
		}
		else
		{
			if(!check_channel_name(name))
			{
				sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name,
					   source_p->name, (unsigned char *) name);
				return;
			}

			/* channel name must begin with & or # */
			if(!IsChannelName(name))
			{
				sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name,
					   source_p->name, (unsigned char *) name);
				return;
			}

			/* name can't be longer than CHANNELLEN */
			if(strlen(name) > CHANNELLEN)
			{
				sendto_one_notice(source_p, ":Channel name is too long");
				return;
			}

			chptr = get_or_create_channel(target_p, name, NULL);

			flags = CHFL_CHANOP;
			
			if(ConfigChannel.founder_on_channel_create && ConfigChannel.use_founder)
				flags |= CHFL_FOUNDER;

			if(ConfigChannel.admin_on_channel_create && ConfigChannel.use_admin)
				flags |= CHFL_ADMIN;

			add_user_to_channel(chptr, target_p, flags);
			if (chptr->mode.join_num &&
					rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
			{
				chptr->join_count = 0;
				chptr->join_delta = rb_current_time();
			}
			chptr->join_count++;
			
			sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
					     target_p->name, target_p->username,
					     target_p->host, chptr->chname);
		
			/* autochanmodes stuff */
			if(ConfigChannel.autochanmodes)
			{
				char * ch;
				for(ch = ConfigChannel.autochanmodes; *ch != '\0'; ch++)
				{
					chptr->mode.mode |= chmode_table[(unsigned int)*ch].mode_type;
				}
			}
			else
			{
				chptr->mode.mode |= MODE_TOPICLIMIT;
				chptr->mode.mode |= MODE_NOPRIVMSGS;
			}

			modes = channel_modes(chptr, &me);
			sendto_channel_local(ONLY_HALFOPSANDUP, chptr, ":%s MODE %s %s",
					     me.name, chptr->chname, modes);

			sendto_server(target_p, chptr, CAP_TS6, NOCAPS,
				       ":%s SJOIN %ld %s %s :%s%s",
				       me.id, (long) chptr->channelts,
				       chptr->chname, modes,
				       flags & CHFL_FOUNDER ? "~@" : "@",
				       get_id(target_p, client_p));

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

			/* we do this to let the oper know that a channel was created, this will be
			 * seen from the server handling the command instead of the server that
			 * the oper is on.
			 */
			sendto_one_notice(source_p, ":*** Notice -- Creating channel %s", chptr->chname);
		}
	}		


	return;
}
Пример #11
0
static int
ms_bmask(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	static char modebuf[BUFSIZE];
	static char parabuf[BUFSIZE];
	struct Channel *chptr;
	rb_dlink_list *banlist;
	const char *s;
	char *t;
	char *mbuf;
	char *pbuf;
	long mode_type;
	int mlen;
	int plen = 0;
	int tlen;
	int arglen;
	int modecount = 0;
	int needcap = NOCAPS;
	int mems;
	struct Client *fakesource_p;

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

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

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

	switch (parv[3][0])
	{
	case 'b':
		banlist = &chptr->banlist;
		mode_type = CHFL_BAN;
		mems = ALL_MEMBERS;
		break;

	case 'e':
		banlist = &chptr->exceptlist;
		mode_type = CHFL_EXCEPTION;
		needcap = CAP_EX;
		mems = ONLY_HALFOPSANDUP;
		break;

	case 'I':
		banlist = &chptr->invexlist;
		mode_type = CHFL_INVEX;
		needcap = CAP_IE;
		mems = ONLY_HALFOPSANDUP;
		break;

	case 'Z':
		banlist = &chptr->quietlist;
		mode_type = CHFL_QUIET;
		mems = ALL_MEMBERS;
		break;
	/* XXX should use encap? */
	case 'y':
		banlist = &chptr->censorlist;
		mode_type = CHFL_CENSOR;
		mems = ALL_MEMBERS;
		break;
		/* maybe we should just blindly propagate this? */
	default:
		return 0;
	}

	parabuf[0] = '\0';
	s = LOCAL_COPY(parv[4]);

	/* Hide connecting server on netburst -- jilles */
	if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
		fakesource_p = &me;
	else
		fakesource_p = source_p;
	mlen = rb_sprintf(modebuf, ":%s MODE %s +", fakesource_p->name, chptr->chname);
	mbuf = modebuf + mlen;
	pbuf = parabuf;

	while(*s == ' ')
		s++;

	/* next char isnt a space, point t to the next one */
	if((t = strchr(s, ' ')) != NULL)
	{
		*t++ = '\0';

		/* double spaces will break the parser */
		while(*t == ' ')
			t++;
	}

	/* couldve skipped spaces and got nothing.. */
	while(!EmptyString(s))
	{
		/* ban with a leading ':' -- this will break the protocol */
		if(*s == ':')
			goto nextban;

		tlen = strlen(s);

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

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

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

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

	      nextban:
		s = t;

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

				while(*t == ' ')
					t++;
			}
		}
	}

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

	sendto_server(client_p, chptr, CAP_TS6 | needcap, NOCAPS, ":%s BMASK %ld %s %s :%s",
		      source_p->id, (long) chptr->channelts, chptr->chname, parv[3], parv[4]);
	return 0;
}
Пример #12
0
/*
 * m_forcejoin
 *      parv[1] = user to force
 *      parv[2] = channel to force them into
 */
static int
mo_forcejoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Client *target_p;
    struct Channel *chptr;
    int type;
    char mode;
    char sjmode;
    char *newch;

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

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

    /* if target_p is not existant, print message
     * to source_p and bail - scuzzy
     */
    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(!IsPerson(target_p))
        return 0;

    sendto_wallops_flags(UMODE_WALLOP, &me,
                         "FORCEJOIN called for %s %s by %s!%s@%s",
                         parv[1], parv[2], source_p->name, source_p->username, source_p->host);
    ilog(L_MAIN, "FORCEJOIN called for %s %s by %s!%s@%s",
         parv[1], parv[2], source_p->name, source_p->username, source_p->host);
    sendto_server(NULL, NULL, NOCAPS, NOCAPS,
                  ":%s WALLOPS :FORCEJOIN called for %s %s by %s!%s@%s",
                  me.name, parv[1], parv[2],
                  source_p->name, source_p->username, source_p->host);

    /* select our modes from parv[2] if they exist... (chanop) */
    if(*parv[2] == '@') {
        type = CHFL_CHANOP;
        mode = 'o';
        sjmode = '@';
    } else if(*parv[2] == '+') {
        type = CHFL_VOICE;
        mode = 'v';
        sjmode = '+';
    } else {
        type = CHFL_PEON;
        mode = sjmode = '\0';
    }

    if(mode != '\0')
        parv[2]++;

    if((chptr = find_channel(parv[2])) != NULL) {
        if(IsMember(target_p, chptr)) {
            /* debugging is fun... */
            sendto_one_notice(source_p, ":*** Notice -- %s is already in %s",
                              target_p->name, chptr->chname);
            return 0;
        }

        add_user_to_channel(chptr, target_p, type);

        sendto_server(target_p, chptr, NOCAPS, NOCAPS,
                      ":%s SJOIN %ld %s + :%c%s",
                      me.name, (long) chptr->channelts,
                      chptr->chname, type ? sjmode : ' ', target_p->name);

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

        if(type)
            sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +%c %s",
                                 me.name, chptr->chname, mode, target_p->name);

        if(chptr->topic != NULL) {
            sendto_one(target_p, form_str(RPL_TOPIC), me.name,
                       target_p->name, chptr->chname, chptr->topic);
            sendto_one(target_p, form_str(RPL_TOPICWHOTIME),
                       me.name, source_p->name, chptr->chname,
                       chptr->topic_info, chptr->topic_time);
        }

        channel_member_names(chptr, target_p, 1);
    } else {
        newch = LOCAL_COPY(parv[2]);
        if(!check_channel_name(newch)) {
            sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name,
                       source_p->name, (unsigned char *) newch);
            return 0;
        }

        /* channel name must begin with & or # */
        if(!IsChannelName(newch)) {
            sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name,
                       source_p->name, (unsigned char *) newch);
            return 0;
        }

        /* newch can't be longer than CHANNELLEN */
        if(strlen(newch) > CHANNELLEN) {
            sendto_one_notice(source_p, ":Channel name is too long");
            return 0;
        }

        chptr = get_or_create_channel(target_p, newch, NULL);
        add_user_to_channel(chptr, target_p, CHFL_CHANOP);

        /* send out a join, make target_p join chptr */
        sendto_server(target_p, chptr, NOCAPS, NOCAPS,
                      ":%s SJOIN %ld %s +nt :@%s", me.name,
                      (long) chptr->channelts, chptr->chname, target_p->name);

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

        chptr->mode.mode |= MODE_TOPICLIMIT;
        chptr->mode.mode |= MODE_NOPRIVMSGS;

        sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +nt", me.name, chptr->chname);

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

        /* we do this to let the oper know that a channel was created, this will be
         * seen from the server handling the command instead of the server that
         * the oper is on.
         */
        sendto_one_notice(source_p, ":*** Notice -- Creating channel %s", chptr->chname);
    }
    return 0;
}
Пример #13
0
/*
 * m_join
 *      parv[0] = sender prefix
 *      parv[1] = channel
 *      parv[2] = channel password (key)
 */
static void
m_join(struct Client *client_p,
       struct Client *source_p,
       int parc,
       char *parv[])
{
  struct Channel *chptr = NULL;
  char  *name, *key = NULL;
  int   i, flags = 0;
  char  *p = NULL, *p2 = NULL;
  int   successful_join_count = 0; /* Number of channels successfully joined */
  
  if (*parv[1] == '\0')
    {
      sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
                 me.name, parv[0], "JOIN");
      return;
    }

  if (parc > 2)
    {
      key = strtoken(&p2, parv[2], ",");
    }

  for (name = strtoken(&p, parv[1], ","); name;
         key = (key) ? strtoken(&p2, NULL, ",") : NULL,
         name = strtoken(&p, NULL, ","))
    {

      if(!check_channel_name(name))
      {
        sendto_one(source_p, form_str(ERR_BADCHANNAME),
	           me.name, source_p->name, (unsigned char*)name);
        continue;
      }

      /*
      ** JOIN 0 sends out a part for all channels a user
      ** has joined.
      **
      ** this should be either disabled or selectable in
      ** config file .. it's abused a lot more than it's
      ** used these days :/ --is
      */
      if (*name == '0' && !atoi(name))
      {
        if (source_p->user->channel.head == NULL)
          continue;
	  
        do_join_0(&me,source_p);
	continue;
      }
      
      /* check it begins with # or & */
      else if(!IsChannelName(name))
      {
        sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
	           me.name, source_p->name, name);
	continue;
      }

      if(ConfigServerHide.disable_local_channels &&
        (*name == '&'))
      {
        sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
	           me.name, source_p->name, name);
        continue;
      }

      /* check the length */
      if (strlen(name) > CHANNELLEN)
      {
        sendto_one(source_p, form_str(ERR_BADCHANNAME),
	           me.name, source_p->name, name);
	continue;
      }
      
      /* see if its resv'd */
      if(find_channel_resv(name) && 
         (!IsOper(source_p) || !ConfigChannel.no_oper_resvs))
	{
	  sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
		     me.name, source_p->name, name);
          sendto_realops_flags(UMODE_SPY, L_ALL,
                   "User %s (%s@%s) is attempting to join locally juped channel %s",
                   source_p->name, source_p->username, source_p->host, name);
	  continue;
	}

      /* look for the channel */
      if((chptr = hash_find_channel(name)) != NULL)
	{
	  if(IsMember(source_p, chptr))
            return;

	  if(splitmode && !IsOper(source_p) && (*name != '&') && 
             ConfigChannel.no_join_on_split)
	  {
	    sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
                       me.name, source_p->name, name);
	    continue;
	  }

	  if (chptr->users == 0)
	    flags = CHFL_CHANOP;
	  else
	    flags = 0;
	}
      else
	{
	  if(splitmode && !IsOper(source_p) && (*name != '&') && 
            (ConfigChannel.no_create_on_split || ConfigChannel.no_join_on_split))
	  {
	    sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
	               me.name, source_p->name, name);
	    continue;
	  }
	  
	  flags = CHFL_CHANOP;
	}

      if ((source_p->user->joined >= ConfigChannel.max_chans_per_user) &&
         (!IsOper(source_p) || (source_p->user->joined >=
	                        ConfigChannel.max_chans_per_user*3)))
	{
	  sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
		     me.name, parv[0], name);
	  if(successful_join_count)
	    source_p->localClient->last_join_time = CurrentTime;
	  return;
	}

      if(flags == 0)        /* if channel doesn't exist, don't penalize */
	successful_join_count++;

      if(chptr == NULL)     /* If I already have a chptr, no point doing this */
	{
	  chptr = get_or_create_channel(source_p, name, NULL);
	}
      
      if(chptr == NULL)
	{
	  sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
		     me.name, parv[0], name);
	  if(successful_join_count > 0)
	    successful_join_count--;
	  continue;
	}

    if (!IsOper(source_p))
     check_spambot_warning(source_p, name);
      
      /* can_join checks for +i key, bans etc */
      if ( (i = can_join(source_p, chptr, key)) )
	{
	  sendto_one(source_p,
		     form_str(i), me.name, parv[0], name);
	  if(successful_join_count > 0)
	    successful_join_count--;
	  continue;
	}

      /* add the user to the channel */
      add_user_to_channel(chptr, source_p, flags);

      /* we send the user their join here, because we could have to
       * send a mode out next.
       */
      sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
			   source_p->name,
			   source_p->username,
			   source_p->host,
			   chptr->chname);

      /* if theyre joining opped (ie, new chan or joining one thats
       * persisting) then set timestamp to current, set +nt and
       * broadcast the sjoin with its old modes, or +nt.
       */
      if (flags & CHFL_CHANOP)
	{
          char mbuf[MODEBUFLEN];
          char pbuf[MODEBUFLEN];

	  chptr->channelts = CurrentTime;
          chptr->mode.mode |= MODE_TOPICLIMIT;
          chptr->mode.mode |= MODE_NOPRIVMSGS;

	  sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s +nt",
			       me.name, chptr->chname);

          if(*chptr->chname == '#')
          {
            channel_modes(chptr, source_p, mbuf, pbuf);

            strlcat(mbuf, " ", sizeof(mbuf));

            if(pbuf[0] != '\0')
              strlcat(mbuf, pbuf, sizeof(mbuf));

            /* note: mbuf here will have a trailing space.  we add one above,
             * and channel_modes() will leave a trailing space on pbuf if
             * its used --fl
             */
	    sendto_server(client_p, chptr, NOCAPS, NOCAPS,
                          ":%s SJOIN %lu %s %s:@%s",
                          me.name, (unsigned long) chptr->channelts, 
                          chptr->chname, mbuf, parv[0]);
          }

          /* drop our +beI modes */
          free_channel_list(&chptr->banlist);
          free_channel_list(&chptr->exceptlist);
          free_channel_list(&chptr->invexlist);
	}
      else 
	{
	  sendto_server(client_p, chptr, NOCAPS, NOCAPS,
                        ":%s SJOIN %lu %s + :%s",
                        me.name, (unsigned long) chptr->channelts,
                        chptr->chname, parv[0]);
        }

      del_invite(chptr, source_p);
      
      if (chptr->topic != NULL)
	{
	  sendto_one(source_p, form_str(RPL_TOPIC), me.name,
		     parv[0], chptr->chname, chptr->topic);

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

      channel_member_names(source_p, chptr, chptr->chname, 1);

      if(successful_join_count)
	source_p->localClient->last_join_time = CurrentTime;
    }
}
Пример #14
0
/*
 * m_omode - MODE command handler
 * parv[0] - sender
 * parv[1] - channel
 */
static void
m_omode(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	struct Channel *chptr = NULL;
	struct membership *msptr;
	static char modebuf[MODEBUFLEN];
	static char parabuf[MODEBUFLEN];
	int n = 2;

	if(EmptyString(parv[1]))
	{
		sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
			   me.name, parv[0], "MODE");
		return;
	}

	/* Now, try to find the channel in question */
	if(!IsChanPrefix(parv[1][0]))
	{
		/* if here, it has to be a non-channel name */
		user_mode(client_p, source_p, parc, parv);
		return;
	}

	if(!check_channel_name(parv[1]))
	{
		sendto_one(source_p, form_str(ERR_BADCHANNAME),
			   me.name, parv[0], (unsigned char *) parv[1]);
		return;
	}

	chptr = hash_find_channel(parv[1]);

	if(chptr == NULL)
	{
		sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
		return;
	}

	sendto_wallops_flags(UMODE_WALLOP, &me, 
			     "OMODE called for [%s] by %s!%s@%s",
			     parv[1], source_p->name, source_p->username, source_p->host);
	ilog(L_NOTICE, "OMODE called for [%s] by %s!%s@%s",
	     parv[1], source_p->name, source_p->username, source_p->host);

	if(*chptr->chname != '&')
		sendto_server(NULL, NULL, NOCAPS, NOCAPS, 
			      ":%s WALLOPS :OMODE called for [%s] by %s!%s@%s",
			      me.name, parv[1], source_p->name, source_p->username,
			      source_p->host);

	/* Now know the channel exists */
	if(parc < n + 1)
	{
		channel_modes(chptr, source_p, modebuf, parabuf);
		sendto_one(source_p, form_str(RPL_CHANNELMODEIS),
			   me.name, parv[0], parv[1], modebuf, parabuf);

		sendto_one(source_p, form_str(RPL_CREATIONTIME),
			   me.name, parv[0], parv[1], chptr->channelts);
	}
	else if(IsServer(source_p))
	{
		set_channel_mode(client_p, source_p, chptr, NULL,
				 parc - n, parv + n, chptr->chname);
	}
	else
	{
		msptr = find_channel_membership(chptr, source_p);

		set_channel_mode(client_p, source_p->servptr, chptr, msptr, 
				 parc - n, parv + n, chptr->chname);
	}
}
Пример #15
0
/*
 * m_mode - MODE command handler
 * parv[1] - channel
 */
static int
m_mode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;
	struct membership *msptr;
	int n = 2;
	const char *dest;
	int operspy = 0;

	dest = parv[1];

	if(IsOperSpy(source_p) && *dest == '!')
	{
		dest++;
		operspy = 1;

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

	/* Now, try to find the channel in question */
	if(!IsChanPrefix(*dest))
	{
		/* if here, it has to be a non-channel name */
		user_mode(client_p, source_p, parc, parv);
		return 0;
	}

	if(!check_channel_name(dest))
	{
		sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[1]);
		return 0;
	}

	chptr = find_channel(dest);

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

	/* Now know the channel exists */
	if(parc < n + 1)
	{
		if(operspy)
			report_operspy(source_p, "MODE", chptr->chname);

		sendto_one(source_p, form_str(RPL_CHANNELMODEIS),
			   me.name, source_p->name, parv[1],
			   operspy ? channel_modes(chptr, &me) : channel_modes(chptr, source_p));

		sendto_one(source_p, form_str(RPL_CREATIONTIME),
			   me.name, source_p->name, parv[1], chptr->channelts);
	}
	else
	{
		msptr = find_channel_membership(chptr, source_p);

		/* Finish the flood grace period... */
		if(MyClient(source_p) && !IsFloodDone(source_p))
		{
			if(!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0')))
				flood_endgrace(source_p);
		}

		set_channel_mode(client_p, source_p, chptr, msptr, parc - n, parv + n);
	}

	return 0;
}
Пример #16
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;
}
Пример #17
0
/*
** m_cjoin
**      parv[0] = sender prefix
**      parv[1] = channel
**      parv[2] = channel password (key)
*/
static void m_cjoin(struct Client *client_p,
                   struct Client *source_p,
                   int parc,
                   char *parv[])
{
  static char   jbuf[BUFSIZE];
  struct Channel *chptr = NULL;
  struct Channel *vchan_chptr = NULL;
  struct Channel *root_vchan = NULL;
  char  *name;
  char  *p = NULL;

  if (!(source_p->user))
    {
      /* something is *f****d* - bail */
      return;
    }

  if(ConfigChannel.use_vchans == 0)
  {
    sendto_one(source_p, form_str(source_p,ERR_VCHANDISABLED),
               me.name, parv[0]);
    return;
  }
  
  if (ConfigChannel.vchans_oper_only && !IsOper(source_p))
  {
    sendto_one(source_p, form_str(source_p,ERR_NOPRIVILEGES),
               me.name, parv[0]);
    return;
  }

  if (*parv[1] == '\0')
    {
      sendto_one(source_p, form_str(source_p,ERR_NEEDMOREPARAMS),
                 me.name, parv[0], "CJOIN");
      return;
    }


  /* Ok, only allowed to CJOIN already existing channels
   * so first part simply verifies the "root" channel exists first
   */

  *jbuf = '\0';

  name = parv[1];
  while (*name == ',')
    name++;
  if ((p = strchr(name,',')) != NULL)
    *p = '\0';
  if (!*name)
    return;

  if (!check_channel_name(name))
    {
      sendto_one(source_p, form_str(source_p,ERR_BADCHANNAME),
		 me.name, parv[0], (unsigned char*) name);
      return;
    }

  if (*name == '&')
    {
      sendto_one(source_p, form_str(source_p,ERR_BADCHANNAME),
		 me.name, parv[0], (unsigned char*) name);
      return;
    }

  if (!IsChannelName(name))
    {
      sendto_one(source_p, form_str(source_p,ERR_NOSUCHCHANNEL),
		 me.name, parv[0], name);
      return;
    }

  strlcpy(jbuf, name, sizeof(jbuf));

  if ((chptr = hash_find_channel(name)) == NULL)
    {
      /* if chptr isn't found locally, it =could= exist
       * on the uplink. So ask.
       */
      if ( !ServerInfo.hub && uplink &&
           IsCapable(uplink, CAP_LL))
        {
          /* cache the channel if it exists on uplink
           * If the channel as seen by the uplink, has vchans,
           * the uplink will have to SJOIN all of those.
           */
          sendto_one(uplink, ":%s CBURST %s !%s",
                     me.name, parv[1], source_p->name);

          return;
        }
      else
        {
          sendto_one(source_p, form_str(source_p,ERR_NOSUCHCHANNEL),
                     me.name, source_p->name, name);
        }
      return;
    }

  if (! (vchan_chptr = cjoin_channel(chptr, source_p, name)) )
    return;

  root_vchan = chptr;
  chptr = vchan_chptr;
  
  /*
  **  Complete user entry to the new channel
  */
  add_user_to_channel(chptr, source_p, CHFL_CHANOP);

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

  sendto_server(client_p, NULL, chptr, NOCAPS, NOCAPS, NOFLAGS,
                ":%s SJOIN %lu %s + :@%s",
                me.name,
                (unsigned long) chptr->channelts,
                chptr->chname,
                source_p->name);

  vchan_chptr->mode.mode |= MODE_TOPICLIMIT;
  vchan_chptr->mode.mode |= MODE_NOPRIVMSGS;

  sendto_channel_local(ALL_MEMBERS,chptr,
			":%s MODE %s +nt",
			me.name,
			root_vchan->chname);

  sendto_server(source_p, NULL, vchan_chptr, NOCAPS, NOCAPS, NOFLAGS,
                ":%s MODE %s +nt",
                me.name,
                vchan_chptr->chname);

  del_invite(vchan_chptr, source_p);
  channel_member_names(source_p, vchan_chptr, root_vchan->chname, 1);
}