bug fixes (from code coverage tests)
[srvx.git] / src / proto-p10.c
index 2fc7fac7d964928ff56abdf8c30dfb885b3efca8..7717c8d3d7e8dd1c3ecbb7ab3c2f74e646e42559 100644 (file)
@@ -832,14 +832,18 @@ static CMD_FUNC(cmd_eob_ack)
 
 static CMD_FUNC(cmd_ping)
 {
+    struct server *srv;
+    struct userNode *un;
+
     if(argc > 3)
-    {
         irc_pong(argv[2], argv[1]);
-    }
+    else if ((srv = GetServerH(origin)))
+        irc_pong(self->name, srv->numeric);
+    else if ((un = GetUserH(origin)))
+        irc_pong(self->name, un->numeric);
     else
-    {
         irc_pong(self->name, origin);
-    }
+
     timeq_del(0, timed_send_ping, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
     timeq_del(0, timed_ping_timeout, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
     timeq_add(now + ping_freq, timed_send_ping, 0);
@@ -871,20 +875,14 @@ static void
 create_helper(char *name, void *data)
 {
     struct create_desc *cd = data;
-    /* We can't assume the channel create was allowed because of the
-     * bad-word channel checking.
-     */
-    struct chanNode *cn;
-    struct modeNode *mn;
+
     if (!strcmp(name, "0")) {
         while (cd->user->channels.used > 0)
             DelChannelUser(cd->user, cd->user->channels.list[0]->channel, 0, 0);
         return;
     }
-    cn = AddChannel(name, cd->when, NULL, NULL);
-    mn = AddChannelUser(cd->user, cn);
-    if (mn && (cn->members.used == 1))
-        mn->modes = MODE_CHANOP;
+
+    AddChannelUser(cd->user, AddChannel(name, cd->when, NULL, NULL));
 }
 
 static CMD_FUNC(cmd_create)
@@ -1120,7 +1118,8 @@ static CMD_FUNC(cmd_clearmode)
 
 static CMD_FUNC(cmd_topic)
 {
-    static struct chanNode *cn;
+    struct chanNode *cn;
+    time_t chan_ts, topic_ts;
 
     if (argc < 3)
         return 0;
@@ -1128,7 +1127,16 @@ static CMD_FUNC(cmd_topic)
         log_module(MAIN_LOG, LOG_ERROR, "Unable to find channel %s whose topic is being set", argv[1]);
         return 0;
     }
-    SetChannelTopic(cn, GetUserH(origin), argv[2], 0);
+    if (argc >= 5) {
+        /* Looks like an Asuka style topic burst. */
+        chan_ts = atoi(argv[2]);
+        topic_ts = atoi(argv[3]);
+    } else {
+        chan_ts = cn->timestamp;
+        topic_ts = now;
+    }
+    SetChannelTopic(cn, GetUserH(origin), argv[argc-1], 0);
+    cn->topic_time = topic_ts;
     return 1;
 }
 
@@ -1975,7 +1983,7 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un
         case '-':
             add = 0;
             break;
-#define do_chan_mode(FLAG) do { if (add) change->modes_set |= FLAG, change->modes_clear &= ~FLAG; else change->modes_clear |= FLAG, change->modes_set &= ~FLAG; } while(0)
+#define do_chan_mode(FLAG) do { if (add) change->modes_set |= (FLAG), change->modes_clear &= ~(FLAG); else change->modes_clear |= (FLAG), change->modes_set &= ~(FLAG); } while(0)
         case 'C': do_chan_mode(MODE_NOCTCPS); break;
         case 'D': do_chan_mode(MODE_DELAYJOINS); break;
         case 'c': do_chan_mode(MODE_NOCOLORS); break;
@@ -2044,6 +2052,13 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un
         }
     }
     change->argc = ch_arg; /* in case any turned out to be ignored */
+    if (change->modes_set & MODE_SECRET) {
+        change->modes_set &= ~(MODE_PRIVATE);
+        change->modes_clear |= MODE_PRIVATE;
+    } else if (change->modes_set & MODE_PRIVATE) {
+        change->modes_set &= ~(MODE_SECRET);
+        change->modes_clear |= MODE_SECRET;
+    }
     return change;
   error:
     mod_chanmode_free(change);
@@ -2066,7 +2081,8 @@ static void
 mod_chanmode_append(struct chanmode_buffer *buf, char ch, const char *arg)
 {
     size_t arg_len = strlen(arg);
-    if (buf->modes_used + buf->args_used + buf->chname_len + arg_len > 450) {
+    if (buf->modes_used > (MAXMODEPARAMS) ||
+        buf->modes_used + buf->args_used + buf->chname_len + arg_len > 450) {
         memcpy(buf->modes + buf->modes_used, buf->args, buf->args_used);
         buf->modes[buf->modes_used + buf->args_used] = '\0';
         irc_mode((buf->is_chanop ? buf->actor : NULL), buf->channel, buf->modes);