Exemplo n.º 1
0
/* Punishes bad guys under certain circumstances using methods as defined
 * by the revenge_mode flag.
 */
static void maybe_revenge(struct chanset_t *chan, char *whobad,
                          char *whovictim, int type)
{
    char *badnick, *victim;
    int mevictim;
    struct userrec *u, *u2;

    if (!chan || (type < 0))
        return;

    /* Get info about offender */
    u = get_user_by_host(whobad);
    badnick = splitnick(&whobad);

    /* Get info about victim */
    u2 = get_user_by_host(whovictim);
    victim = splitnick(&whovictim);
    mevictim = match_my_nick(victim);

    /* Do we want to revenge? */
    if (want_to_revenge(chan, u, u2, badnick, victim, mevictim))
        punish_badguy(chan, whobad, u, badnick, victim, mevictim, type);
}
Exemplo n.º 2
0
/* If this user@host is in a channel, set it (it was null)
 */
void set_chanlist(const char *host, struct userrec *rec)
{
  char *nick, *uhost, buf[UHOSTLEN];
  register memberlist *m;
  register struct chanset_t *chan;

  strncpyz(buf, host, sizeof buf);
  uhost = buf;
  nick = splitnick(&uhost);
  for (chan = chanset; chan; chan = chan->next)
    for (m = chan->channel.member; m && m->nick[0]; m = m->next)
      if (!rfc_casecmp(nick, m->nick) && !egg_strcasecmp(uhost, m->userhost))
        m->user = rec;
}
Exemplo n.º 3
0
/* WALLOPS: oper's nuisance
 */
static int gotwall(char *from, char *msg)
{
  char *nick;

  fixcolon(msg);

  if (check_tcl_wall(from, msg) != 2) {
    if (strchr(from, '!')) {
      nick = splitnick(&from);
      putlog(LOG_WALL, "*", "!%s(%s)! %s", nick, from, msg);
    } else
      putlog(LOG_WALL, "*", "!%s! %s", from, msg);
  }
  return 0;
}
Exemplo n.º 4
0
/* Shortcut for get_user_by_host -- might have user record in one
 * of the channel caches.
 */
struct userrec *check_chanlist(const char *host)
{
  char				*nick = NULL, *uhost = NULL, buf[UHOSTLEN] = "";
  register memberlist		*m = NULL;
  register struct chanset_t	*chan = NULL;

  strlcpy(buf, host, sizeof buf);
  uhost = buf;
  nick = splitnick(&uhost);
  for (chan = chanset; chan; chan = chan->next)
    for (m = chan->channel.member; m && m->nick[0]; m = m->next) 
      if (!rfc_casecmp(nick, m->nick) && !strcasecmp(uhost, m->userhost))
	return m->user;
  return NULL;
}
Exemplo n.º 5
0
/* Expire mask originally set by `who' on `chan'?
 *
 * We might not want to expire masks in all cases, as other bots
 * often tend to immediately reset masks they've listed in their
 * internal ban list, making it quite senseless for us to remove
 * them in the first place.
 *
 * Returns 1 if a mask on `chan' by `who' may be expired and 0 if
 * not.
 */
static int expired_mask(struct chanset_t *chan, char *who)
{
  memberlist *m, *m2;
  char buf[UHOSTLEN], *snick, *sfrom;
  struct userrec *u;

  /* Always expire masks, regardless of who set it? */
  if (force_expire)
    return 1;

  strcpy(buf, who);
  sfrom = buf;
  snick = splitnick(&sfrom);

  if (!snick[0])
    return 1;

  m = ismember(chan, snick);
  if (!m)
    for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next)
      if (!egg_strcasecmp(sfrom, m2->userhost)) {
        m = m2;
        break;
      }

  if (!m || !chan_hasop(m) || !rfc_casecmp(m->nick, botname))
    return 1;

  /* At this point we know the person/bot who set the mask is currently
   * present in the channel and has op.
   */

  if (m->user)
    u = m->user;
  else {
    simple_sprintf(buf, "%s!%s", m->nick, m->userhost);
    u = get_user_by_host(buf);
  }
  /* Do not expire masks set by bots. */
  if (u && u->flags & USER_BOT)
    return 0;
  else
    return 1;
}
Exemplo n.º 6
0
/* Got nick change.
 */
static int gotnick(char *from, char *msg)
{
  char *nick, *alt = get_altbotnick();

  nick = splitnick(&from);
  fixcolon(msg);
  check_queues(nick, msg);
  if (match_my_nick(nick)) {
    /* Regained nick! */
    strncpyz(botname, msg, NICKLEN);
    altnick_char = 0;
    if (!strcmp(msg, origbotname)) {
      putlog(LOG_SERV | LOG_MISC, "*", "Regained nickname '%s'.", msg);
      nick_juped = 0;
    } else if (alt[0] && !strcmp(msg, alt))
      putlog(LOG_SERV | LOG_MISC, "*", "Regained alternate nickname '%s'.",
             msg);
    else if (keepnick && strcmp(nick, msg)) {
      putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg);
      if (!rfc_casecmp(nick, origbotname)) {
        putlog(LOG_MISC, "*", IRC_GETORIGNICK, origbotname);
        dprintf(DP_SERVER, "NICK %s\n", origbotname);
      } else if (alt[0] && !rfc_casecmp(nick, alt) &&
               egg_strcasecmp(botname, origbotname)) {
        putlog(LOG_MISC, "*", IRC_GETALTNICK, alt);
        dprintf(DP_SERVER, "NICK %s\n", alt);
      }
    } else
      putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg);
  } else if ((keepnick) && (rfc_casecmp(nick, msg))) {
    /* Only do the below if there was actual nick change, case doesn't count */
    if (!rfc_casecmp(nick, origbotname)) {
      putlog(LOG_MISC, "*", IRC_GETORIGNICK, origbotname);
      dprintf(DP_SERVER, "NICK %s\n", origbotname);
    } else if (alt[0] && !rfc_casecmp(nick, alt) &&
             egg_strcasecmp(botname, origbotname)) {
      putlog(LOG_MISC, "*", IRC_GETALTNICK, altnick);
      dprintf(DP_SERVER, "NICK %s\n", altnick);
    }
  }
  return 0;
}
Exemplo n.º 7
0
/* Got a private notice.
 */
static int gotnotice(char *from, char *msg)
{
  char *to, *nick, ctcpbuf[512], *p, *p1, buf[512], *uhost = buf, *ctcp;
  struct userrec *u;
  int ignoring;

  /* Notice to a channel, not handled here */
  if (msg[0] && ((strchr(CHANMETA, *msg) != NULL) || (*msg == '@')))
    return 0;

  ignoring = match_ignore(from);
  to = newsplit(&msg);
  fixcolon(msg);
  strcpy(uhost, from);
  nick = splitnick(&uhost);

  /* Check for CTCP: */
  p = strchr(msg, 1);
  while ((p != NULL) && (*p)) {
    p++;
    p1 = p;
    while ((*p != 1) && (*p != 0))
      p++;
    if (*p == 1) {
      *p = 0;
      ctcp = strcpy(ctcpbuf, p1);
      strcpy(p1 - 1, p + 1);
      if (!ignoring)
        detect_flood(nick, uhost, from, FLOOD_CTCP);
      p = strchr(msg, 1);
      if (ctcp[0] != ' ') {
        char *code = newsplit(&ctcp);

        /* CTCP reply from oper, don't interpret */
        if ((to[0] == '$') || strchr(to, '.')) {
          if (!ignoring)
            putlog(LOG_PUBLIC, "*",
                   "CTCP reply %s: %s from %s (%s) to %s", code, ctcp,
                   nick, uhost, to);
        } else {
          u = get_user_by_host(from);
          if (!ignoring || trigger_on_ignore) {
            check_tcl_ctcr(nick, uhost, u, to, code, ctcp);
            if (!ignoring)
              /* Who cares? */
              putlog(LOG_MSGS, "*",
                     "CTCP reply %s: %s from %s (%s) to %s",
                     code, ctcp, nick, uhost, to);
          }
        }
      }
    }
  }
  if (msg[0]) {

    /* Notice from oper, don't interpret */
    if ((to[0] == '$') || (strchr(to, '.') != NULL)) {
      if (!ignoring) {
        detect_flood(nick, uhost, from, FLOOD_NOTICE);
        putlog(LOG_MSGS | LOG_SERV, "*", "-%s (%s) to %s- %s",
               nick, uhost, to, msg);
      }
      return 0;
    }

    /* Server notice? */
    if ((nick[0] == 0) || (uhost[0] == 0)) {

      /* Hidden `250' connection count message from server */
      if (strncmp(msg, "Highest connection count:", 25))
        putlog(LOG_SERV, "*", "-NOTICE- %s", msg);

      return 0;
    }

    detect_flood(nick, uhost, from, FLOOD_NOTICE);
    u = get_user_by_host(from);

    if (!ignoring || trigger_on_ignore)
      if (check_tcl_notc(nick, uhost, u, botname, msg) == 2)
        return 0;

    if (!ignoring)
      putlog(LOG_MSGS, "*", "-%s (%s)- %s", nick, uhost, msg);
  }
  return 0;
}
Exemplo n.º 8
0
/* Got a private message.
 */
static int gotmsg(char *from, char *msg)
{
  char *to, buf[UHOSTLEN], *nick, ctcpbuf[512], *uhost = buf, *ctcp,
       *p, *p1, *code;
  struct userrec *u;
  int ctcp_count = 0;
  int ignoring;

  /* Notice to a channel, not handled here */
  if (msg[0] && ((strchr(CHANMETA, *msg) != NULL) || (*msg == '@')))
    return 0;

  ignoring = match_ignore(from);
  to = newsplit(&msg);
  fixcolon(msg);
  strncpyz(uhost, from, sizeof(buf));
  nick = splitnick(&uhost);
 
  /* Check for CTCP: */
  ctcp_reply[0] = 0;
  p = strchr(msg, 1);
  while ((p != NULL) && (*p)) {
    p++;
    p1 = p;
    while ((*p != 1) && (*p != 0))
      p++;
    if (*p == 1) {
      *p = 0;
      strncpyz(ctcpbuf, p1, sizeof(ctcpbuf));
      ctcp = ctcpbuf;

      /* remove the ctcp in msg */
      memmove(p1 - 1, p + 1, strlen(p + 1) + 1);

      if (!ignoring)
        detect_flood(nick, uhost, from,
                     strncmp(ctcp, "ACTION ", 7) ? FLOOD_CTCP : FLOOD_PRIVMSG);
      /* Respond to the first answer_ctcp */
      p = strchr(msg, 1);
      if (ctcp_count < answer_ctcp) {
        ctcp_count++;
        if (ctcp[0] != ' ') {
          code = newsplit(&ctcp);

          /* CTCP from oper, don't interpret */
          if ((to[0] == '$') || strchr(to, '.')) {
            if (!ignoring)
              putlog(LOG_PUBLIC, to, "CTCP %s: %s from %s (%s) to %s",
                     code, ctcp, nick, uhost, to);
          } else {
            u = get_user_by_host(from);
            if (!ignoring || trigger_on_ignore) {
              if (!check_tcl_ctcp(nick, uhost, u, to, code, ctcp) && !ignoring) {
                if ((lowercase_ctcp && !egg_strcasecmp(code, "DCC")) ||
                    (!lowercase_ctcp && !strcmp(code, "DCC"))) {
                  /* If it gets this far unhandled, it means that
                   * the user is totally unknown.
                   */
                  code = newsplit(&ctcp);
                  if (!strcmp(code, "CHAT")) {
                    if (!quiet_reject) {
                      if (u)
                        dprintf(DP_HELP, "NOTICE %s :I'm not accepting calls "
                                "at the moment.\n", nick);
                      else
                        dprintf(DP_HELP, "NOTICE %s :%s\n", nick,
                                DCC_NOSTRANGERS);
                    }
                    putlog(LOG_MISC, "*", "%s: %s", DCC_REFUSED, from);
                  } else
                    putlog(LOG_MISC, "*", "Refused DCC %s: %s", code, from);
                }
              }
              if (!strcmp(code, "ACTION")) {
                putlog(LOG_MSGS, "*", "Action to %s: %s %s", to, nick, ctcp);
              } else {
                putlog(LOG_MSGS, "*", "CTCP %s: %s from %s (%s)", code, ctcp,
                       nick, uhost);
              }                 /* I love a good close cascade ;) */
            }
          }
        }
      }
    }
  }
  /* Send out possible ctcp responses */
  if (ctcp_reply[0]) {
    if (ctcp_mode != 2) {
      dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
    } else {
      if (now - last_ctcp > flud_ctcp_time) {
        dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
        count_ctcp = 1;
      } else if (count_ctcp < flud_ctcp_thr) {
        dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
        count_ctcp++;
      }
      last_ctcp = now;
    }
  }
  if (msg[0]) {
    int result = 0;

    /* Msg from oper, don't interpret */
    if ((to[0] == '$') || (strchr(to, '.') != NULL)) {
      if (!ignoring) {
        detect_flood(nick, uhost, from, FLOOD_PRIVMSG);
        putlog(LOG_MSGS | LOG_SERV, "*", "[%s!%s to %s] %s",
               nick, uhost, to, msg);
      }
      return 0;
    }

    detect_flood(nick, uhost, from, FLOOD_PRIVMSG);
    u = get_user_by_host(from);
    code = newsplit(&msg);
    rmspace(msg);

    if (!ignoring || trigger_on_ignore) {
      result = check_tcl_msgm(code, nick, uhost, u, msg);

      if (!result || !exclusive_binds)
        if (check_tcl_msg(code, nick, uhost, u, msg))
          return 0;
    }

    if (!ignoring && result != 2)
      putlog(LOG_MSGS, "*", "[%s] %s %s", from, code, msg);
  }
  return 0;
}
Exemplo n.º 9
0
/* Dependant on revenge_mode, punish the offender.
 */
static void punish_badguy(struct chanset_t *chan, char *whobad,
                          struct userrec *u, char *badnick, char *victim,
                          int mevictim, int type)
{
    char reason[1024], ct[81], *kick_msg;
    memberlist *m;
    struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };

    m = ismember(chan, badnick);
    if (!m)
        return;
    get_user_flagrec(u, &fr, chan->dname);

    /* Get current time into a string */
    egg_strftime(ct, 7, "%d %b", localtime(&now));

    /* Put together log and kick messages */
    reason[0] = 0;
    switch (type) {
    case REVENGE_KICK:
        kick_msg = IRC_KICK_PROTECT;
        simple_sprintf(reason, "kicked %s off %s", victim, chan->dname);
        break;
    case REVENGE_DEOP:
        simple_sprintf(reason, "deopped %s on %s", victim, chan->dname);
        kick_msg = IRC_DEOP_PROTECT;
        break;
    default:
        kick_msg = "revenge!";
    }
    putlog(LOG_MISC, chan->dname, "Punishing %s (%s)", badnick, reason);

    /* Set the offender +d */
    if ((chan->revenge_mode > 0) && !(chan_deop(fr) || glob_deop(fr))) {
        char s[UHOSTLEN], s1[UHOSTLEN];
        memberlist *mx = NULL;

        /* Removing op */
        if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) {
            fr.match = FR_CHAN;
            if (chan_op(fr))
                fr.chan &= ~USER_OP;
            else
                fr.chan |= USER_DEOP;
            set_user_flagrec(u, &fr, chan->dname);
            putlog(LOG_MISC, "*", "No longer opping %s[%s] (%s)", u->handle, whobad,
                   reason);
        }
        /* ... or just setting to deop */
        else if (u) {
            /* In the user list already, cool :) */
            fr.match = FR_CHAN;
            fr.chan |= USER_DEOP;
            set_user_flagrec(u, &fr, chan->dname);
            simple_sprintf(s, "(%s) %s", ct, reason);
            putlog(LOG_MISC, "*", "Now deopping %s[%s] (%s)", u->handle, whobad, s);
        }
        /* ... or creating new user and setting that to deop */
        else {
            strcpy(s1, whobad);
            maskaddr(s1, s, chan->ban_type);
            strcpy(s1, badnick);
            /* If that handle exists use "badX" (where X is an increasing number)
             * instead.
             */
            while (get_user_by_handle(userlist, s1)) {
                if (!strncmp(s1, "bad", 3)) {
                    int i;

                    i = atoi(s1 + 3);
                    simple_sprintf(s1 + 3, "%d", i + 1);
                } else
                    strcpy(s1, "bad1");   /* Start with '1' */
            }
            userlist = adduser(userlist, s1, s, "-", 0);
            fr.match = FR_CHAN;
            fr.chan = USER_DEOP;
            fr.udef_chan = 0;
            u = get_user_by_handle(userlist, s1);
            if ((mx = ismember(chan, badnick)))
                mx->user = u;
            set_user_flagrec(u, &fr, chan->dname);
            simple_sprintf(s, "(%s) %s (%s)", ct, reason, whobad);
            set_user(&USERENTRY_COMMENT, u, (void *) s);
            putlog(LOG_MISC, "*", "Now deopping %s (%s)", whobad, reason);
        }
    }

    /* Always try to deop the offender */
    if (!mevictim)
        add_mode(chan, '-', 'o', badnick);
    /* Ban. Should be done before kicking. */
    if (chan->revenge_mode > 2) {
        char s[UHOSTLEN], s1[UHOSTLEN];

        splitnick(&whobad);
        maskaddr(whobad, s1, chan->ban_type);
        simple_sprintf(s, "(%s) %s", ct, reason);
        u_addban(chan, s1, botnetnick, s, now + (60 * chan->ban_time), 0);
        if (!mevictim && HALFOP_CANDOMODE('b')) {
            add_mode(chan, '+', 'b', s1);
            flush_mode(chan, QUICK);
        }
    }
    /* Kick the offender */
    if (!mevictim && (chan->revenge_mode > 1) && (!channel_dontkickops(chan) ||
            (!chan_op(fr) && (!glob_op(fr) || chan_deop(fr)))) &&
            !chan_sentkick(m) && (me_op(chan) || (me_halfop(chan) &&
                                  !chan_hasop(m) && (strchr(NOHALFOPS_MODES, 'b') == NULL)))) {
        dprintf(DP_MODE, "KICK %s %s :%s\n", chan->name, badnick, kick_msg);
        m->flags |= SENTKICK;
    }
}
Exemplo n.º 10
0
static int gotmode(char *from, char *origmsg)
{
  char *nick, *ch, *op, *chg, *msg;
  char s[UHOSTLEN], buf[511];
  char ms2[3];
  int z;
  struct userrec *u;
  memberlist *m;
  struct chanset_t *chan;

  strncpy(buf, origmsg, 510);
  buf[510] = 0;
  msg = buf;
  /* Usermode changes? */
  if (msg[0] && (strchr(CHANMETA, msg[0]) != NULL)) {
    ch = newsplit(&msg);
    chg = newsplit(&msg);
    reversing = 0;
    chan = findchan(ch);
    if (!chan) {
      putlog(LOG_MISC, "*", CHAN_FORCEJOIN, ch);
      dprintf(DP_SERVER, "PART %s\n", ch);
    } else if (channel_active(chan) || channel_pending(chan)) {
      z = strlen(msg);
      if (msg[--z] == ' ')      /* I hate cosmetic bugs :P -poptix */
        msg[z] = 0;
      putlog(LOG_MODES, chan->dname, "%s: mode change '%s %s' by %s", ch, chg,
             msg, from);
      u = get_user_by_host(from);
      get_user_flagrec(u, &user, ch);
      nick = splitnick(&from);
      m = ismember(chan, nick);
      if (m)
        m->last = now;
      if (m && channel_active(chan) && (me_op(chan) || (me_halfop(chan) &&
          !chan_hasop(m))) && !(glob_friend(user) || chan_friend(user) ||
          (channel_dontkickops(chan) && (chan_op(user) || (glob_op(user) &&
          !chan_deop(user))))) && !match_my_nick(nick)) {
        if (chan_fakeop(m) || chan_fakehalfop(m)) {
          putlog(LOG_MODES, ch, CHAN_FAKEMODE, ch);
          dprintf(DP_MODE, "KICK %s %s :%s\n", ch, nick, CHAN_FAKEMODE_KICK);
          m->flags |= SENTKICK;
          reversing = 1;
        } else if (!chan_hasop(m) && !chan_hashalfop(m) &&
                 !channel_nodesynch(chan)) {
          putlog(LOG_MODES, ch, CHAN_DESYNCMODE, ch);
          dprintf(DP_MODE, "KICK %s %s :%s\n", ch, nick, CHAN_DESYNCMODE_KICK);
          m->flags |= SENTKICK;
          reversing = 1;
        }
      }
      ms2[0] = '+';
      ms2[2] = 0;
      while ((ms2[1] = *chg)) {
        int todo = 0;

        switch (*chg) {
        case '+':
          ms2[0] = '+';
          break;
        case '-':
          ms2[0] = '-';
          break;
        case 'i':
          todo = CHANINV;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'p':
          todo = CHANPRIV;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 's':
          todo = CHANSEC;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'm':
          todo = CHANMODER;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'c':
          todo = CHANNOCLR;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'C':
          todo = CHANNOCTCP;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'R':
          todo = CHANREGON;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'M':
          todo = CHANMODREG;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'r':
          todo = CHANLONLY;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'D':
          todo = CHANDELJN;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'u':
          todo = CHANSTRIP;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'N':
          todo = CHANNONOTC;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'T':
          todo = CHANNOAMSG;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'd':
          todo = CHANINVIS;
          break;
        case 't':
          todo = CHANTOPIC;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'n':
          todo = CHANNOMSG;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'a':
          todo = CHANANON;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'q':
          todo = CHANQUIET;
          if (!nick[0] && bounce_modes)
            reversing = 1;
          break;
        case 'l':
          if (!nick[0] && bounce_modes)
            reversing = 1;
          if (ms2[0] == '-') {
            check_tcl_mode(nick, from, u, chan->dname, ms2, "");
            /* The Tcl proc might have modified/removed the chan or user */
            if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
              return 0;
            if (channel_active(chan)) {
              if (reversing && (chan->channel.maxmembers != 0)) {
                simple_sprintf(s, "%d", chan->channel.maxmembers);
                add_mode(chan, '+', 'l', s);
              } else if ((chan->limit_prot != 0) && !glob_master(user) &&
                         !chan_master(user) && !match_my_nick(nick)) {
                simple_sprintf(s, "%d", chan->limit_prot);
                add_mode(chan, '+', 'l', s);
              }
            }
            chan->channel.maxmembers = 0;
          } else {
            op = newsplit(&msg);
            fixcolon(op);
            if (op == '\0')
              break;
            chan->channel.maxmembers = atoi(op);
            check_tcl_mode(nick, from, u, chan->dname, ms2,
                           int_to_base10(chan->channel.maxmembers));
            /* The Tcl proc might have modified/removed the chan or user */
            if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
              return 0;
            if (channel_pending(chan))
              break;
            if ((reversing && !(chan->mode_pls_prot & CHANLIMIT)) ||
                ((chan->mode_mns_prot & CHANLIMIT) && !glob_master(user) &&
                !chan_master(user)))
              add_mode(chan, '-', 'l', "");
            if ((chan->limit_prot != chan->channel.maxmembers) &&
                (chan->mode_pls_prot & CHANLIMIT) && (chan->limit_prot != 0) &&
                !glob_master(user) && !chan_master(user)) {
              simple_sprintf(s, "%d", chan->limit_prot);
              add_mode(chan, '+', 'l', s);
            }
          }
          break;
        case 'k':
          if (ms2[0] == '+')
            chan->channel.mode |= CHANKEY;
          else
            chan->channel.mode &= ~CHANKEY;
          op = newsplit(&msg);
          fixcolon(op);
          if (op == '\0') {
            break;
          }
          check_tcl_mode(nick, from, u, chan->dname, ms2, op);
          /* The Tcl proc might have modified/removed the chan or user */
          if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
            return 0;
          if (ms2[0] == '+') {
            set_key(chan, op);
            if (channel_active(chan))
              got_key(chan, nick, from, op);
          } else {
            if (channel_active(chan)) {
              if (reversing && chan->channel.key[0])
                add_mode(chan, '+', 'k', chan->channel.key);
              else if (chan->key_prot[0] && !glob_master(user) &&
                       !chan_master(user) && !match_my_nick(nick))
                add_mode(chan, '+', 'k', chan->key_prot);
            }
            set_key(chan, NULL);
          }
          break;
        case 'o':
          op = newsplit(&msg);
          fixcolon(op);
          if (ms2[0] == '+')
            got_op(chan, nick, from, op, u, &user);
          else
            got_deop(chan, nick, from, op, u);
          break;
        case 'h':
          op = newsplit(&msg);
          fixcolon(op);
          if (ms2[0] == '+')
            got_halfop(chan, nick, from, op, u, &user);
          else
            got_dehalfop(chan, nick, from, op, u);
          break;
        case 'v':
          op = newsplit(&msg);
          fixcolon(op);
          m = ismember(chan, op);
          if (!m) {
            if (channel_pending(chan))
              break;
            putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, op);
            chan->status |= CHAN_PEND;
            refresh_who_chan(chan->name);
          } else {
            simple_sprintf(s, "%s!%s", m->nick, m->userhost);
            get_user_flagrec(m->user ? m->user : get_user_by_host(s),
                             &victim, chan->dname);
            if (ms2[0] == '+') {
              m->flags &= ~SENTVOICE;
              m->flags |= CHANVOICE;
              check_tcl_mode(nick, from, u, chan->dname, ms2, op);
              if (!(chan = modebind_refresh(ch, from, &user, s, &victim)))
                return 0;
              if (channel_active(chan) && !glob_master(user) &&
                  !chan_master(user) && !match_my_nick(nick)) {
                if (chan_quiet(victim) ||
                    (glob_quiet(victim) && !chan_voice(victim)))
                  add_mode(chan, '-', 'v', op);
                else if (reversing)
                  add_mode(chan, '-', 'v', op);
              }
            } else {
              m->flags &= ~SENTDEVOICE;
              m->flags &= ~CHANVOICE;
              check_tcl_mode(nick, from, u, chan->dname, ms2, op);
              if (!(chan = modebind_refresh(ch, from, &user, s, &victim)))
                return 0;
              if (channel_active(chan) && !glob_master(user) &&
                  !chan_master(user) && !match_my_nick(nick)) {
                if ((channel_autovoice(chan) && !chan_quiet(victim) &&
                    (chan_voice(victim) || glob_voice(victim))) ||
                    (!chan_quiet(victim) && (glob_gvoice(victim) ||
                    chan_gvoice(victim))))
                  add_mode(chan, '+', 'v', op);
                else if (reversing)
                  add_mode(chan, '+', 'v', op);
              }
            }
          }
          break;
        case 'b':
          op = newsplit(&msg);
          fixcolon(op);
          if (ms2[0] == '+')
            got_ban(chan, nick, from, op, ch, u);
          else
            got_unban(chan, nick, from, op, ch, u);
          break;
        case 'e':
          op = newsplit(&msg);
          fixcolon(op);
          if (ms2[0] == '+')
            got_exempt(chan, nick, from, op, ch, u);
          else
            got_unexempt(chan, nick, from, op, ch, u);
          break;
        case 'I':
          op = newsplit(&msg);
          fixcolon(op);
          if (ms2[0] == '+')
            got_invite(chan, nick, from, op, ch, u);
          else
            got_uninvite(chan, nick, from, op, ch, u);
          break;
        }
        if (todo) {
          check_tcl_mode(nick, from, u, chan->dname, ms2, "");
          if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
            return 0;
          if (ms2[0] == '+')
            chan->channel.mode |= todo;
          else
            chan->channel.mode &= ~todo;
          if (channel_active(chan)) {
            if ((((ms2[0] == '+') && (chan->mode_mns_prot & todo)) ||
                ((ms2[0] == '-') && (chan->mode_pls_prot & todo))) &&
                !glob_master(user) && !chan_master(user) &&
                !match_my_nick(nick))
              add_mode(chan, ms2[0] == '+' ? '-' : '+', *chg, "");
            else if (reversing && ((ms2[0] == '+') ||
                     (chan->mode_pls_prot & todo)) && ((ms2[0] == '-') ||
                     (chan->mode_mns_prot & todo)))
              add_mode(chan, ms2[0] == '+' ? '-' : '+', *chg, "");
          }
        }
        chg++;
      }
      if (!me_op(chan) && !nick[0])
        chan->status |= CHAN_ASKEDMODES;
    }
  }
  return 0;
}
Exemplo n.º 11
0
static void tell_invites(int idx, int show_inact, char *match)
{
  int k = 1;
  char *chname;
  struct chanset_t *chan = NULL;
  maskrec *u;

  /* Was a channel given? */
  if (match[0]) {
    chname = newsplit(&match);
    if (chname[0] && strchr(CHANMETA, chname[0])) {
      chan = findchan_by_dname(chname);
      if (!chan) {
        dprintf(idx, "%s.\n", CHAN_NOSUCH);
        return;
      }
    } else
      match = chname;
  }

  /* don't return here, we want to show global invites even if no chan */
  if (!chan && !(chan = findchan_by_dname(dcc[idx].u.chat->con_chan)) &&
      !(chan = chanset))
    chan = NULL;

  if (chan && show_inact)
    dprintf(idx, "%s:   (! = %s %s)\n", INVITES_GLOBAL,
            MODES_NOTACTIVE, chan->dname);
  else
    dprintf(idx, "%s:\n", INVITES_GLOBAL);
  for (u = global_invites; u; u = u->next) {
    if (match[0]) {
      if ((match_addr(match, u->mask)) ||
          (wild_match(match, u->desc)) || (wild_match(match, u->user)))
        display_invite(idx, k, u, chan, 1);
      k++;
    } else
      display_invite(idx, k++, u, chan, show_inact);
  }
  if (chan) {
    if (show_inact)
      dprintf(idx, "%s %s:   (! = %s, * = %s)\n", INVITES_BYCHANNEL,
              chan->dname, MODES_NOTACTIVE2, MODES_NOTBYBOT);
    else
      dprintf(idx, "%s %s:  (* = %s)\n",
              INVITES_BYCHANNEL, chan->dname, MODES_NOTBYBOT);
    for (u = chan->invites; u; u = u->next) {
      if (match[0]) {
        if ((match_addr(match, u->mask)) ||
            (wild_match(match, u->desc)) || (wild_match(match, u->user)))
          display_invite(idx, k, u, chan, 1);
        k++;
      } else
        display_invite(idx, k++, u, chan, show_inact);
    }
    if (chan->status & CHAN_ACTIVE) {
      masklist *i;
      char s[UHOSTLEN], *s1, *s2, fill[256];
      int min, sec;

      for (i = chan->channel.invite; i && i->mask[0]; i = i->next) {
        if ((!u_equals_mask(global_invites, i->mask)) &&
            (!u_equals_mask(chan->invites, i->mask))) {
          strcpy(s, i->who);
          s2 = s;
          s1 = splitnick(&s2);
          if (s1[0])
            sprintf(fill, "%s (%s!%s)", i->mask, s1, s2);
          else
            sprintf(fill, "%s (server %s)", i->mask, s2);
          if (i->timer != 0) {
            min = (now - i->timer) / 60;
            sec = (now - i->timer) - (min * 60);
            sprintf(s, " (active %02d:%02d)", min, sec);
            strcat(fill, s);
          }
          if ((!match[0]) || (match_addr(match, i->mask)))
            dprintf(idx, "* [%3d] %s\n", k, fill);
          k++;
        }
      }
    }
  }
  if (k == 1)
    dprintf(idx, "(There are no invites, permanent or otherwise.)\n");
  if ((!show_inact) && (!match[0]))
    dprintf(idx, "%s.\n", INVITES_USEINVITESALL);
}