Beispiel #1
0
/** Send a (prefixed) command to all local users on a channel with or without
 *  a client capability specified.
 * @param[in] from Client originating the command.
 * @param[in] cmd Long name of command.
 * @param[in] tok Short name of command (ignored).
 * @param[in] to Destination channel.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] skip Bitmask of SKIP_DEAF, SKIP_NONOPS, SKIP_NONVOICES indicating which clients to skip.
 * @param[in] withcap CAP_* that the user must have active to receive the message.
 * @param[in] skipcap CAP_* that the user must not have active to receive the message.
 * @param[in] pattern Format string for command arguments.
 */
void sendcmdto_channel_capab_butserv_butone(struct Client *from, const char *cmd,
                                      const char *tok, struct Channel *to,
                                      struct Client *one, unsigned int skip,
                                      int withcap, int skipcap,
                                      const char *pattern, ...)
{
  struct VarData vd;
  struct MsgBuf *mb;
  struct Membership *member;

  vd.vd_format = pattern; /* set up the struct VarData for %v */
  va_start(vd.vd_args, pattern);

  /* build the buffer */
  mb = msgq_make(0, "%:#C %s %v", from, cmd, &vd);
  va_end(vd.vd_args);

  /* send the buffer to each local channel member */
  for (member = to->members; member; member = member->next_member) {
    if (!MyConnect(member->user)
        || member->user == one
        || IsZombie(member)
        || (skip & SKIP_DEAF && IsDeaf(member->user))
        || (skip & SKIP_NONOPS && !IsChanOp(member))
        || (skip & SKIP_NONHOPS && !IsChanOp(member) && !IsHalfOp(member))
        || (skip & SKIP_NONVOICES && !IsChanOp(member) && !IsHalfOp(member)&& !HasVoice(member))
        || ((withcap != CAP_NONE) && !CapActive(member->user, withcap))
        || ((skipcap != CAP_NONE) && CapActive(member->user, skipcap)))
        continue;
      send_buffer(member->user, mb, 0);
  }

  msgq_clean(mb);
}
Beispiel #2
0
/** Send a (prefixed) command to all servers with users on \a to.
 * Skip \a from and \a one plus those indicated in \a skip.
 * @param[in] from Client originating the command.
 * @param[in] cmd Long name of command (ignored).
 * @param[in] tok Short name of command.
 * @param[in] to Destination channel.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] skip Bitmask of SKIP_NONOPS and SKIP_NONVOICES indicating which clients to skip.
 * @param[in] pattern Format string for command arguments.
 */
void sendcmdto_channel_servers_butone(struct Client *from, const char *cmd,
                                      const char *tok, struct Channel *to,
                                      struct Client *one, unsigned int skip,
                                      const char *pattern, ...)
{
  struct VarData vd;
  struct MsgBuf *serv_mb;
  struct Membership *member;

  /* build the buffer */
  vd.vd_format = pattern;
  va_start(vd.vd_args, pattern);
  serv_mb = msgq_make(&me, "%:#C %s %v", from, tok, &vd);
  va_end(vd.vd_args);

  /* send the buffer to each server */
  bump_sentalong(one);
  cli_sentalong(from) = sentalong_marker;
  for (member = to->members; member; member = member->next_member) {
    if (MyConnect(member->user)
        || IsZombie(member)
        || cli_fd(cli_from(member->user)) < 0
        || cli_sentalong(member->user) == sentalong_marker
        || (skip & SKIP_NONOPS && !IsChanOp(member))
        || (skip & SKIP_NONHOPS && !IsChanOp(member) && !IsHalfOp(member))
        || (skip & SKIP_NONVOICES && !IsChanOp(member) && !IsHalfOp(member)&& !HasVoice(member)))
      continue;
    cli_sentalong(member->user) = sentalong_marker;
    send_buffer(member->user, serv_mb, 0);
  }
  msgq_clean(serv_mb);
}
Beispiel #3
0
/** Send a bot command to all local users on a channel.
 * @param[in] botname Bot sending the command.
 * @param[in] cmd Long name of command.
 * @param[in] tok Short name of command (ignored).
 * @param[in] to Destination channel.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] skip Bitmask of SKIP_DEAF, SKIP_NONOPS, SKIP_NONVOICES indicating which clients to skip.
 * @param[in] pattern Format string for command arguments.
 */
void sendcmdbotto_channel(const char *botname, const char *cmd,
                          const char *tok, struct Channel *to,
                          struct Client *one, unsigned int skip,
                          const char *pattern, ...)
{
  struct VarData vd;
  struct MsgBuf *mb;
  struct Membership *member;

  vd.vd_format = pattern; /* set up the struct VarData for %v */
  va_start(vd.vd_args, pattern);

  /* build the buffer */
  mb = msgq_make(0, ":%s %s %v", botname, cmd, &vd);
  va_end(vd.vd_args);

  /* send the buffer to each local channel member */
  for (member = to->members; member; member = member->next_member) {
    if (!MyConnect(member->user)
        || member->user == one
        || IsZombie(member)
        || (skip & SKIP_DEAF && IsDeaf(member->user))
#if defined(DDB) || defined(SERVICES)
        || (skip & SKIP_NONOPS && !IsChanOwner(member) && !IsChanOp(member))
        || (skip & SKIP_NONVOICES && !IsChanOwner(member) && !IsChanOp(member) && !HasVoice(member)))
#else
        || (skip & SKIP_NONOPS && !IsChanOp(member))
        || (skip & SKIP_NONVOICES && !IsChanOp(member) && !HasVoice(member)))
#endif
        continue;
      send_buffer(member->user, mb, 0);
  }

  msgq_clean(mb);
}
Beispiel #4
0
/** Send a (prefixed) command to all users on this channel, except for
 * \a one and those matching \a skip.
 * @warning \a pattern must not contain %v.
 * @param[in] from Client originating the command.
 * @param[in] cmd Long name of command.
 * @param[in] tok Short name of command.
 * @param[in] to Destination channel.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] skip Bitmask of SKIP_NONOPS, SKIP_NONVOICES, SKIP_DEAF, SKIP_BURST, SKIP_SERVERS.
 * @param[in] pattern Format string for command arguments.
 */
void sendcmdto_channel(struct Client *from, const char *cmd,
                       const char *tok, struct Channel *to,
                       struct Client *one, unsigned int skip,
                       const char *pattern, ...)
{
  struct Membership *member;
  struct VarData vd;
  struct MsgBuf *user_mb;
  struct MsgBuf *serv_mb;

  vd.vd_format = pattern;

  /* Build buffer to send to users */
  va_start(vd.vd_args, pattern);
  user_mb = msgq_make(0, skip & (SKIP_NONOPS | SKIP_NONVOICES) ? "%:#C %s @%v" : "%:#C %s %v",
                      from, cmd, &vd);
  va_end(vd.vd_args);

  /* Build buffer to send to servers */
  if ((skip & SKIP_SERVERS) || IsLocalChannel(to->chname))
    serv_mb = NULL;
  else
  {
    va_start(vd.vd_args, pattern);
    serv_mb = msgq_make(&me, skip & SKIP_NONOPS ? "%C %s @%v" : "%C %s %v",
                        from, tok, &vd);
    va_end(vd.vd_args);
  }

  /* send buffer along! */
  bump_sentalong(one);
  for (member = to->members; member; member = member->next_member) {
    /* skip duplicates, zombies, and flagged users... */
    if (cli_sentalong(member->user) == sentalong_marker ||
        IsZombie(member) ||
        (skip & SKIP_DEAF && IsDeaf(member->user)) ||
#if defined(DDB) || defined(SERVICES)
        (skip & SKIP_NONOPS && !IsChanOwner(member) && !IsChanOp(member)) ||
        (skip & SKIP_NONVOICES && !IsChanOwner(member) && !IsChanOp(member) && !HasVoice(member)) ||
#else
        (skip & SKIP_NONOPS && !IsChanOp(member)) ||
        (skip & SKIP_NONVOICES && !IsChanOp(member) && !HasVoice(member)) ||
#endif
        (skip & SKIP_COLOUR && !IsStripColour(member->user)) ||
        (skip & SKIP_NOCOLOUR && IsStripColour(member->user)) ||
        (skip & SKIP_BURST && IsBurstOrBurstAck(cli_from(member->user))) ||
        !(serv_mb || MyUser(member->user)) ||
        cli_fd(cli_from(member->user)) < 0)
      continue;
    cli_sentalong(member->user) = sentalong_marker;

    /* pick right buffer to send */
    send_buffer(member->user, MyConnect(member->user) ? user_mb : serv_mb, 0);
  }

  msgq_clean(user_mb);
  if (serv_mb)
    msgq_clean(serv_mb);
}
Beispiel #5
0
/** Send a (prefixed) command to all users on this channel, except for
 * \a one and those matching \a skip.
 * @warning \a pattern must not contain %v.
 * @param[in] from Client originating the command.
 * @param[in] cmd Long name of command.
 * @param[in] tok Short name of command.
 * @param[in] to Destination channel.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] skip Bitmask of SKIP_NONOPS, SKIP_NONVOICES, SKIP_DEAF, SKIP_BURST.
 * @param[in] pattern Format string for command arguments.
 */
void sendcmdto_channel_butone(struct Client *from, const char *cmd,
			      const char *tok, struct Channel *to,
			      struct Client *one, unsigned int skip,
			      const char *pattern, ...)
{
  struct Membership *member;
  struct VarData vd;
  struct MsgBuf *user_mb;
  struct MsgBuf *serv_mb;

  vd.vd_format = pattern;

  /* Build buffer to send to users */
  va_start(vd.vd_args, pattern);
  user_mb = msgq_make(0, skip & (SKIP_NONOPS | SKIP_NONVOICES) ? "%:#C %s @%v" : "%:#C %s %v",
                      from, skip & (SKIP_NONOPS | SKIP_NONVOICES) ? MSG_NOTICE : cmd, &vd);
  va_end(vd.vd_args);

  /* Build buffer to send to servers */
  va_start(vd.vd_args, pattern);
  serv_mb = msgq_make(&me, "%C %s %v", from, tok, &vd);
  va_end(vd.vd_args);

  /* send buffer along! */
  bump_sentalong(one);
  for (member = to->members; member; member = member->next_member) {
    /* skip one, zombies, and deaf users... */
    if (IsZombie(member) ||
        (skip & SKIP_DEAF && IsDeaf(member->user)) ||
        (skip & SKIP_NONOPS && !IsChanOp(member)) ||
        (skip & SKIP_NONVOICES && !IsChanOp(member) && !HasVoice(member)) ||
        (skip & SKIP_BURST && IsBurstOrBurstAck(cli_from(member->user))) ||
        cli_fd(cli_from(member->user)) < 0 ||
        cli_sentalong(member->user) == sentalong_marker)
      continue;
    cli_sentalong(member->user) = sentalong_marker;

    if (MyConnect(member->user)) /* pick right buffer to send */
      send_buffer(member->user, user_mb, 0);
    else
      send_buffer(member->user, serv_mb, 0);
  }

  msgq_clean(user_mb);
  msgq_clean(serv_mb);
}
Beispiel #6
0
int
ms_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Channel *chptr = 0;
  struct ModeBuf mbuf;
  struct Membership *member = 0;

  if (parc < 3)
    return need_more_params(sptr, "MODE");

  if (IsLocalChannel(parv[1]))
    return 0;

  if (!(chptr = FindChannel(parv[1])))
    return set_user_mode(cptr, sptr, parc, parv);

  ClrFlag(sptr, FLAG_TS8);

  if (IsServer(sptr)) {
    if (cli_uworld(sptr))
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to clients */
		    MODEBUF_DEST_SERVER  | /* Send mode to servers */
		    MODEBUF_DEST_HACK4));  /* Send a HACK(4) message */
    else
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to clients */
		    MODEBUF_DEST_SERVER  | /* Send mode to servers */
		    MODEBUF_DEST_HACK3));  /* Send a HACK(3) message */

    mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
	       (MODE_PARSE_SET    | /* Set the mode */
		MODE_PARSE_STRICT | /* Interpret it strictly */
		MODE_PARSE_FORCE), NULL); /* And force it to be accepted */
  } else {
    if (!IsChannelService(sptr) && (!(member = find_member_link(chptr, sptr)) || (!IsChanOp(member) && !IsHalfOp(member)))) {
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_SERVER |  /* Send mode to server */
		    MODEBUF_DEST_HACK2  |  /* Send a HACK(2) message */
		    MODEBUF_DEST_DEOP   |  /* Deop the source */
		    MODEBUF_DEST_BOUNCE)); /* And bounce the MODE */
      mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
		 (MODE_PARSE_STRICT |  /* Interpret it strictly */
		  MODE_PARSE_BOUNCE), member); /* And bounce the MODE */
    } else {
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to clients */
		    MODEBUF_DEST_SERVER)); /* Send mode to servers */
      mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
		 (MODE_PARSE_SET    | /* Set the mode */
		  MODE_PARSE_STRICT | /* Interpret it strictly */
		  MODE_PARSE_FORCE), member); /* And force it to be accepted */
    }
  }

  return modebuf_flush(&mbuf);
}
Beispiel #7
0
int
m_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Channel *chptr = 0;
  unsigned int hoflags  = 0;
  struct ModeBuf mbuf;
  struct Membership *member = 0;

  if (parc < 2)
    return need_more_params(sptr, "MODE");

  clean_channelname(parv[1]);

  if (!(chptr = FindChannel(parv[1])))
    return set_user_mode(cptr, sptr, parc, parv);

  ClrFlag(sptr, FLAG_TS8);

  member = find_member_link(chptr, sptr);

  if (parc < 3) {
    char modebuf[MODEBUFLEN];
    char parabuf[MODEBUFLEN];

    *modebuf = *parabuf = '\0';
    modebuf[1] = '\0';
    channel_modes(sptr, modebuf, parabuf, sizeof(parabuf), chptr);
    send_reply(sptr, RPL_CHANNELMODEIS, chptr->chname, modebuf, parabuf);
    send_reply(sptr, RPL_CREATIONTIME, chptr->chname, chptr->creationtime);
    return 0;
  }

  if ((!member && !IsChannelService(sptr)) ||
      (member && !IsChanOp(member) && !IsHalfOp(member))) {
    if (IsLocalChannel(chptr->chname) && HasPriv(sptr, PRIV_MODE_LCHAN)) {
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to channel */
		    MODEBUF_DEST_HACK4));  /* Send HACK(4) notice */
      mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
		 (MODE_PARSE_SET |    /* Set the mode */
		  MODE_PARSE_FORCE), NULL); /* Force it to take */
      return modebuf_flush(&mbuf);
    } else
      mode_parse(0, cptr, sptr, chptr, parc - 2, parv + 2,
		 (member ? MODE_PARSE_NOTOPER : MODE_PARSE_NOTMEMBER), NULL);
    return 0;
  }

  modebuf_init(&mbuf, sptr, cptr, chptr,
	       (MODEBUF_DEST_CHANNEL | /* Send mode to channel */
		MODEBUF_DEST_SERVER)); /* Send mode to servers */

  if (member && IsChanOp(member))
    hoflags = MODE_PARSE_SET; /* set unconditionally */
  else if (member && IsHalfOp(member))
    hoflags = MODE_PARSE_ISHALFOP|MODE_PARSE_SET|MODE_PARSE_NOTOPER; /* allowed to +v */
  else
    hoflags = MODE_PARSE_NOTOPER;
  mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2, hoflags, member);
  return modebuf_flush(&mbuf);
}
/*
 * ms_kick - server message handler
 *
 * parv[0] = sender prefix
 * parv[1] = channel
 * parv[2] = client to kick
 * parv[parc-1] = kick comment
 */
int ms_kick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Client *who;
  struct Channel *chptr;
  struct Membership *member = 0, *sptr_link = 0;
  char *name, *comment;

  ClrFlag(sptr, FLAG_TS8);

  if (parc < 3 || *parv[1] == '\0')
    return need_more_params(sptr, "KICK");

  name = parv[1];
  comment = parv[parc - 1];

  /* figure out who gets kicked from what */
  if (IsLocalChannel(name) ||
      !(chptr = get_channel(sptr, name, CGT_NO_CREATE)) ||
      !(who = findNUser(parv[2])))
    return 0;

  /* We go ahead and pass on the KICK for users not on the channel */
  member = find_member_link(chptr, who);
  if (member && IsZombie(member))
  {
    /* We might get a KICK from a zombie's own server because the user
     * net-rode during a burst (which always generates a KICK) *and*
     * was kicked via another server.  In that case, we must remove
     * the user from the channel.
     */
    if (sptr == cli_user(who)->server)
    {
      remove_user_from_channel(who, chptr);
    }
    /* Otherwise, we treat zombies like they are not channel members. */
    member = 0;
  }

  /* Send HACK notice, but not for servers in BURST */
  /* 2002-10-17: Don't send HACK if the users local server is kicking them */
  if (IsServer(sptr) &&
      !IsBurstOrBurstAck(sptr) &&
      sptr!=cli_user(who)->server)
    sendto_opmask_butone(0, SNO_HACK4, "HACK: %C KICK %H %C %s", sptr, chptr,
			 who, comment);

  /* Unless someone accepted it downstream (or the user isn't on the channel
   * here), if kicker is not on channel, or if kicker is not a channel
   * operator, bounce the kick
   */
  if (!IsServer(sptr) && member && cli_from(who) != cptr &&
      (!(sptr_link = find_member_link(chptr, sptr)) || !IsChanOp(sptr_link))) {
    sendto_opmask_butone(0, SNO_HACK2, "HACK: %C KICK %H %C %s", sptr, chptr,
			 who, comment);

    sendcmdto_one(who, CMD_JOIN, cptr, "%H", chptr);

    /* Reop/revoice member */
    if (IsChanOp(member) || HasVoice(member)) {
      struct ModeBuf mbuf;

      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_SERVER |  /* Send mode to a server */
		    MODEBUF_DEST_DEOP   |  /* Deop the source */
		    MODEBUF_DEST_BOUNCE)); /* And bounce the MODE */

      if (IsChanOp(member))
	modebuf_mode_client(&mbuf, MODE_DEL | MODE_CHANOP, who, OpLevel(member));
      if (HasVoice(member))
	modebuf_mode_client(&mbuf, MODE_DEL | MODE_VOICE, who, MAXOPLEVEL + 1);

      modebuf_flush(&mbuf);
    }
  } else {
    /* Propagate kick... */
    sendcmdto_serv_butone(sptr, CMD_KICK, cptr, "%H %C :%s", chptr, who,
			  comment);

    if (member) { /* and tell the channel about it */
      if (IsDelayedJoin(member)) {
        if (MyUser(who))
          sendcmdto_one(IsServer(sptr) ? &his : sptr, CMD_KICK,
                        who, "%H %C :%s", chptr, who, comment);
      } else {
        sendcmdto_channel_butserv_butone(IsServer(sptr) ? &his : sptr, CMD_KICK,
                                         chptr, NULL, 0, "%H %C :%s", chptr, who,
                                         comment);
      }

      make_zombie(member, who, cptr, sptr, chptr);
    }
  }

  return 0;
}
/*
 * m_kick - generic message handler
 *
 * parv[0] = sender prefix
 * parv[1] = channel
 * parv[2] = client to kick
 * parv[parc-1] = kick comment
 */
int m_kick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Client *who;
  struct Channel *chptr;
  struct Membership *member = 0;
  struct Membership* member2;
  char *name, *comment;

  ClrFlag(sptr, FLAG_TS8);

  if (parc < 3 || *parv[1] == '\0')
    return need_more_params(sptr, "KICK");

  name = parv[1];

  /* simple checks */
  if (!(chptr = get_channel(sptr, name, CGT_NO_CREATE)))
    return send_reply(sptr, ERR_NOSUCHCHANNEL, name);

  if (!(member2 = find_member_link(chptr, sptr)) || IsZombie(member2)
      || !IsChanOp(member2))
    return send_reply(sptr, ERR_CHANOPRIVSNEEDED, name);

  if (!(who = find_chasing(sptr, parv[2], 0)))
    return 0; /* find_chasing sends the reply for us */

  /* Don't allow the channel service to be kicked */
  if (IsChannelService(who))
    return send_reply(sptr, ERR_ISCHANSERVICE, cli_name(who), chptr->chname);

  /* Prevent kicking opers from local channels -DM- */
  if (IsLocalChannel(chptr->chname) && HasPriv(who, PRIV_DEOP_LCHAN))
    return send_reply(sptr, ERR_ISOPERLCHAN, cli_name(who), chptr->chname);

  /* check if kicked user is actually on the channel */
  if (!(member = find_member_link(chptr, who)) || IsZombie(member))
    return send_reply(sptr, ERR_USERNOTINCHANNEL, cli_name(who), chptr->chname);

  /* Don't allow to kick member with a higher op-level,
   * or members with the same op-level unless both are MAXOPLEVEL.
   */
  if (OpLevel(member) < OpLevel(member2)
      || (OpLevel(member) == OpLevel(member2)
          && OpLevel(member) < MAXOPLEVEL))
    return send_reply(sptr, ERR_NOTLOWEROPLEVEL, cli_name(who), chptr->chname,
	OpLevel(member2), OpLevel(member), "kick",
	OpLevel(member) == OpLevel(member2) ? "the same" : "a higher");

  /* We rely on ircd_snprintf to truncate the comment */
  comment = EmptyString(parv[parc - 1]) ? parv[0] : parv[parc - 1];

  if (!IsLocalChannel(name))
    sendcmdto_serv_butone(sptr, CMD_KICK, cptr, "%H %C :%s", chptr, who,
			  comment);

  if (IsDelayedJoin(member)) {
    /* If it's a delayed join, only send the KICK to the person doing
     * the kicking and the victim */
    if (MyUser(who))
      sendcmdto_one(sptr, CMD_KICK, who, "%H %C :%s", chptr, who, comment);
    sendcmdto_one(who, CMD_JOIN, sptr, "%H", chptr);
    sendcmdto_one(sptr, CMD_KICK, sptr, "%H %C :%s", chptr, who, comment);
    CheckDelayedJoins(chptr);
  } else
    sendcmdto_channel_butserv_butone(sptr, CMD_KICK, chptr, NULL, 0, "%H %C :%s", chptr, who,
                                     comment);

  make_zombie(member, who, cptr, sptr, chptr);

  return 0;
}
Beispiel #10
0
void do_names(struct Client* sptr, struct Channel* chptr, int filter)
{ 
  int mlen;
  int idx;
  int flag;
  int needs_space; 
  int len; 
  char buf[BUFSIZE];
  struct Client *c2ptr;
  struct Membership* member;
  
  assert(chptr);
  assert(sptr);
  assert((filter&NAMES_ALL) != (filter&NAMES_VIS));

  /* Tag Pub/Secret channels accordingly. */

  strcpy(buf, "* ");
  if (PubChannel(chptr))
    *buf = '=';
  else if (SecretChannel(chptr))
    *buf = '@';
 
  len = strlen(chptr->chname);
  strcpy(buf + 2, chptr->chname);
  strcpy(buf + 2 + len, " :");

  idx = len + 4;
  flag = 1;
  needs_space = 0;

  if (!ShowChannel(sptr, chptr)) /* Don't list private channels unless we are on them. */
    return;

  /* Iterate over all channel members, and build up the list. */

  mlen = strlen(cli_name(&me)) + 10 + strlen(cli_name(sptr));
  
  for (member = chptr->members; member; member = member->next_member)
  {
    c2ptr = member->user;

    if (((filter&NAMES_VIS)!=0) && IsInvisible(c2ptr))
      continue;

    if (IsZombie(member) && member->user != sptr)
      continue;

    if (IsDelayedJoin(member) && (member->user != sptr) && !(filter & NAMES_DEL))
        continue;

    if ((!IsDelayedJoin(member) || (member->user == sptr)) && (filter & NAMES_DEL))
        continue;

    if (needs_space)
      buf[idx++] = ' ';
    needs_space=1;
    if (IsZombie(member))
      buf[idx++] = '!';
    else if (IsChanOp(member))
      buf[idx++] = '@';
    else if (HasVoice(member))
      buf[idx++] = '+';
    strcpy(buf + idx, cli_name(c2ptr));
    idx += strlen(cli_name(c2ptr));
    flag = 1;
    if (mlen + idx + NICKLEN + 5 > BUFSIZE)
      /* space, modifier, nick, \r \n \0 */
    {
      send_reply(sptr, (filter & NAMES_DEL) ? RPL_DELNAMREPLY : RPL_NAMREPLY, buf);
      idx = len + 4;
      flag = 0;
      needs_space=0;
    }
  }
  if (flag)
    send_reply(sptr, (filter & NAMES_DEL) ? RPL_DELNAMREPLY : RPL_NAMREPLY, buf); 
  if (filter&NAMES_EON)
    send_reply(sptr, RPL_ENDOFNAMES, chptr->chname);
}
Beispiel #11
0
void checkUsers(struct Client *sptr, struct Channel *chptr, int flags) {
  struct Membership *lp;
  struct SLink *slp;
  struct Client *acptr;

   char outbuf[BUFSIZE], ustat[64];
   int cntr = 0, opcntr = 0, hopcntr = 0, vcntr = 0, clones = 0, bans = 0, excepts = 0, c = 0, authed = 0;

   if (flags & CHECK_SHOWUSERS) {
     if (feature_bool(FEAT_HALFOPS))
       send_reply(sptr, RPL_DATASTR, "Users (@ = op, % = halfop, + = voice, * = clone)");
     else
       send_reply(sptr, RPL_DATASTR, "Users (@ = op, + = voice, * = clone)");
   }

   for (lp = chptr->members; lp; lp = lp->next_member)
   {
      int opped = 0;

      acptr = lp->user;

      if ((c = checkClones(chptr, acptr->cli_name, acptr->cli_user->realhost)) != 0)
      {
         ircd_snprintf(0, ustat, sizeof(ustat), "%2d ", c);
         clones++;
      }
      else
      {
         strcpy(ustat, "   ");
      }

      if (chptr && IsChanOp(lp))
      {
         strcat(ustat, "@");
         opcntr++;
         opped = 1;
      }

      else if (chptr && IsHalfOp(lp))
      {
         strcat(ustat, "%");
         hopcntr++;
      }

      else if (chptr && HasVoice(lp))
      {
         strcat(ustat, "+");
         vcntr++;
      }
      else
         strcat(ustat, " ");

      if ((c = IsAccount(acptr)) != 0) ++authed;

      if ((flags & CHECK_SHOWUSERS) || ((flags & CHECK_OPSONLY) && opped)) {
        ircd_snprintf(0, outbuf, sizeof(outbuf), "%s%c", acptr->cli_info, COLOR_OFF);
        send_reply(sptr, RPL_CHANUSER, ustat, acptr->cli_name, acptr->cli_user->realusername,
            (flags & CHECK_SHOWIPS) ? ircd_ntoa((const char*)&(cli_ip(acptr))) : acptr->cli_user->realhost, outbuf, 
            (c ? acptr->cli_user->account : ""));
      }

      cntr++;
   }

   send_reply(sptr, RPL_DATASTR, " ");

   if (feature_bool(FEAT_HALFOPS))
     ircd_snprintf(0, outbuf, sizeof(outbuf),
        "Total users:: %d (%d ops, %d half ops, %d voiced, %d clones, %d authed)",
        cntr, opcntr, hopcntr, vcntr, clones, authed);
   else
     ircd_snprintf(0, outbuf, sizeof(outbuf),
        "Total users:: %d (%d ops, %d voiced, %d clones, %d authed)",
        cntr, opcntr, vcntr, clones, authed);

   send_reply(sptr, RPL_DATASTR, outbuf);

   send_reply(sptr, RPL_DATASTR, " ");

   /* Do not display bans if ! flags & CHECK_SHOWUSERS */
   if (!(flags & CHECK_SHOWUSERS)) {
     send_reply(sptr, RPL_ENDOFCHECK, " ");
     return;
   }

   /* Bans */
   send_reply(sptr, RPL_DATASTR, "Bans on channel::");

   for (slp = chptr->banlist; slp; slp = slp->next)
   {
      ircd_snprintf(0, outbuf, sizeof(outbuf),  "[%d] - %s - Set by %s, on %s", 
         ++bans, slp->value.ban.banstr, slp->value.ban.who, myctime(slp->value.ban.when));
      send_reply(sptr, RPL_DATASTR, outbuf);
   }

   if (bans == 0)
     send_reply(sptr, RPL_DATASTR, "<none>");

   /* Excepts */
   if (feature_bool(FEAT_EXCEPTS)) {
     send_reply(sptr, RPL_DATASTR, "Excepts on channel::");

     for (slp = chptr->exceptlist; slp; slp = slp->next)
     {
        ircd_snprintf(0, outbuf, sizeof(outbuf),  "[%d] - %s - Set by %s, on %s",
           ++excepts, slp->value.except.exceptstr, slp->value.except.who, myctime(slp->value.except.when));
        send_reply(sptr, RPL_DATASTR, outbuf);
     }

     if (excepts == 0)
       send_reply(sptr, RPL_DATASTR, "<none>");
   }

   send_reply(sptr, RPL_ENDOFCHECK, " ");
}
Beispiel #12
0
int
ms_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Channel *chptr = 0;
  struct ModeBuf mbuf;
  struct Membership *member;

  if (parc < 3)
    return need_more_params(sptr, "MODE");

  if (IsLocalChannel(parv[1]))
    return 0;

  if (!(chptr = FindChannel(parv[1])))
  {
    struct Client *acptr;

    acptr = FindUser(parv[1]);
    if (!acptr)
    {
      return 0;
    }
    else if (sptr != acptr)
    {
      sendwallto_group_butone(&me, WALL_WALLOPS, 0, 
                              "MODE for User %s from %s!%s", parv[1],
                              cli_name(cptr), cli_name(sptr));
      return 0;
    }
    return set_user_mode(cptr, sptr, parc, parv, ALLOWMODES_ANY);
  }

  ClrFlag(sptr, FLAG_TS8);

  if (IsServer(sptr)) {
    if (find_conf_byhost(cli_confs(cptr), cli_name(sptr), CONF_UWORLD))
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to clients */
		    MODEBUF_DEST_SERVER  | /* Send mode to servers */
		    MODEBUF_DEST_HACK4));  /* Send a HACK(4) message */
    else if (!feature_bool(FEAT_OPLEVELS))
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to clients */
		    MODEBUF_DEST_SERVER  | /* Send mode to servers */
		    MODEBUF_DEST_HACK3));  /* Send a HACK(3) message */
    else
      /* Servers need to be able to op people who join using the Apass
       * or upass, as well as people joining a zannel, therefore we do
       * not generate HACK3 when oplevels are on. */
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to clients */
		    MODEBUF_DEST_SERVER));   /* Send mode to servers */

    mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
	       (MODE_PARSE_SET    | /* Set the mode */
		MODE_PARSE_STRICT | /* Interpret it strictly */
		MODE_PARSE_FORCE),  /* And force it to be accepted */
	        NULL);
  } else {
    if (!(member = find_member_link(chptr, sptr)) || !IsChanOp(member)) {
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_SERVER |  /* Send mode to server */
		    MODEBUF_DEST_HACK2  |  /* Send a HACK(2) message */
		    MODEBUF_DEST_DEOP   |  /* Deop the source */
		    MODEBUF_DEST_BOUNCE)); /* And bounce the MODE */
      mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
		 (MODE_PARSE_STRICT |  /* Interpret it strictly */
		  MODE_PARSE_BOUNCE),  /* And bounce the MODE */
		  member);
    } else {
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to clients */
		    MODEBUF_DEST_SERVER)); /* Send mode to servers */
      mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
		 (MODE_PARSE_SET    | /* Set the mode */
		  MODE_PARSE_STRICT | /* Interpret it strictly */
		  MODE_PARSE_FORCE),  /* And force it to be accepted */
		  member);
    }
  }

  return modebuf_flush(&mbuf);
}
Beispiel #13
0
int
m_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Channel *chptr = 0;
  struct ModeBuf mbuf;
  struct Membership *member;

  if (parc < 2)
    return need_more_params(sptr, "MODE");

  if (!IsChannelName(parv[1]) || !(chptr = FindChannel(parv[1])))
  {
    struct Client *acptr;

    acptr = FindUser(parv[1]);
    if (!acptr)
    {
      send_reply(sptr, ERR_NOSUCHCHANNEL, parv[1]);
      return 0;
    }
    else if (sptr != acptr)
    {
      send_reply(sptr, ERR_USERSDONTMATCH);
      return 0;
    }
    return set_user_mode(cptr, sptr, parc, parv, ALLOWMODES_ANY);
  }

  ClrFlag(sptr, FLAG_TS8);

  member = find_member_link(chptr, sptr);

  if (parc < 3) {
    char modebuf[MODEBUFLEN];
    char parabuf[MODEBUFLEN];

    *modebuf = *parabuf = '\0';
    modebuf[1] = '\0';
    channel_modes(sptr, modebuf, parabuf, sizeof(parabuf), chptr, member);
    send_reply(sptr, RPL_CHANNELMODEIS, chptr->chname, modebuf, parabuf);
    send_reply(sptr, RPL_CREATIONTIME, chptr->chname, chptr->creationtime);
    return 0;
  }

  if (!member || !IsChanOp(member)) {
    if (IsLocalChannel(chptr->chname) && HasPriv(sptr, PRIV_MODE_LCHAN)) {
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to channel */
		    MODEBUF_DEST_HACK4));  /* Send HACK(4) notice */
      mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
		 (MODE_PARSE_SET |    /* Set the mode */
		  MODE_PARSE_FORCE),  /* Force it to take */
		  member);
      return modebuf_flush(&mbuf);
    } else
      mode_parse(0, cptr, sptr, chptr, parc - 2, parv + 2,
		 (member ? MODE_PARSE_NOTOPER : MODE_PARSE_NOTMEMBER), member);
    return 0;
  }

  modebuf_init(&mbuf, sptr, cptr, chptr,
	       (MODEBUF_DEST_CHANNEL | /* Send mode to channel */
		MODEBUF_DEST_SERVER)); /* Send mode to servers */
  mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2, MODE_PARSE_SET, member);
  return modebuf_flush(&mbuf);
}
Beispiel #14
0
/** Send a (prefixed) command to all users on this channel, except for
 * \a one and those matching \a skip.
 * @warning \a pattern must not contain %v.
 * @param[in] from Client originating the command.
 * @param[in] cmd Long name of command.
 * @param[in] tok Short name of command.
 * @param[in] to Destination channel.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] skip Bitmask of SKIP_NONOPS, SKIP_NONVOICES, SKIP_DEAF, SKIP_BURST.
 * @param[in] pattern Format string for command arguments.
 */
void sendcmdto_channel_butone(struct Client *from, const char *cmd,
			      const char *tok, struct Channel *to,
			      struct Client *one, unsigned int skip,
			      unsigned char prefix, const char *pattern, ...)
{
  struct Membership *member;
  struct VarData vd;
  struct MsgBuf *user_mb;
  struct MsgBuf *serv_mb;
  struct Client *service;
  const char *userfmt;
  const char *usercmd;

  vd.vd_format = pattern;

  /* Build buffer to send to users */
  usercmd = cmd;
  userfmt = "%:#C %s %v";
  if (skip & (SKIP_NONOPS | SKIP_NONHOPS | SKIP_NONVOICES)) {
    usercmd = MSG_NOTICE;
    if (skip & SKIP_NONVOICES)
      userfmt = "%:#C %s +%v";
    else if (skip & SKIP_NONHOPS)
      userfmt = "%:#C %s %%%v";
    else
      userfmt = "%:#C %s @%v";
  }

  va_start(vd.vd_args, pattern);
  user_mb = msgq_make(0, userfmt, from, usercmd, &vd);
  va_end(vd.vd_args);

  /* Build buffer to send to servers */
  va_start(vd.vd_args, pattern);
  serv_mb = msgq_make(&me, "%C %s %v", from, tok, &vd);
  va_end(vd.vd_args);

  /* send buffer along! */
  bump_sentalong(one);
  for (member = to->members; member; member = member->next_member) {
    /* skip one, zombies, and deaf users... */
    if (IsZombie(member) ||
        (skip & SKIP_DEAF && IsDeaf(member->user)) ||
        (skip & SKIP_NONOPS && !IsChanOp(member)) ||
        (skip & SKIP_NONHOPS && !IsChanOp(member) && !IsHalfOp(member)) ||
        (skip & SKIP_NONVOICES && !IsChanOp(member) && !IsHalfOp(member) && !HasVoice(member)) ||
        (skip & SKIP_BURST && IsBurstOrBurstAck(cli_from(member->user))) ||
        (is_silenced(from, member->user, 1)) ||
        cli_fd(cli_from(member->user)) < 0 ||
        cli_sentalong(member->user) == sentalong_marker)
      continue;
    cli_sentalong(member->user) = sentalong_marker;

    if (MyConnect(member->user)) /* pick right buffer to send */
      send_buffer(member->user, user_mb, 0);
    else
      send_buffer(member->user, serv_mb, 0);
  }
  /* Consult service forwarding table. */
  if(GlobalForwards[prefix]
      && (service = FindServer(GlobalForwards[prefix]))
      && cli_sentalong(service) != sentalong_marker) {
      cli_sentalong(service) = sentalong_marker;
      send_buffer(service, serv_mb, 0);
  }

  msgq_clean(user_mb);
  msgq_clean(serv_mb);
}
Beispiel #15
0
/*
 * do_clearmode(struct Client *cptr, struct Client *sptr,
 *		struct Channel *chptr, char *control)
 *
 * This is the function that actually clears the channel modes.
 */
static int
do_clearmode(struct Client *cptr, struct Client *sptr, struct Channel *chptr,
	     char *control)
{
  static int flags[] = {
    MODE_CHANOP,	'o',
    MODE_VOICE,		'v',
    MODE_PRIVATE,	'p',
    MODE_SECRET,	's',
    MODE_MODERATED,	'm',
    MODE_TOPICLIMIT,	't',
    MODE_INVITEONLY,	'i',
    MODE_NOPRIVMSGS,	'n',
    MODE_KEY,		'k',
    MODE_BAN,		'b',
    MODE_LIMIT,		'l',
    MODE_REGONLY,	'r',
    MODE_DELJOINS,      'D',
    0x0, 0x0
  };
  int *flag_p;
  unsigned int del_mode = 0;
  char control_buf[20];
  int control_buf_i = 0;
  struct ModeBuf mbuf;
  struct Ban *link, *next;
  struct Membership *member;

  /* Ok, so what are we supposed to get rid of? */
  for (; *control; control++) {
    for (flag_p = flags; flag_p[0]; flag_p += 2)
      if (*control == flag_p[1]) {
	del_mode |= flag_p[0];
	break;
      }
  }

  if (!del_mode)
    return 0; /* nothing to remove; ho hum. */

  modebuf_init(&mbuf, sptr, cptr, chptr,
	       (MODEBUF_DEST_CHANNEL | /* Send MODE to channel */
		MODEBUF_DEST_OPMODE  | /* Treat it like an OPMODE */
		MODEBUF_DEST_HACK4));  /* Generate a HACK(4) notice */

  modebuf_mode(&mbuf, MODE_DEL | (del_mode & chptr->mode.mode));
  chptr->mode.mode &= ~del_mode; /* and of course actually delete them */

  /* If we're removing invite, remove all the invites */
  if (del_mode & MODE_INVITEONLY)
    mode_invite_clear(chptr);

  /*
   * If we're removing the key, note that; note that we can't clear
   * the key until after modebuf_* are done with it
   */
  if (del_mode & MODE_KEY && *chptr->mode.key)
    modebuf_mode_string(&mbuf, MODE_DEL | MODE_KEY, chptr->mode.key, 0);

  /* If we're removing the limit, note that and clear the limit */
  if (del_mode & MODE_LIMIT && chptr->mode.limit) {
    modebuf_mode_uint(&mbuf, MODE_DEL | MODE_LIMIT, chptr->mode.limit);
    chptr->mode.limit = 0; /* not referenced, so safe */
  }

  /*
   * Go through and mark the bans for deletion; note that we can't
   * free them until after modebuf_* are done with them
   */
  if (del_mode & MODE_BAN) {
    for (link = chptr->banlist; link; link = next) {
      char *bandup;
      next = link->next;

      DupString(bandup, link->banstr);
      modebuf_mode_string(&mbuf, MODE_DEL | MODE_BAN, /* delete ban */
			  bandup, 1);
      free_ban(link);
    }

    chptr->banlist = 0;
  }

  /* Deal with users on the channel */
  if (del_mode & (MODE_BAN | MODE_CHANOP | MODE_VOICE))
    for (member = chptr->members; member; member = member->next_member) {
      if (IsZombie(member)) /* we ignore zombies */
	continue;

      if (del_mode & MODE_BAN) /* If we cleared bans, clear the valid flags */
	ClearBanValid(member);

      /* Drop channel operator status */
      if (IsChanOp(member) && del_mode & MODE_CHANOP) {
	modebuf_mode_client(&mbuf, MODE_DEL | MODE_CHANOP, member->user, MAXOPLEVEL + 1);
	member->status &= ~CHFL_CHANOP;
      }

      /* Drop voice */
      if (HasVoice(member) && del_mode & MODE_VOICE) {
	modebuf_mode_client(&mbuf, MODE_DEL | MODE_VOICE, member->user, MAXOPLEVEL + 1);
	member->status &= ~CHFL_VOICE;
      }
    }

  /* And flush the modes to the channel */
  modebuf_flush(&mbuf);

  /* Finally, we can clear the key... */
  if (del_mode & MODE_KEY)
    chptr->mode.key[0] = '\0';

  /* Ok, build control string again */
  for (flag_p = flags; flag_p[0]; flag_p += 2)
    if (del_mode & flag_p[0])
      control_buf[control_buf_i++] = flag_p[1];

  control_buf[control_buf_i] = '\0';

  /* Log it... */
  log_write(LS_OPERMODE, L_INFO, LOG_NOSNOTICE, "%#C CLEARMODE %H %s", sptr,
	    chptr, control_buf);

  /* Then send it */
  if (!IsLocalChannel(chptr->chname))
    sendcmdto_serv_butone(sptr, CMD_CLEARMODE, cptr, "%H %s", chptr,
			  control_buf);

  return 0;
}
/** Handle a JOIN message from a server connection.
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Membership *member;
  struct Channel *chptr;
  struct JoinBuf join;
  unsigned int flags;
  time_t creation = 0;
  char *p = 0;
  char *chanlist;
  char *name;

  if (IsServer(sptr))
  {
    return protocol_violation(cptr,
                              "%s tried to JOIN %s, duh!",
                              cli_name(sptr),
                              (parc < 2 || *parv[1] == '\0') ? "a channel" :
                                                               parv[1]
                              );
  }

  if (parc < 2 || *parv[1] == '\0')
    return need_more_params(sptr, "JOIN");

  if (parc > 2 && parv[2])
    creation = atoi(parv[2]);

  joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0);

  chanlist = last0(cptr, sptr, parv[1]); /* find last "JOIN 0" */

  for (name = ircd_strtok(&p, chanlist, ","); name;
       name = ircd_strtok(&p, 0, ",")) {

    flags = CHFL_DEOPPED;

    if (IsLocalChannel(name) || !IsChannelName(name))
    {
      protocol_violation(cptr, "%s tried to join %s", cli_name(sptr), name);
      continue;
    }

    if (!(chptr = FindChannel(name)))
    {
      /* No channel exists, so create one */
      if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
      {
        protocol_violation(sptr,"couldn't get channel %s for %s",
        		   name,cli_name(sptr));
      	continue;
      }
      flags |= HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0;

      chptr->creationtime = creation;
    }
    else { /* We have a valid channel? */
      if ((member = find_member_link(chptr, sptr)))
      {
	/* It is impossible to get here --Run */
	if (!IsZombie(member)) /* already on channel */
	  continue;

	flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK);
	remove_user_from_channel(sptr, chptr);
	chptr = FindChannel(name);
      }
      else
        flags |= HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0;
      /* Always copy the timestamp when it is older, that is the only way to
         ensure network-wide synchronization of creation times.
         We now also copy a creation time that only 1 second younger...
         this is needed because the timestamp must be incremented
         by one when someone joins an existing, but empty, channel.
         However, this is only necessary when the channel is still
         empty (also here) and when this channel doesn't have +A set.

         To prevent this from allowing net-rides on the channel, we
         clear all modes from the channel.

         (Scenario for a net ride: c1 - s1 - s2 - c2, with c1 the only
         user in the channel; c1 parts and rejoins, gaining ops.
         Before s2 sees c1's part, c2 joins the channel and parts
         immediately.  s1 sees c1 part, c1 create, c2 join, c2 part;
         c2's join resets the timestamp.  s2 sees c2 join, c2 part, c1
         part, c1 create; but since s2 sees the channel as a zannel or
         non-existent, it does not bounce the create with the newer
         timestamp.)
      */
      if (creation && (creation < chptr->creationtime ||
		       (!chptr->mode.apass[0] && chptr->users == 0))) {
        struct Membership *member;
        struct ModeBuf mbuf;

	chptr->creationtime = creation;
        /* Wipe out the current modes on the channel. */
        modebuf_init(&mbuf, sptr, cptr, chptr, MODEBUF_DEST_CHANNEL | MODEBUF_DEST_HACK3);

        modebuf_mode(&mbuf, MODE_DEL | chptr->mode.mode);
        chptr->mode.mode &= MODE_BURSTADDED | MODE_WASDELJOINS;

        if (chptr->mode.limit) {
          modebuf_mode_uint(&mbuf, MODE_DEL | MODE_LIMIT, chptr->mode.limit);
          chptr->mode.limit = 0;
        }

        if (chptr->mode.key[0]) {
          modebuf_mode_string(&mbuf, MODE_DEL | MODE_KEY, chptr->mode.key, 0);
          chptr->mode.key[0] = '\0';
        }

        if (chptr->mode.upass[0]) {
          modebuf_mode_string(&mbuf, MODE_DEL | MODE_UPASS, chptr->mode.upass, 0);
          chptr->mode.upass[0] = '\0';
        }

        if (chptr->mode.apass[0]) {
          modebuf_mode_string(&mbuf, MODE_DEL | MODE_APASS, chptr->mode.apass, 0);
          chptr->mode.apass[0] = '\0';
        }

        for (member = chptr->members; member; member = member->next_member)
        {
          if (IsChanOp(member)) {
            modebuf_mode_client(&mbuf, MODE_DEL | MODE_CHANOP, member->user, OpLevel(member));
	    member->status &= ~CHFL_CHANOP;
	  }
          if (HasVoice(member)) {
            modebuf_mode_client(&mbuf, MODE_DEL | MODE_VOICE, member->user, OpLevel(member));
	    member->status &= ~CHFL_VOICE;
          }
        }
        modebuf_flush(&mbuf);
      }
    }

    joinbuf_join(&join, chptr, flags);
  }

  joinbuf_flush(&join); /* flush joins... */

  return 0;
}
Beispiel #17
0
/*
 * Send whois information for acptr to sptr
 */
static void do_whois(struct Client* sptr, struct Client *acptr, int parc)
{
  struct Client *a2cptr=0;
  struct Channel *chptr=0;
  int mlen;
  int len;
  static char buf[512];
  
  const struct User* user = cli_user(acptr);
  const char* name = (!*(cli_name(acptr))) ? "?" : cli_name(acptr);  
  a2cptr = feature_bool(FEAT_HIS_WHOIS_SERVERNAME) && !IsAnOper(sptr)
      && sptr != acptr ? &his : user->server;
  assert(user);
  send_reply(sptr, RPL_WHOISUSER, name, user->username, user->host,
		   cli_info(acptr));

  /* Display the channels this user is on. */
  if (!IsChannelService(acptr))
  {
    struct Membership* chan;
    mlen = strlen(cli_name(&me)) + strlen(cli_name(sptr)) + 12 + strlen(name);
    len = 0;
    *buf = '\0';
    for (chan = user->channel; chan; chan = chan->next_channel)
    {
       chptr = chan->channel;
       
       if (!ShowChannel(sptr, chptr)
           && !(IsOper(sptr) && IsLocalChannel(chptr->chname)))
          continue;

       if (acptr != sptr && IsZombie(chan))
          continue;

       /* Don't show local channels when HIS is defined, unless it's a
	* remote WHOIS --ULtimaTe_
	*/
       if (IsLocalChannel(chptr->chname) && (acptr != sptr) && (parc == 2)
           && feature_bool(FEAT_HIS_WHOIS_LOCALCHAN) && !IsAnOper(sptr))
	  continue;

       if (len+strlen(chptr->chname) + mlen > BUFSIZE - 5)
       {
          send_reply(sptr, SND_EXPLICIT | RPL_WHOISCHANNELS, "%s :%s", name, buf);
          *buf = '\0';
          len = 0;
       }
       if (IsDeaf(acptr))
         *(buf + len++) = '-';
       if (!ShowChannel(sptr, chptr))
         *(buf + len++) = '*';
       if (IsDelayedJoin(chan) && (sptr != acptr))
         *(buf + len++) = '<';
       else if (IsChanOp(chan))
         *(buf + len++) = '@';
       else if (HasVoice(chan))
         *(buf + len++) = '+';
       else if (IsZombie(chan))
         *(buf + len++) = '!';
       if (len)
          *(buf + len) = '\0';
       strcpy(buf + len, chptr->chname);
       len += strlen(chptr->chname);
       strcat(buf + len, " ");
       len++;
     }
     if (buf[0] != '\0')
        send_reply(sptr, RPL_WHOISCHANNELS, name, buf);
  }

  send_reply(sptr, RPL_WHOISSERVER, name, cli_name(a2cptr),
             cli_info(a2cptr));

  if (user)
  {
    if (user->away)
       send_reply(sptr, RPL_AWAY, name, user->away);

    if (SeeOper(sptr,acptr))
       send_reply(sptr, RPL_WHOISOPERATOR, name);

    if (IsAccount(acptr))
      send_reply(sptr, RPL_WHOISACCOUNT, name, user->account);

    if (HasHiddenHost(acptr) && (IsAnOper(sptr) || acptr == sptr))
      send_reply(sptr, RPL_WHOISACTUALLY, name, user->username,
                 user->realhost, ircd_ntoa(&cli_ip(acptr)));

    /* Hint: if your looking to add more flags to a user, eg +h, here's
     *       probably a good place to add them :)
     */

    if (MyConnect(acptr) && (!feature_bool(FEAT_HIS_WHOIS_IDLETIME) ||
                             (sptr == acptr || IsAnOper(sptr) || parc >= 3)))
       send_reply(sptr, RPL_WHOISIDLE, name, CurrentTime - user->last,
                  cli_firsttime(acptr));
  }
}