Pull ThiefMaster's patch-3..5.
authorMichael Poole <mdpoole@troilus.org>
Fri, 27 Oct 2006 00:21:32 +0000 (00:21 +0000)
committerMichael Poole <mdpoole@troilus.org>
Fri, 27 Oct 2006 00:21:32 +0000 (00:21 +0000)
Patches applied:

 * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--base-0
   tag of srvx@srvx.net--2006/srvx--devo--1.3--patch-58

 * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-3
   Implement complete remote whois.

 * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-4
   Improve override logging and ignore godmode in !trim.

 * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-5
   Announce ounregisters to staff via Global.
git-archimport-id: srvx@srvx.net--2006/srvx--devo--1.3--patch-63

ChangeLog
src/chanserv.c
src/hash.h
src/modcmd.c
src/modcmd.h
src/nickserv.c
src/opserv.c
src/proto-p10.c
src/proto.h

index 2b0b2ab8630ba03f73d328004ee0289a246d11be..bba3689e3cce57dce3775df1f85bae1358612b6e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,38 @@
 # arch-tag: automatic-ChangeLog--srvx@srvx.net--2006/srvx--devo--1.3
 #
 
+2006-10-27 00:21:32 GMT        Michael Poole <mdpoole@troilus.org>     patch-63
+
+    Summary:
+      Pull ThiefMaster's patch-3..5.
+    Revision:
+      srvx--devo--1.3--patch-63
+
+    Patches applied:
+    
+     * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--base-0
+       tag of srvx@srvx.net--2006/srvx--devo--1.3--patch-58
+    
+     * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-3
+       Implement complete remote whois.
+    
+     * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-4
+       Improve override logging and ignore godmode in !trim.
+    
+     * thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-5
+       Announce ounregisters to staff via Global.
+
+    modified files:
+     ChangeLog src/chanserv.c src/hash.h src/modcmd.c src/modcmd.h
+     src/nickserv.c src/opserv.c src/proto-p10.c src/proto.h
+
+    new patches:
+     thiefmaster@gamesurge.net--2006/srvx--devo--1.3--base-0
+     thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-3
+     thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-4
+     thiefmaster@gamesurge.net--2006/srvx--devo--1.3--patch-5
+
+
 2006-10-26 23:44:10 GMT        Michael Poole <mdpoole@troilus.org>     patch-62
 
     Summary:
index d2ab69a57326699069df42426fdfeac0d890aaf0..9ee271b6f58fcb425488ffdbdd1bd36d7c06bdbf 100644 (file)
@@ -2213,9 +2213,9 @@ static CHANSERV_FUNC(cmd_opchan)
 static CHANSERV_FUNC(cmd_adduser)
 {
     struct userData *actee;
-    struct userData *actor;
+    struct userData *actor, *real_actor;
     struct handle_info *handle;
-    unsigned short access;
+    unsigned short access, override = 0;
 
     REQUIRE_PARAMS(3);
 
@@ -2233,16 +2233,22 @@ static CHANSERV_FUNC(cmd_adduser)
     }
 
     actor = GetChannelUser(channel->channel_info, user->handle_info);
+    real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
+
     if(actor->access <= access)
     {
        reply("CSMSG_NO_BUMP_ACCESS");
        return 0;
     }
 
+    // Trying to add someone with equal/more access
+    if (!real_actor || real_actor->access <= access)
+        override = CMD_LOG_OVERRIDE;
+
     if(!(handle = modcmd_get_handle_info(user, argv[1])))
         return 0;
 
-    if((actee = GetTrueChannelAccess(channel->channel_info, handle)))
+    if((actee = GetChannelAccess(channel->channel_info, handle)))
     {
        reply("CSMSG_USER_EXISTS", handle->handle, channel->name, actee->access);
        return 0;
@@ -2251,20 +2257,21 @@ static CHANSERV_FUNC(cmd_adduser)
     actee = add_channel_user(channel->channel_info, handle, access, 0, NULL);
     scan_user_presence(actee, NULL);
     reply("CSMSG_ADDED_USER", handle->handle, channel->name, access);
-    return 1;
+    return 1 | override;
 }
 
 static CHANSERV_FUNC(cmd_clvl)
 {
     struct handle_info *handle;
     struct userData *victim;
-    struct userData *actor;
-    unsigned short new_access;
+    struct userData *actor, *real_actor;
+    unsigned short new_access, override = 0;
     int privileged = IsHelping(user) && ((user->handle_info->opserv_level >= chanserv_conf.nodelete_level) || !IsProtected(channel->channel_info));
 
     REQUIRE_PARAMS(3);
 
     actor = GetChannelUser(channel->channel_info, user->handle_info);
+    real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
 
     if(!(handle = modcmd_get_handle_info(user, argv[1])))
         return 0;
@@ -2301,22 +2308,32 @@ static CHANSERV_FUNC(cmd_clvl)
        return 0;
     }
 
+    // Trying to clvl a equal/higher user
+    if(!real_actor || (real_actor->access <= victim->access && handle != user->handle_info))
+        override = CMD_LOG_OVERRIDE;
+    // Trying to clvl someone to equal/higher access
+    if(!real_actor || new_access >= real_actor->access)
+        override = CMD_LOG_OVERRIDE;
+    // Helpers clvling themselves get caught by the "clvl someone to equal/higher access" check.
+    // If they lower their own access it's not a big problem.
+
     victim->access = new_access;
     reply("CSMSG_CHANGED_ACCESS", handle->handle, new_access, channel->name);
-    return 1;
+    return 1 | override;
 }
 
 static CHANSERV_FUNC(cmd_deluser)
 {
     struct handle_info *handle;
     struct userData *victim;
-    struct userData *actor;
-    unsigned short access;
+    struct userData *actor, *real_actor;
+    unsigned short access, override = 0;
     char *chan_name;
 
     REQUIRE_PARAMS(2);
 
     actor = GetChannelUser(channel->channel_info, user->handle_info);
+    real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
 
     if(!(handle = modcmd_get_handle_info(user, argv[argc-1])))
         return 0;
@@ -2352,19 +2369,25 @@ static CHANSERV_FUNC(cmd_deluser)
        return 0;
     }
 
+    // If people delete themselves it is an override, but they could've used deleteme so we don't log it as an override
+    if(!real_actor || (real_actor->access <= victim->access && real_actor != victim))
+        override = CMD_LOG_OVERRIDE;
+
     chan_name = strdup(channel->name);
     del_channel_user(victim, 1);
     reply("CSMSG_DELETED_USER", handle->handle, access, chan_name);
     free(chan_name);
-    return 1;
+    return 1 | override;
 }
 
 static int
 cmd_mdel_user(struct userNode *user, struct chanNode *channel, unsigned short min_access, unsigned short max_access, char *mask, struct svccmd *cmd)
 {
-    struct userData *actor, *uData, *next;
+    struct userData *actor, *real_actor, *uData, *next;
+    unsigned int override = 0;
 
     actor = GetChannelUser(channel->channel_info, user->handle_info);
+    real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
 
     if(min_access > max_access)
     {
@@ -2378,6 +2401,9 @@ cmd_mdel_user(struct userNode *user, struct chanNode *channel, unsigned short mi
        return 0;
     }
 
+    if(!real_actor || real_actor->access <= max_access)
+        override = CMD_LOG_OVERRIDE;
+
     for(uData = channel->channel_info->users; uData; uData = next)
     {
        next = uData->next;
@@ -2389,7 +2415,7 @@ cmd_mdel_user(struct userNode *user, struct chanNode *channel, unsigned short mi
     }
 
     reply("CSMSG_DELETED_USERS", mask, min_access, max_access, channel->name);
-    return 1;
+    return 1 | override;
 }
 
 static CHANSERV_FUNC(cmd_mdelowner)
@@ -2451,14 +2477,14 @@ cmd_trim_users(struct userNode *user, struct chanNode *channel, unsigned short m
     unsigned int count;
     time_t limit;
 
-    actor = GetChannelUser(channel->channel_info, user->handle_info);
+    actor = GetChannelAccess(channel->channel_info, user->handle_info);
     if(min_access > max_access)
     {
         send_message(user, chanserv, "CSMSG_BAD_RANGE", min_access, max_access);
         return 0;
     }
 
-    if((actor->access <= max_access) && !IsHelping(user))
+    if(!actor || actor->access <= max_access)
     {
        send_message(user, chanserv, "CSMSG_NO_ACCESS");
        return 0;
@@ -4128,10 +4154,12 @@ static CHANSERV_FUNC(cmd_peek)
 static MODCMD_FUNC(cmd_wipeinfo)
 {
     struct handle_info *victim;
-    struct userData *ud, *actor;
+    struct userData *ud, *actor, *real_actor;
+    unsigned int override = 0;
 
     REQUIRE_PARAMS(2);
     actor = GetChannelUser(channel->channel_info, user->handle_info);
+    real_actor = GetChannelAccess(channel->channel_info, user->handle_info);
     if(!(victim = modcmd_get_handle_info(user, argv[1])))
         return 0;
     if(!(ud = GetTrueChannelAccess(channel->channel_info, victim)))
@@ -4144,11 +4172,13 @@ static MODCMD_FUNC(cmd_wipeinfo)
         reply("MSG_USER_OUTRANKED", victim->handle);
         return 0;
     }
+    if((ud->access >= real_actor->access) && (ud != real_actor))
+        override = CMD_LOG_OVERRIDE;
     if(ud->info)
         free(ud->info);
     ud->info = NULL;
     reply("CSMSG_WIPED_INFO_LINE", argv[1], channel->name);
-    return 1;
+    return 1 | override;
 }
 
 static CHANSERV_FUNC(cmd_resync)
@@ -5597,11 +5627,13 @@ static CHANSERV_FUNC(cmd_giveownership)
 static CHANSERV_FUNC(cmd_suspend)
 {
     struct handle_info *hi;
-    struct userData *self, *target;
+    struct userData *self, *real_self, *target;
+    unsigned int override = 0;
 
     REQUIRE_PARAMS(2);
     if(!(hi = modcmd_get_handle_info(user, argv[1]))) return 0;
     self = GetChannelUser(channel->channel_info, user->handle_info);
+    real_self = GetChannelAccess(channel->channel_info, user->handle_info);
     if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
     {
         reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
@@ -5622,19 +5654,23 @@ static CHANSERV_FUNC(cmd_suspend)
         target->present = 0;
         target->seen = now;
     }
+    if(!real_self || target->access >= real_self->access)
+        override = CMD_LOG_OVERRIDE;
     target->flags |= USER_SUSPENDED;
     reply("CSMSG_USER_SUSPENDED", hi->handle, channel->name);
-    return 1;
+    return 1 | override;
 }
 
 static CHANSERV_FUNC(cmd_unsuspend)
 {
     struct handle_info *hi;
-    struct userData *self, *target;
+    struct userData *self, *real_self, *target;
+    unsigned int override = 0;
 
     REQUIRE_PARAMS(2);
     if(!(hi = modcmd_get_handle_info(user, argv[1]))) return 0;
     self = GetChannelUser(channel->channel_info, user->handle_info);
+    real_self = GetChannelAccess(channel->channel_info, user->handle_info);
     if(!(target = GetTrueChannelAccess(channel->channel_info, hi)))
     {
         reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name);
@@ -5650,10 +5686,12 @@ static CHANSERV_FUNC(cmd_unsuspend)
         reply("CSMSG_NOT_SUSPENDED", hi->handle);
         return 0;
     }
+    if(!real_self || target->access >= real_self->access)
+        override = CMD_LOG_OVERRIDE;
     target->flags &= ~USER_SUSPENDED;
     scan_user_presence(target, NULL);
     reply("CSMSG_USER_UNSUSPENDED", hi->handle, channel->name);
-    return 1;
+    return 1 | override;
 }
 
 static MODCMD_FUNC(cmd_deleteme)
index f1b9f489bcaa2adc09a1a23905d426158b531b7a..84bb8a3787ea3e3236b3a67cb49175063a6969f1 100644 (file)
@@ -51,6 +51,7 @@
 #define FLAGS_DEAF             0x0020 /* deaf +d */
 #define FLAGS_SERVICE          0x0040 /* cannot be kicked, killed or deoped +k */
 #define FLAGS_GLOBAL           0x0080 /* receives global messages +g */
+#define FLAGS_NOCHAN           0x0100 /* hide channels in whois +n */
 #define FLAGS_PERSISTENT       0x0200 /* for reserved nicks, this isn't just one-shot */
 #define FLAGS_GAGGED           0x0400 /* for gagged users */
 #define FLAGS_AWAY             0x0800 /* for away users */
 #define IsDeaf(x)               ((x)->modes & FLAGS_DEAF)
 #define IsInvisible(x)          ((x)->modes & FLAGS_INVISIBLE)
 #define IsGlobal(x)             ((x)->modes & FLAGS_GLOBAL)
+#define IsNoChan(x)             ((x)->modes & FLAGS_NOCHAN)
 #define IsWallOp(x)             ((x)->modes & FLAGS_WALLOP)
 #define IsGagged(x)             ((x)->modes & FLAGS_GAGGED)
-#define IsPersistent(x)         ((x)->modes & FLAGS_PERSISTENT) 
+#define IsPersistent(x)         ((x)->modes & FLAGS_PERSISTENT)
 #define IsAway(x)               ((x)->modes & FLAGS_AWAY)
 #define IsStamped(x)            ((x)->modes & FLAGS_STAMPED)
 #define IsHiddenHost(x)         ((x)->modes & FLAGS_HIDDEN_HOST)
index f1720f2e1b7ae76b16fca6d68be9542bae4cf3ca..e3b51a2e780fdee1e86dfa767828ed574277ce10 100644 (file)
@@ -626,7 +626,7 @@ int
 svccmd_invoke_argv(struct userNode *user, struct service *service, struct chanNode *channel, unsigned int argc, char *argv[], unsigned int server_qualified) {
     extern struct userNode *chanserv;
     struct svccmd *cmd;
-    unsigned int cmd_arg, perms, flags, options;
+    unsigned int cmd_arg, perms, flags, options, result;
     char channel_name[CHANNELLEN+1];
 
     /* First check pubcmd for the channel. */
@@ -737,11 +737,13 @@ svccmd_invoke_argv(struct userNode *user, struct service *service, struct chanNo
         safestrncpy(channel_name, channel->name, sizeof(channel_name));
     else
         channel_name[0] = 0;
-    if (!cmd->command->func(user, channel, argc, argv, cmd))
+    if (!(result = cmd->command->func(user, channel, argc, argv, cmd)))
         return 0;
     if (!(flags & MODCMD_NO_LOG)) {
         enum log_severity slvl;
-        if (perms & ACTION_STAFF)
+        if (result & CMD_LOG_OVERRIDE)
+            slvl = LOG_OVERRIDE;
+        else if ((perms & ACTION_STAFF) || (result & CMD_LOG_STAFF))
             slvl = LOG_STAFF;
         else if (perms & ACTION_OVERRIDE)
             slvl = LOG_OVERRIDE;
index 3523356799f6502f5269e158913078efb1ab3b94..b65c235b4ede87efb2ed26b82e5aa06b8eb2e88d 100644 (file)
@@ -75,6 +75,12 @@ DECLARE_LIST(module_list, struct module*);
 #define SVCCMD_DEBIT                  0x000002
 #define SVCCMD_NOISY                  0x000004
 
+/* We do not use constants for 0 (no logging) and 1 (regular logging) as those
+ * are used very often and are intuitive enough.
+ */
+#define CMD_LOG_STAFF       0x02
+#define CMD_LOG_OVERRIDE    0x04
+
 /* Modularized commands work like this:
  *
  * Modules define commands.  Services contain "bindings" of those
index 869b4352e42bc0ba39080e24300670622d4bf91f..7ac7c2e7557ce5da455e35dd2b1a60e5c8567595 100644 (file)
@@ -1217,7 +1217,7 @@ static NICKSERV_FUNC(cmd_register)
         nickserv_make_cookie(user, hi, ACTIVATION, hi->passwd);
 
     /* Set registering flag.. */
-    user->modes |= FLAGS_REGISTERING; 
+    user->modes |= FLAGS_REGISTERING;
 
     return 1;
 }
@@ -2593,10 +2593,13 @@ static NICKSERV_FUNC(cmd_unregister)
 static NICKSERV_FUNC(cmd_ounregister)
 {
     struct handle_info *hi;
+    char reason[MAXLEN];
 
     NICKSERV_MIN_PARMS(2);
     if (!(hi = get_victim_oper(user, argv[1])))
         return 0;
+    snprintf(reason, sizeof(reason), "%s unregistered account %s.", user->handle_info->handle, hi->handle);
+    global_message(MESSAGE_RECIPIENT_STAFF, reason);
     nickserv_unregister_handle(hi, user);
     return 1;
 }
index 7a768a85eecce5adabfd64f90cb103df5529bf56..cd384a600ef40f8c3a35c5c2876f8527febc2a24 100644 (file)
@@ -1187,6 +1187,7 @@ static MODCMD_FUNC(cmd_whois)
        if (IsGlobal(target)) buffer[bpos++] = 'g';
        if (IsService(target)) buffer[bpos++] = 'k';
        if (IsDeaf(target)) buffer[bpos++] = 'd';
+       if (IsNoChan(target)) buffer[bpos++] = 'n';
         if (IsHiddenHost(target)) buffer[bpos++] = 'x';
         if (IsGagged(target)) buffer_cat(" (gagged)");
        if (IsRegistering(target)) buffer_cat(" (registered account)");
index 4d64e830b9a4a60062a93826c18fc9aaf817b504..e748474cc474bfd465585d69bbe48695aee29701 100644 (file)
@@ -475,6 +475,8 @@ irc_user(struct userNode *user)
             modes[modelen++] = 'd';
         if (IsGlobal(user))
             modes[modelen++] = 'g';
+        if (IsNoChan(user))
+            modes[modelen++] = 'n';
         if (IsHiddenHost(user))
             modes[modelen++] = 'x';
         modes[modelen] = 0;
@@ -888,6 +890,8 @@ static CMD_FUNC(cmd_whois)
 {
     struct userNode *from;
     struct userNode *who;
+    char buf[MAXLEN];
+    unsigned int i, mlen, len;
 
     if (argc < 3)
         return 0;
@@ -899,17 +903,67 @@ static CMD_FUNC(cmd_whois)
         irc_numeric(from, ERR_NOSUCHNICK, "%s@%s :No such nick", argv[2], self->name);
         return 1;
     }
-    if (IsHiddenHost(who) && !IsOper(from)) {
-        /* Just stay quiet. */
-        return 1;
+
+    if (IsFakeHost(who) && IsHiddenHost(who))
+        irc_numeric(from, RPL_WHOISUSER, "%s %s %s * :%s", who->nick, who->ident, who->fakehost, who->info);
+    else if (IsHiddenHost(who) && who->handle_info && hidden_host_suffix)
+        irc_numeric(from, RPL_WHOISUSER, "%s %s %s.%s * :%s", who->nick, who->ident, who->handle_info->handle, hidden_host_suffix, who->info);
+    else
+        irc_numeric(from, RPL_WHOISUSER, "%s %s %s * :%s", who->nick, who->ident, who->hostname, who->info);
+
+    if ((!IsService(who) && !IsNoChan(who)) || (from == who)) {
+        struct modeNode *mn;
+        mlen = strlen(self->name) + strlen(from->nick) + 12 + strlen(who->nick);
+        len = 0;
+        *buf = '\0';
+        for (i = 0; i < who->channels.used; i++)
+        {
+            mn = who->channels.list[i];
+
+            if (!IsOper(from) && (mn->channel->modes & (MODE_PRIVATE | MODE_SECRET)) && !GetUserMode(mn->channel, from))
+                continue;
+
+            if (len + strlen(mn->channel->name) + mlen > MAXLEN - 5)
+            {
+                irc_numeric(from, RPL_WHOISCHANNELS, "%s :%s", who->nick, buf);
+                *buf = '\0';
+                len = 0;
+            }
+
+            if (IsDeaf(who))
+                *(buf + len++) = '-';
+            if ((mn->channel->modes & (MODE_PRIVATE | MODE_SECRET)) && !GetUserMode(mn->channel, from))
+                *(buf + len++) = '*';
+            if (mn->modes & MODE_CHANOP)
+                *(buf + len++) = '@';
+            else if (mn->modes & MODE_VOICE)
+                *(buf + len++) = '+';
+
+            if (len)
+                *(buf + len) = '\0';
+            strcpy(buf + len, mn->channel->name);
+            len += strlen(mn->channel->name);
+            strcat(buf + len, " ");
+            len++;
+        }
+        if (buf[0] != '\0')
+            irc_numeric(from, RPL_WHOISCHANNELS, "%s :%s", who->nick, buf);
     }
-    irc_numeric(from, RPL_WHOISUSER, "%s %s %s * :%s", who->nick, who->ident, who->hostname, who->info);
-    if (his_servername && his_servercomment)
+
+    if (his_servername && his_servercomment && !IsOper(from) && from != who)
         irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, his_servername, his_servercomment);
     else
         irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, who->uplink->name, who->uplink->description);
+
+    if (IsAway(who))
+        irc_numeric(from, RPL_AWAY, "%s :Away", who->nick);
     if (IsOper(who))
-        irc_numeric(from, RPL_WHOISOPERATOR, "%s :is a megalomaniacal power hungry tyrant", who->nick);
+        irc_numeric(from, RPL_WHOISOPERATOR, "%s :%s", who->nick, IsLocal(who) ? "is a megalomaniacal power hungry tyrant" : "is an IRC Operator");
+    if (who->handle_info)
+        irc_numeric(from, RPL_WHOISACCOUNT, "%s %s :is logged in as", who->nick, who->handle_info->handle);
+    if (IsHiddenHost(who) && who->handle_info && (IsOper(from) || from == who))
+        irc_numeric(from, RPL_WHOISACTUALLY, "%s %s@%s %s :Actual user@host, Actual IP", who->nick, who->ident, who->hostname, irc_ntoa(&who->ip));
+
     irc_numeric(from, RPL_ENDOFWHOIS, "%s :End of /WHOIS list", who->nick);
     return 1;
 }
@@ -2167,6 +2221,7 @@ void mod_usermode(struct userNode *user, const char *mode_change) {
        case 'd': do_user_mode(FLAGS_DEAF); break;
        case 'k': do_user_mode(FLAGS_SERVICE); break;
        case 'g': do_user_mode(FLAGS_GLOBAL); break;
+       case 'n': do_user_mode(FLAGS_NOCHAN); break;
         case 'x': do_user_mode(FLAGS_HIDDEN_HOST); break;
         case 'r':
             if (*word) {
@@ -2709,10 +2764,10 @@ unreg_privmsg_func(struct userNode *user, privmsg_func_t handler)
 
     memset(privmsg_funcs+user->num_local, 0, sizeof(privmsg_func_t));
 
-    for (x = user->num_local+1; x < num_privmsg_funcs; x++) 
+    for (x = user->num_local+1; x < num_privmsg_funcs; x++)
        memmove(privmsg_funcs+x-1, privmsg_funcs+x, sizeof(privmsg_func_t));
-    
-    privmsg_funcs = realloc(privmsg_funcs, num_privmsg_funcs*sizeof(privmsg_func_t)); 
+
+    privmsg_funcs = realloc(privmsg_funcs, num_privmsg_funcs*sizeof(privmsg_func_t));
     num_privmsg_funcs--;
 }
 
index 451c889f365dbc4dafb774731b48b4fb80b169ab..6f4dccf1274bfefc1f04c0a38d8567882e05cba6 100644 (file)
@@ -158,10 +158,14 @@ void irc_numeric(struct userNode *user, unsigned int num, const char *format, ..
 #define RPL_ENDOFSTATS          219
 #define RPL_STATSUPTIME         242
 #define RPL_MAXCONNECTIONS      250
+#define RPL_AWAY                301
 #define RPL_WHOISUSER           311
 #define RPL_WHOISSERVER         312
 #define RPL_WHOISOPERATOR       313
 #define RPL_ENDOFWHOIS          318
+#define RPL_WHOISCHANNELS       319
+#define RPL_WHOISACCOUNT        330
+#define RPL_WHOISACTUALLY       338
 #define ERR_NOSUCHNICK          401
 
 /* stuff originally from other headers that is really protocol-specific */