Beispiel #1
0
static void 
ms_join(struct Client *client_p,
	struct Client *source_p,
	int parc,
	char *parv[])
{
  char *name;
  int new_ts;

  if (!(source_p->user))
    return;
  
  name = parv[1];

  if ((name[0] == '0') && (name[1] == '\0'))
    {
      do_join_0(client_p, source_p);
    }
  else
    {
      if(parc > 2)
	{
	  new_ts = atoi(parv[2]);
	}
      else
	{
	  ts_warn("User on %s remotely JOINing new channel with no TS", 
		  source_p->user->server);
	}
    }
}
Beispiel #2
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;
}
Beispiel #3
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;
    }
}
Beispiel #4
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;
}