Initial oplevel support.
authorMichael Poole <mdpoole@troilus.org>
Sat, 8 Oct 2005 14:56:31 +0000 (14:56 +0000)
committerMichael Poole <mdpoole@troilus.org>
Sat, 8 Oct 2005 14:56:31 +0000 (14:56 +0000)
src/proto-p10.c: Fix a few bugs and compile errors in oplevel code.

Patches applied:

 * sp@gamesurge.net--2005/srvx--sp--1.3--patch-1
   Oplevel support

 * sp@gamesurge.net--2005/srvx--sp--1.3--patch-2
   Oplevel support (part 2)
git-archimport-id: srvx@srvx.net--2005-srvx/srvx--devo--1.3--patch-29

ChangeLog
src/hash.c
src/hash.h
src/opserv.c
src/proto-common.c
src/proto-p10.c
src/proto.h

index e9a3926f69206b524e2ee5c8586155a2c94375b7..11f4bf2edc2b5de00eb47069bb0876b3a419f0cb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,32 @@
 # arch-tag: automatic-ChangeLog--srvx@srvx.net--2005-srvx/srvx--devo--1.3
 #
 
+2005-10-08 14:56:31 GMT        Michael Poole <mdpoole@troilus.org>     patch-29
+
+    Summary:
+      Initial oplevel support.
+    Revision:
+      srvx--devo--1.3--patch-29
+
+    src/proto-p10.c: Fix a few bugs and compile errors in oplevel code.
+    
+    Patches applied:
+    
+     * sp@gamesurge.net--2005/srvx--sp--1.3--patch-1
+       Oplevel support
+    
+     * sp@gamesurge.net--2005/srvx--sp--1.3--patch-2
+       Oplevel support (part 2)
+
+    modified files:
+     ChangeLog src/hash.c src/hash.h src/opserv.c
+     src/proto-common.c src/proto-p10.c src/proto.h
+
+    new patches:
+     sp@gamesurge.net--2005/srvx--sp--1.3--patch-1
+     sp@gamesurge.net--2005/srvx--sp--1.3--patch-2
+
+
 2005-10-08 14:33:12 GMT        Michael Poole <mdpoole@troilus.org>     patch-28
 
     Summary:
index c60ec57bdd4e4eb8eff65f181a08014235f4c6a6..eff19d1e28a70f4c9635221403984863a759e198 100644 (file)
@@ -289,6 +289,8 @@ wipeout_channel(struct chanNode *cNode, time_t new_time, char **modes, unsigned
     unsigned int orig_limit;
     chan_mode_t orig_modes;
     char orig_key[KEYLEN+1];
+    char orig_apass[KEYLEN+1];
+    char orig_upass[KEYLEN+1];
     unsigned int nn, argc;
 
     /* nuke old topic */
@@ -300,6 +302,8 @@ wipeout_channel(struct chanNode *cNode, time_t new_time, char **modes, unsigned
     orig_modes = cNode->modes;
     orig_limit = cNode->limit;
     strcpy(orig_key, cNode->key);
+    strcpy(orig_upass, cNode->upass);
+    strcpy(orig_apass, cNode->apass);
     cNode->modes = 0;
     mod_chanmode(NULL, cNode, modes, modec, 0);
     cNode->timestamp = new_time;
@@ -323,6 +327,8 @@ wipeout_channel(struct chanNode *cNode, time_t new_time, char **modes, unsigned
         change->modes_set = orig_modes;
         change->new_limit = orig_limit;
         strcpy(change->new_key, orig_key);
+        strcpy(change->new_upass, orig_upass);
+        strcpy(change->new_apass, orig_apass);
         for (nn = argc = 0; nn < cNode->members.used; ++nn) {
             struct modeNode *mn = cNode->members.list[nn];
             if ((mn->modes & MODE_CHANOP) && IsService(mn->user) && IsLocal(mn->user)) {
@@ -475,7 +481,8 @@ AddChannelUser(struct userNode *user, struct chanNode* channel)
        modeList_append(&user->channels, mNode);
 
         if (channel->members.used == 1
-            && !(channel->modes & MODE_REGISTERED))
+            && !(channel->modes & MODE_REGISTERED)
+            && !(channel->modes & MODE_APASS))
             mNode->modes |= MODE_CHANOP;
 
         for (n=0; n<jf_used; n++) {
@@ -564,7 +571,9 @@ DelChannelUser(struct userNode* user, struct chanNode* channel, const char *reas
     /* free memory */
     free(mNode);
 
-    if (!deleting && !channel->members.used && !channel->locks && !(channel->modes & MODE_REGISTERED))
+    /* A single check for APASS only should be enough here */
+    if (!deleting && !channel->members.used && !channel->locks 
+        && !(channel->modes & MODE_REGISTERED) && !(channel->modes & MODE_APASS))
         DelChannel(channel);
 }
 
index 975ccf44ad355de9d487a9fecf33ffc14b64393e..2ecd74981c3002b6a6c81233db95b6f0f86fe258 100644 (file)
@@ -41,6 +41,8 @@
 #define MODE_NOCOLORS           0x2000 /* +c */
 #define MODE_NOCTCPS            0x4000 /* +C */
 #define MODE_REGISTERED         0x8000 /* Bahamut +r */
+#define MODE_APASS             0x10000 /* +A adminpass */
+#define MODE_UPASS             0x20000 /* +U userpass */
 #define MODE_REMOVE             0x80000000
 
 #define FLAGS_OPER             0x0001 /* Operator +O */
@@ -125,6 +127,8 @@ struct chanNode {
     chan_mode_t modes;
     unsigned int limit, locks;
     char key[KEYLEN + 1];
+    char upass[KEYLEN + 1];
+    char apass[KEYLEN + 1];
     time_t timestamp; /* creation time */
 
     char topic[TOPICLEN + 1];
@@ -152,6 +156,7 @@ struct modeNode {
     struct chanNode *channel;
     struct userNode *user;
     long modes;
+    int oplevel;
     time_t idle_since;
 };
 
index 35ead4a223f4fee44a57dc93fdd449845776ed7c..7aed1109f3d8b3e0b119177bf67e05967334050b 100644 (file)
@@ -457,9 +457,16 @@ static MODCMD_FUNC(cmd_chaninfo)
     }
     reply("OSMSG_CHANINFO_USER_COUNT", channel->members.used);
     for (n=0; n<channel->members.used; n++) {
-       moden = channel->members.list[n];
-       if (moden->modes & MODE_CHANOP)
-            send_message_type(4, user, cmd->parent->bot, " @%s (%s@%s)", moden->user->nick, moden->user->ident, moden->user->hostname);
+           moden = channel->members.list[n];
+           if (moden->modes & MODE_CHANOP)
+        {
+                if (moden->oplevel >= 0)
+                {
+                    send_message_type(4, user, cmd->parent->bot, " (%d)@%s (%s@%s)", moden->oplevel, moden->user->nick, moden->user->ident, moden->user->hostname);
+                } else {
+                    send_message_type(4, user, cmd->parent->bot, " @%s (%s@%s)", moden->user->nick, moden->user->ident, moden->user->hostname);
+                }
+        }
     }
     for (n=0; n<channel->members.used; n++) {
        moden = channel->members.list[n];
index b5e5118a02e246706df003fbfdc5f21fb122dd52..b7b9bc22d09665618ba8f479a5aa4b38e1d4c3cf 100644 (file)
@@ -543,6 +543,8 @@ mod_chanmode_dup(struct mod_chanmode *orig, unsigned int extra)
         res->modes_clear = orig->modes_clear;
         res->new_limit = orig->new_limit;
         memcpy(res->new_key, orig->new_key, sizeof(res->new_key));
+        memcpy(res->new_upass, orig->new_upass, sizeof(res->new_upass));
+        memcpy(res->new_apass, orig->new_apass, sizeof(res->new_apass));
         res->argc = orig->argc;
         memcpy(res->args, orig->args, orig->argc*sizeof(orig->args[0]));
     }
@@ -561,6 +563,10 @@ mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_ch
         channel->limit = change->new_limit;
     if (change->modes_set & MODE_KEY)
         strcpy(channel->key, change->new_key);
+    if (change->modes_set & MODE_UPASS)
+       strcpy(channel->upass, change->new_upass);
+    if (change->modes_set & MODE_APASS)
+       strcpy(channel->apass, change->new_apass);
     for (ii = 0; ii < change->argc; ++ii) {
         switch (change->args[ii].mode) {
         case MODE_BAN:
@@ -648,6 +654,8 @@ irc_make_chanmode(struct chanNode *chan, char *out)
     change.modes_set = chan->modes;
     change.new_limit = chan->limit;
     safestrncpy(change.new_key, chan->key, sizeof(change.new_key));
+    safestrncpy(change.new_upass, chan->upass, sizeof(change.new_upass));
+    safestrncpy(change.new_apass, chan->apass, sizeof(change.new_apass));
     return strlen(mod_chanmode_format(&change, out));
 }
 
index cf9b07637dfb630ae2e3e333a53ec46b8984adfb..ec34a8dd3d62304a56a3b11c9cb95d8f6bf3141b 100644 (file)
@@ -296,6 +296,8 @@ static struct userNode *AddUser(struct server* uplink, const char *nick, const c
 
 extern int off_channel;
 
+static int parse_oplevel(char *str);
+
 /* Numerics can be XYY, XYYY, or XXYYY; with X's identifying the
  * server and Y's indentifying the client on that server. */
 struct server*
@@ -981,6 +983,7 @@ static CMD_FUNC(cmd_error_nick)
 
 struct create_desc {
     struct userNode *user;
+    int oplevel;
     time_t when;
 };
 
@@ -988,7 +991,12 @@ static void
 join_helper(struct chanNode *chan, void *data)
 {
     struct create_desc *cd = data;
-    AddChannelUser(cd->user, chan);
+    struct modeNode *mNode;
+
+    mNode = AddChannelUser(cd->user, chan);
+    mNode->oplevel = cd->oplevel;
+    if (mNode->oplevel >= 0)
+        mNode->modes |= MODE_CHANOP;
 }
 
 static void
@@ -1105,6 +1113,7 @@ static CMD_FUNC(cmd_burst)
     struct userNode *un;
     struct modeNode *mNode;
     long mode;
+    int oplevel = -1;
     char *user, *end, sep;
     time_t in_timestamp;
 
@@ -1117,7 +1126,8 @@ static CMD_FUNC(cmd_burst)
             const char *pos;
             int n_modes;
             for (pos=argv[next], n_modes = 1; *pos; pos++)
-                if ((*pos == 'k') || (*pos == 'l'))
+                if ((*pos == 'k') || (*pos == 'l') || (*pos == 'A')
+                    || (*pos == 'U'))
                     n_modes++;
             unsplit_string(argv+next, n_modes, modes);
             next += n_modes;
@@ -1143,12 +1153,18 @@ static CMD_FUNC(cmd_burst)
         if (sep == ':') {
             mode = 0;
             while ((sep = *end++)) {
-                if (sep == 'o')
+                if (sep == 'o') {
                     mode |= MODE_CHANOP;
-                else if (sep == 'v')
+                    oplevel = -1;
+                } else if (sep == 'v') {
                     mode |= MODE_VOICE;
-                else if (isdigit(sep)) {
+                    oplevel = -1;
+                } else if (isdigit(sep)) {
                     mode |= MODE_CHANOP;
+                    if (oplevel >= 0)
+                        oplevel += parse_oplevel(end);
+                    else
+                        oplevel = parse_oplevel(end);
                     while (isdigit(*end)) end++;
                 } else
                     break;
@@ -1160,8 +1176,10 @@ static CMD_FUNC(cmd_burst)
             res = 0;
             continue;
         }
-        if ((mNode = AddChannelUser(un, cNode)))
+        if ((mNode = AddChannelUser(un, cNode))) {
             mNode->modes = mode;
+            mNode->oplevel = oplevel;
+        }
     }
 
     return res;
@@ -1710,15 +1728,38 @@ static void
 parse_foreach(char *target_list, foreach_chanfunc cf, foreach_nonchan nc, foreach_userfunc uf, foreach_nonuser nu, void *data)
 {
     char *j, old;
+    char *cPos, *hPos;
+    int oplevel;
+
     do {
         j = target_list;
         while (*j != 0 && *j != ',')
             j++;
         old = *j;
         *j = 0;
+
+        hPos = strchr(target_list,'#');
+        cPos = strchr(target_list,':');
+
+        /*
+         * Check if both a '#' and a ':' is in the target's name
+         * and if cPos < hPos.
+         * If that's the case, voila, we've found a join with an oplevel
+         */
+        if (hPos && cPos && (cPos < hPos))
+        {
+            oplevel = parse_oplevel(target_list);
+            target_list = hPos + 1;
+        }
+        else
+            oplevel = -1;
+
         if (IsChannelName(target_list)
             || (target_list[0] == '0' && target_list[1] == '\0')) {
             struct chanNode *chan = GetChannel(target_list);
+            struct create_desc *cd = (struct create_desc*) data;
+
+            cd->oplevel = oplevel;
             if (chan) {
                 if (cf)
                     cf(chan, data);
@@ -2193,6 +2234,37 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un
                 }
             }
             break;
+        case 'U':
+            if (add)
+            {
+              if (in_arg >= argc)
+                  goto error;
+              change->modes_set |= MODE_UPASS;
+              safestrncpy(change->new_upass, modes[in_arg++], sizeof(change->new_upass));
+            } else {
+                change->modes_clear |= MODE_UPASS;
+                if (!(flags & MCP_UPASS_FREE)) {
+                    if (in_arg >= argc)
+                        goto error;
+                    in_arg++;
+                }
+            }
+            break;
+        case 'A':
+            if (add) {
+                if (in_arg >= argc)
+                    goto error;
+                change->modes_set |= MODE_APASS;
+                safestrncpy(change->new_apass, modes[in_arg++], sizeof(change->new_apass));
+            } else {
+                change->modes_clear |= MODE_APASS;
+                if (!(flags & MCP_APASS_FREE)) {
+                    if (in_arg >= argc)
+                      goto error;
+                    in_arg++;
+                }
+            }
+            break;
         case 'b':
             if (!(flags & MCP_ALLOW_OVB))
                 goto error;
@@ -2206,6 +2278,25 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un
         case 'o': case 'v':
         {
             struct userNode *victim;
+            char *oplevel_str;
+            int oplevel;
+
+            oplevel_str = strchr(modes[in_arg], ':');
+
+            /* XXYYY M #channel +o XXYYY:<oplevel> */
+            if (oplevel_str)
+            {
+                oplevel = parse_oplevel(oplevel_str+1);
+                *oplevel_str = 0;
+            }
+            else if (channel->modes & MODE_UPASS)
+            {
+                /* TODO: need to set oplevel based on issuer's oplevel */
+                oplevel = -1;
+            }
+            else
+                oplevel = -1;
+
             if (!(flags & MCP_ALLOW_OVB))
                 goto error;
             if (in_arg >= argc)
@@ -2220,7 +2311,11 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un
             if (!victim)
                 continue;
             if ((change->args[ch_arg].u.member = GetUserMode(channel, victim)))
+            {
+                /* Apply the oplevel change */
+                change->args[ch_arg].u.member->oplevel = oplevel;
                 ch_arg++;
+            }
             break;
         }
         default:
@@ -2313,6 +2408,10 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod
 #undef DO_MODE_CHAR
         if (change->modes_clear & channel->modes & MODE_KEY)
             mod_chanmode_append(&chbuf, 'k', channel->key);
+        if (change->modes_clear & channel->modes & MODE_UPASS)
+            mod_chanmode_append(&chbuf, 'U', channel->upass);
+        if (change->modes_clear * channel->modes & MODE_APASS)
+            mod_chanmode_append(&chbuf, 'A', channel->apass);
     }
     for (arg = 0; arg < change->argc; ++arg) {
         if (!(change->args[arg].mode & MODE_REMOVE))
@@ -2352,6 +2451,10 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod
 #undef DO_MODE_CHAR
         if(change->modes_set & MODE_KEY)
             mod_chanmode_append(&chbuf, 'k', change->new_key);
+        if (change->modes_set & MODE_UPASS)
+            mod_chanmode_append(&chbuf, 'U', change->new_upass);
+        if (change->modes_set & MODE_APASS)
+            mod_chanmode_append(&chbuf, 'A', change->new_apass);
         if(change->modes_set & MODE_LIMIT) {
             sprintf(int_buff, "%d", change->new_limit);
             mod_chanmode_append(&chbuf, 'l', int_buff);
@@ -2400,6 +2503,8 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
         DO_MODE_CHAR(NOPRIVMSGS, 'n');
         DO_MODE_CHAR(LIMIT, 'l');
         DO_MODE_CHAR(KEY, 'k');
+        DO_MODE_CHAR(UPASS, 'U');
+        DO_MODE_CHAR(APASS, 'A');
         DO_MODE_CHAR(DELAYJOINS, 'D');
         DO_MODE_CHAR(REGONLY, 'r');
         DO_MODE_CHAR(NOCOLORS, 'c');
@@ -2422,10 +2527,51 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
         DO_MODE_CHAR(NOCTCPS, 'C');
         DO_MODE_CHAR(REGISTERED, 'z');
 #undef DO_MODE_CHAR
-        switch (change->modes_set & (MODE_KEY|MODE_LIMIT)) {
+        switch (change->modes_set & (MODE_KEY|MODE_LIMIT|MODE_APASS|MODE_UPASS)) {
+        /* Doing this implementation has been a pain in the arse, I hope I didn't forget a possible combination */
+        case MODE_KEY|MODE_LIMIT|MODE_APASS|MODE_UPASS:
+            used += sprintf(outbuff+used, "lkAU %d %s %s %s", change->new_limit, change->new_key, change->new_apass, change->new_upass);
+            break;
+
+        case MODE_KEY|MODE_LIMIT|MODE_APASS:
+            used += sprintf(outbuff+used, "lkA %d %s %s", change->new_limit, change->new_key, change->new_apass);
+            break;
+        case MODE_KEY|MODE_LIMIT|MODE_UPASS:
+            used += sprintf(outbuff+used, "lkU %d %s %s", change->new_limit, change->new_key, change->new_upass);
+            break;
+        case MODE_KEY|MODE_APASS|MODE_UPASS:
+            used += sprintf(outbuff+used, "kAU %s %s %s", change->new_key, change->new_apass, change->new_upass);
+            break;
+
+        case MODE_KEY|MODE_APASS:
+            used += sprintf(outbuff+used, "kA %s %s", change->new_key, change->new_apass);
+            break;
+        case MODE_KEY|MODE_UPASS:
+            used += sprintf(outbuff+used, "kU %s %s", change->new_key, change->new_upass);
+            break;
         case MODE_KEY|MODE_LIMIT:
             used += sprintf(outbuff+used, "lk %d %s", change->new_limit, change->new_key);
             break;
+        case MODE_LIMIT|MODE_UPASS:
+            used += sprintf(outbuff+used, "lU %d %s", change->new_limit, change->new_upass);
+            break;
+        case MODE_LIMIT|MODE_APASS:
+            used += sprintf(outbuff+used, "lA %d %s", change->new_limit, change->new_apass);
+            break;
+        case MODE_APASS|MODE_UPASS:
+            used += sprintf(outbuff+used, "AU %s %s", change->new_apass, change->new_upass);
+            break;
+
+        case MODE_LIMIT|MODE_APASS|MODE_UPASS:
+            used += sprintf(outbuff+used, "lAU %d %s %s", change->new_limit, change->new_apass, change->new_upass);
+            break;
+
+        case MODE_APASS:
+            used += sprintf(outbuff+used, "A %s", change->new_apass);
+            break;
+        case MODE_UPASS:
+            used += sprintf(outbuff+used, "U %s", change->new_upass);
+            break;
         case MODE_KEY:
             used += sprintf(outbuff+used, "k %s", change->new_key);
             break;
@@ -2457,6 +2603,14 @@ clear_chanmode(struct chanNode *channel, const char *modes)
             remove |= MODE_KEY;
             channel->key[0] = '\0';
             break;
+        case 'A':
+            remove |= MODE_APASS;
+            channel->apass[0] = '\0';
+            break;
+        case 'U':
+            remove |= MODE_UPASS;
+            channel->upass[0] = '\0';
+            break;
         case 'l':
             remove |= MODE_LIMIT;
             channel->limit = 0;
@@ -2616,3 +2770,15 @@ send_burst(void)
     for (it = dict_first(channels); it; it = iter_next(it))
         dict_insert(unbursted_channels, iter_key(it), iter_data(it));
 }
+
+/*
+ * Oplevel parsing
+ */
+static int
+parse_oplevel(char *str)
+{
+    int oplevel = 0;
+    while (isdigit(*str))
+        oplevel = oplevel * 10 + *str++ - '0';
+    return oplevel;
+}
index 71e55647aa6f636c6e2265539d9358a28551f6de..9f0f77a18f7b26539a4dea5be49012913ca9a5f1 100644 (file)
@@ -192,6 +192,8 @@ struct mod_chanmode {
     unsigned int alloc_argc;
 #endif
     char new_key[KEYLEN + 1];
+    char new_upass[KEYLEN + 1];
+    char new_apass[KEYLEN + 1];
     struct {
         unsigned int mode;
         union {
@@ -204,6 +206,8 @@ struct mod_chanmode {
 #define MCP_FROM_SERVER   0x0002 /* parse as from a server */
 #define MCP_KEY_FREE      0x0004 /* -k without a key argument */
 #define MCP_REGISTERED   0x0008 /* chan is already registered; do not allow changes to MODE_REGISTERED */
+#define MCP_UPASS_FREE    0x0010 /* -U without a key argument */
+#define MCP_APASS_FREE    0x0020 /* -A without a key argument */
 #define MC_ANNOUNCE       0x0100 /* send a mod_chanmode() change out */
 #define MC_NOTIFY         0x0200 /* make local callbacks to announce */
 #ifdef NDEBUG