Exemple #1
0
/*! \brief TOPIC command handler
 *
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *      - parv[0] = command
 *      - parv[1] = channel name
 *      - parv[2] = topic text
 */
static int
ms_topic(struct Client *source_p, int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  char topic_info[USERHOST_REPLYLEN];

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

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

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

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

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

  else
    sendto_channel_local(0, chptr, ":%s!%s@%s TOPIC %s :%s",
                         source_p->name,
                         source_p->username,
                         source_p->host,
                         chptr->name, chptr->topic);
  return 0;
}
Exemple #2
0
/*! \brief TOPIC command handler
 *
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *      - parv[0] = command
 *      - parv[1] = channel name
 *      - parv[2] = topic text, if setting topic
 */
static int
m_topic(struct Client *source_p, int parc, char *parv[])
{
  struct Channel *chptr = NULL;

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

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

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

  /* setting topic */
  if (parc > 2)
  {
    const struct Membership *member = NULL;

    if ((member = find_channel_link(source_p, chptr)) == NULL)
    {
      sendto_one_numeric(source_p, &me, ERR_NOTONCHANNEL, chptr->name);
      return 0;
    }

    if (!(chptr->mode.mode & MODE_TOPICLIMIT) ||
        has_member_flags(member, 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);
      channel_set_topic(chptr, parv[2], topic_info, CurrentTime, 1);

      sendto_server(source_p, 0, 0, ":%s TOPIC %s :%s",
                    source_p->id, chptr->name,
                    chptr->topic);
      sendto_channel_local(0, chptr, ":%s!%s@%s TOPIC %s :%s",
                           source_p->name,
                           source_p->username,
                           source_p->host,
                           chptr->name, chptr->topic);
    }
    else
      sendto_one_numeric(source_p, &me, ERR_CHANOPRIVSNEEDED, chptr->name);
  }
  else /* only asking for topic */
  {
    if (!SecretChannel(chptr) || IsMember(source_p, chptr))
    {
      if (chptr->topic[0] == '\0')
        sendto_one_numeric(source_p, &me, RPL_NOTOPIC, chptr->name);
      else
      {
        sendto_one_numeric(source_p, &me, RPL_TOPIC,
                           chptr->name, chptr->topic);
        sendto_one_numeric(source_p, &me, RPL_TOPICWHOTIME, chptr->name,
                           chptr->topic_info,
                           chptr->topic_time);
      }
    }
    else
      sendto_one_numeric(source_p, &me, ERR_NOTONCHANNEL, chptr->name);
  }

  return 0;
}
Exemple #3
0
/*! \brief TBURST command handler
 *
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *      - parv[0] = command
 *      - parv[1] = channel timestamp
 *      - parv[2] = channel name
 *      - parv[3] = topic timestamp
 *      - parv[4] = topic setter
 *      - parv[5] = topic
 */
static int
ms_tburst(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 0;

    /*
     * The logic for accepting and rejecting channel topics was
     * always a bit hairy, so now we got exactly 3 cases where
     * we would accept a topic
     *
     * Case 1:
     *        A services client/server wants to set a topic
     * Case 2:
     *        The TS of the remote channel is older than ours
     * Case 3:
     *        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->creationtime)
        accept_remote = 1;
    else if (remote_channel_ts == chptr->creationtime)
        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));

        channel_set_topic(chptr, topic, setby, remote_topic_ts, 0);

        sendto_server(source_p, CAPAB_TBURST, 0, ":%s TBURST %s %s %s %s :%s",
                      source_p->id, parv[1], parv[2], parv[3], setby, topic);

        if (topic_differs)
        {
            if (!IsClient(source_p))
                sendto_channel_local(0, chptr, ":%s TOPIC %s :%s",
                                     hidden_server ? me.name : source_p->name,
                                     chptr->name, chptr->topic);
            else
                sendto_channel_local(0, chptr, ":%s!%s@%s TOPIC %s :%s",
                                     source_p->name, source_p->username, source_p->host,
                                     chptr->name, chptr->topic);
        }
    }

    return 0;
}