Exemplo n.º 1
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);
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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
}
Exemplo n.º 6
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);
	}
    }
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
/*
 * m_topic
 *      parv[1] = channel name
 *	parv[2] = new topic, if setting topic
 */
static int
m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;
	struct membership *msptr;
	char *p = NULL;
	const char *name;
	int operspy = 0;

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

	name = parv[1];

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

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

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

	chptr = find_channel(name);

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

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

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

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

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

			if (ConfigChannel.strip_topic_colors)
				strip_colour(topic);

			set_channel_topic(chptr, topic, topic_info, rb_current_time());

			sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
					":%s TOPIC %s :%s",
					use_id(source_p), chptr->chname,
					chptr->topic == NULL ? "" : chptr->topic);
			sendto_channel_local(ALL_MEMBERS,
					chptr, ":%s!%s@%s TOPIC %s :%s",
					source_p->name, source_p->username,
					source_p->host, chptr->chname,
					chptr->topic == NULL ? "" : chptr->topic);
		}
		else
			sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
					get_id(&me, source_p),
					get_id(source_p, source_p), name);
	}
	else if(MyClient(source_p))
	{
		if(operspy)
			report_operspy(source_p, "TOPIC", chptr->chname);
		if(!IsMember(source_p, chptr) && SecretChannel(chptr) &&
				!operspy)
		{
			sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
					form_str(ERR_NOTONCHANNEL), name);
			return 0;
		}
		if(chptr->topic == NULL)
			sendto_one(source_p, form_str(RPL_NOTOPIC),
					me.name, source_p->name, name);
		else
		{
			sendto_one(source_p, form_str(RPL_TOPIC),
					me.name, source_p->name, chptr->chname, chptr->topic);

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

	return 0;
}
Exemplo n.º 9
0
/* m_topic()
 *  parv[0] = sender prefix
 *  parv[1] = channel name
 *  parv[2] = new topic, if setting topic
 */
static void
m_topic(struct Client *client_p, struct Client *source_p,
        int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  char *p;
  struct Membership *ms;
  const char *from, *to;

  if (!MyClient(source_p) && 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 ((p = strchr(parv[1], ',')) != NULL)
    *p = '\0';

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

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

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

    /* setting topic */
    if (parc > 2)
    {
      if ((ms = find_channel_link(source_p, chptr)) == NULL && !IsService(source_p))
      {
        sendto_one(source_p, form_str(ERR_NOTONCHANNEL), me.name,
                   source_p->name, parv[1]);
        return;
      }

      if ((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
          has_member_flags(ms, CHFL_CHANOP|CHFL_HALFOP) || IsGod(source_p) ||
          IsService(source_p))
      {
        char topic_info[USERHOST_REPLYLEN]; 
        if(!has_member_flags(ms, CHFL_CHANOP|CHFL_HALFOP) && 
                IsGod(source_p) && MyClient(source_p) &&
                (chptr->mode.mode & MODE_TOPICLIMIT) != 0)
        {              
          char tmp[IRCD_BUFSIZE];           
          ircsprintf(tmp, "%s is using God mode: TOPIC %s %s", source_p->name, 
                  chptr->chname, parv[2]);              
          sendto_gnotice_flags(UMODE_SERVNOTICE, L_ALL, me.name, &me, NULL, 
                  tmp);
          oftc_log(tmp);
        }
        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",
                      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, NO,
                             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),
                   from, to, chptr->chname);
    }
    else /* only asking for topic */
    {
      if (!SecretChannel(chptr) || IsMember(source_p, chptr))
      {
        if (chptr->topic == NULL)
          sendto_one(source_p, form_str(RPL_NOTOPIC),
                     from, to, chptr->chname);
        else
        {
          sendto_one(source_p, form_str(RPL_TOPIC),
                     from, to,
                     chptr->chname, chptr->topic);

          sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
                     from, to, chptr->chname,
                     chptr->topic_info,
                     chptr->topic_time);
        }
      }
      else
      {
        sendto_one(source_p, form_str(ERR_NOTONCHANNEL),
                   from, to, chptr->chname);
        return;
      }
    }
  }
  else
  {
    sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
               from, to, parv[1]);
  }
}
Exemplo n.º 10
0
/*
 * m_topic
 *      parv[1] = channel name
 *	parv[2] = new topic, if setting topic
 */
static int
m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;
	struct membership *msptr;
	char *p = NULL;
	const char *name;
	int operspy = 0;

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

	name = parv[1];

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

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

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

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

	chptr = find_channel(name);

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

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

		msptr = find_channel_membership(chptr, source_p);

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

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

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

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

		rb_sprintf(topic_info, "%s!%s@%s",
				source_p->name, source_p->username, source_p->host);
		set_channel_topic(chptr, topic, topic_info, rb_current_time());

		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
				":%s TOPIC %s :%s",
				use_id(source_p), chptr->chname,
				chptr->topic == NULL ? "" : chptr->topic);
		sendto_channel_local(ALL_MEMBERS,
				chptr, ":%s!%s@%s TOPIC %s :%s",
				source_p->name, source_p->username,
				source_p->host, chptr->chname,
				chptr->topic == NULL ? "" : chptr->topic);
	}
	else if(MyClient(source_p))
	{
		if(operspy)
			report_operspy(source_p, "TOPIC", chptr->chname);
		if(!IsMember(source_p, chptr) && SecretChannel(chptr) &&
				!operspy)
		{
			sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
					form_str(ERR_NOTONCHANNEL), name);
			return 0;
		}
		if(chptr->topic == NULL)
			sendto_one(source_p, form_str(RPL_NOTOPIC),
					me.name, source_p->name, name);
		else
		{
			sendto_one(source_p, form_str(RPL_TOPIC),
					me.name, source_p->name, chptr->chname, chptr->topic);

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

	return 0;
}
Exemplo n.º 11
0
/* ms_etb()
 *
 * parv[1] - channel ts
 * parv[2] - channel
 * parv[3] - topic ts
 * parv[4] - topicwho
 * parv[5] - topic
 */
static int
ms_etb(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Channel *chptr;
    const char *newtopic;
    const char *newtopicwho;
    time_t channelts, newtopicts;
    struct Client *fakesource_p, *source_server_p;
    int textchange, can_use_tb, member;

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

    if(chptr == NULL)
        return 0;

    newtopicts = atol(parv[3]);

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

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

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

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

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

    return 0;
}
Exemplo n.º 12
0
/* ms_tburst()
 *
 *      parv[0] = sender prefix
 *      parv[1] = channel timestamp
 *      parv[2] = channel
 *      parv[3] = topic timestamp
 *      parv[4] = topic setter
 *      parv[5] = topic
 */
static void
ms_tburst(struct Client *client_p, struct Client *source_p,
          int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  int accept_remote = 0;
  time_t remote_channel_ts = atol(parv[1]);
  time_t remote_topic_ts = atol(parv[3]);
  const char *topic = "";
  const char *setby = "";

  /*
   * Do NOT test parv[5] for an empty string and return if true!
   * parv[5] CAN be an empty string, i.e. if the other side wants
   * to unset our topic.  Don't forget: an empty topic is also a
   * valid topic.
   */


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

  if (parc == 6)
  {
    topic = parv[5];
    setby = parv[4];
  }

  /*
   * The logic for accepting and rejecting channel topics was
   * always a bit hairy, so now we got exactly 2 cases where
   * we would accept a bursted topic
   *
   * Case 1:
   *        The TS of the remote channel is older than ours
   * Case 2:
   *        The TS of the remote channel is equal to ours AND
   *        the TS of the remote topic is newer than ours
   */
  if (remote_channel_ts < chptr->channelts)
    accept_remote = 1;
  else if (remote_channel_ts == chptr->channelts)
    if (remote_topic_ts > chptr->topic_time)
      accept_remote = 1;

  if (accept_remote)
  {
    int topic_differs = strcmp(chptr->topic ? chptr->topic : "", topic);

    set_channel_topic(chptr, topic, setby, remote_topic_ts);

    if (topic_differs)
      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);
  }

  /*
   * Always propagate what we have received, not only if we accept the topic.
   * This will keep other servers in sync.
   */
  sendto_server(source_p, chptr, CAP_TBURST, NOCAPS,
                ":%s TBURST %s %s %s %s :%s",
                source_p->name, parv[1], parv[2], parv[3], setby, topic);
  if (parc > 5 && *topic != '\0') /* unsetting a topic is not supported by TB */
    sendto_server(source_p, chptr, CAP_TB, CAP_TBURST,
                  ":%s TB %s %s %s :%s",
                  source_p->name, parv[1], parv[2], setby, topic);
}
Exemplo n.º 13
0
/*
 * m_topic
 *      parv[0] = sender prefix
 *      parv[1] = channel name
 *	parv[2] = new topic, if setting topic
 */
static void m_topic(struct Client *client_p,
                   struct Client *source_p,
                   int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  struct Channel *root_chan;
  char  *p = NULL;
#ifdef VCHANS
  struct Channel *vchan;
#endif
    
  if ((p = strchr(parv[1],',')))
    *p = '\0';

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

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

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

      root_chan = chptr;

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

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

                if(!(chptr->mode.mode & MODE_HIDEOPS) ||
                  is_any_op(chptr,source_p))
                {
                  sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
                             me.name, parv[0], root_chan->chname,
                             chptr->topic_info,
                             chptr->topic_time);
                }
	        /* client on LL needing the topic - if we have serverhide, say
	         * its the actual LL server that set the topic, not us the
	         * uplink -- fl_
	         */
	        else if(ConfigServerHide.hide_servers && !MyClient(source_p)
	                && IsCapable(client_p, CAP_LL) && ServerInfo.hub)
  	        {
	          sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
	  	             me.name, parv[0], root_chan->chname,
	  		     client_p->name, chptr->topic_time);
                }
  	        /* just normal topic hiding.. */
	        else
	 	{
                  sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
                             me.name, parv[0], root_chan->chname,
                             me.name,
                             chptr->topic_time);
                }
            }
        }
    }
  else
    {
      sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
                 me.name, parv[0], parv[1]);
    }
}
Exemplo n.º 14
0
/* m_topic()
 *  parv[0] = sender prefix
 *  parv[1] = channel name
 *  parv[2] = new topic, if setting topic
 */
static void
m_topic(struct Client *client_p, struct Client *source_p,
        int parc, char *parv[])
{
  struct Channel *chptr = NULL;

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

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

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

  /* setting topic */
  if (parc > 2)
  {
    struct Membership *ms;

    if ((ms = find_channel_link(source_p, chptr)) == NULL)
    {
      sendto_one(source_p, form_str(ERR_NOTONCHANNEL), me.name,
                 source_p->name, parv[1]);
      return;
    }

    if (!(chptr->mode.mode & MODE_TOPICLIMIT) ||
        has_member_flags(ms, CHFL_CHANOP|CHFL_HALFOP))
    {
      char topic_info[USERHOST_REPLYLEN]; 

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

      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);
      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);
    }
    else
      sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                 me.name, source_p->name, chptr->chname);
  }
  else /* only asking for topic */
  {
    if (!SecretChannel(chptr) || IsMember(source_p, chptr))
    {
      if (chptr->topic[0] == '\0')
        sendto_one(source_p, form_str(RPL_NOTOPIC),
                   me.name, source_p->name, chptr->chname);
      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);
      }
    }
    else
      sendto_one(source_p, form_str(ERR_NOTONCHANNEL),
                 me.name, source_p->name, chptr->chname);
  }
}
Exemplo n.º 15
0
/* ms_tburst()
 *
 *      parv[0] = sender prefix
 *      parv[1] = channel timestamp
 *      parv[2] = channel
 *      parv[3] = topic timestamp
 *      parv[4] = topic setter
 *      parv[5] = topic
 */
static void
ms_tburst(struct Client *client_p, struct Client *source_p,
          int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  int accept_remote = 0;
  time_t remote_channel_ts = atol(parv[1]);
  time_t remote_topic_ts = atol(parv[3]);
  const char *topic = parv[5];
  const char *setby = parv[4];

  /*
   * Do NOT test parv[5] for an empty string and return if true!
   * parv[5] CAN be an empty string, i.e. if the other side wants
   * to unset our topic.  Don't forget: an empty topic is also a
   * valid topic.
   */


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

  /*
   * The logic for accepting and rejecting channel topics was
   * always a bit hairy, so now we got exactly 2 cases where
   * we would accept a bursted topic
   *
   * Case 1:
   *        The TS of the remote channel is older than ours
   * Case 2:
   *        The TS of the remote channel is equal to ours AND
   *        the TS of the remote topic is newer than ours
   */
  if (HasFlag(source_p, FLAGS_SERVICE))
    accept_remote = 1;
  else if (remote_channel_ts < chptr->channelts)
    accept_remote = 1;
  else if (remote_channel_ts == chptr->channelts)
    if (remote_topic_ts > chptr->topic_time)
      accept_remote = 1;

  if (accept_remote)
  {
    int topic_differs = strncmp(chptr->topic, topic, sizeof(chptr->topic) - 1);
    int hidden_server = (ConfigServerHide.hide_servers || IsHidden(source_p));

    set_channel_topic(chptr, topic, setby, remote_topic_ts, !!MyClient(source_p));

    sendto_server(source_p, CAP_TBURST|CAP_TS6, NOCAPS,
                  ":%s TBURST %s %s %s %s :%s",
                  ID(source_p), parv[1], parv[2], parv[3], setby, topic);
    sendto_server(source_p, CAP_TBURST, CAP_TS6,
                  ":%s TBURST %s %s %s %s :%s",
                  source_p->name, parv[1], parv[2], parv[3], setby, topic);

    if (topic_differs)
      sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s TOPIC %s :%s",
                           hidden_server ? me.name : source_p->name,
                           chptr->chname, chptr->topic);
  }
}