]> PatchyGit - patchyircd.git/commitdiff
move channel MODE setting into a separate func
authorEgor <egor@patchysicp.xyz>
Fri, 26 Jan 2024 11:33:56 +0000 (13:33 +0200)
committerEgor <egor@patchysicp.xyz>
Fri, 26 Jan 2024 11:47:48 +0000 (13:47 +0200)
src/irc.c
src/irc.h

index b3f1acc..584a7b4 100644 (file)
--- a/src/irc.c
+++ b/src/irc.c
@@ -903,175 +903,7 @@ saslcleanup:
                                        if (any)
                                                return 0;
                                }
-                               int is_plus;
-                               char *p = args[1];
-                               switch (*p++) {
-                                       case '+': is_plus = 1; break;
-                                       case '-': is_plus = 0; break;
-                                       default: goto unknown;
-                               }
-                               map_t *list;
-                               char **argp = &args[2];
-                               while (*p) {
-                                       switch (*p) {
-                                       case '+': is_plus = 1; break;
-                                       case '-': is_plus = 0; break;
-#define MSG_CHANDMODE(m) \
-                                       copy_strf(&databuf, ":%s!%s@%s MODE %s %s"m"\r\n", \
-                                                       client->nick, client->username, client->hostname, \
-                                                       chan->name, is_plus?"+":"-")
-                                       case 'P':
-                                               if (!(client->umode & UMODE_OPER))
-                                                       break;
-                                               SETBIT(chan->dmode, DMODE_PERSIST, is_plus);
-                                               MSG_CHANDMODE("P");
-                                               chanlog(), sendbuf_chan(chan);
-                                               break;
-                                       case 'i':
-                                               SETBIT(chan->dmode, DMODE_INVITEONLY, is_plus);
-                                               MSG_CHANDMODE("i");
-                                               chanlog(), sendbuf_chan(chan);
-                                               break;
-                                       case 'm':
-                                               SETBIT(chan->dmode, DMODE_MODERATED, is_plus);
-                                               MSG_CHANDMODE("m");
-                                               chanlog(), sendbuf_chan(chan);
-                                               break;
-                                       case 'n':
-                                               SETBIT(chan->dmode, DMODE_NOEXTERNAL, is_plus);
-                                               MSG_CHANDMODE("n");
-                                               chanlog(), sendbuf_chan(chan);
-                                               break;
-                                       case 's':
-                                               SETBIT(chan->dmode, DMODE_SECRET, is_plus);
-                                               MSG_CHANDMODE("s");
-                                               chanlog(), sendbuf_chan(chan);
-                                               break;
-                                       case 't':
-                                               SETBIT(chan->dmode, DMODE_TOPICPROT, is_plus);
-                                               MSG_CHANDMODE("t");
-                                               chanlog(), sendbuf_chan(chan);
-                                               break;
-                                       case 'l':
-                                               if (is_plus) {
-                                                       int x = 0;
-                                                       if (!*argp) {
-                                                               // FIXME: not enough args error
-                                                       } else if (sscanf(*argp, "%u", &x) != 1 || x < 0) {
-                                                               // FIXME: bad arg error
-                                                               argp++;
-                                                       } else {
-                                                               chan->member_limit = x;
-                                                               copy_strf(&databuf, ":%s!%s@%s MODE %s +l %u\r\n",
-                                                                               client->nick, client->username, client->hostname,
-                                                                               chan->name, x);
-                                                               chanlog(), sendbuf_chan(chan);
-                                                               argp++;
-                                                       }
-                                               } else {
-                                                       chan->member_limit = -1;
-                                                       MSG_CHANDMODE("l");
-                                                       chanlog(), sendbuf_chan(chan);
-                                               }
-                                               break;
-                                       case 'k':
-                                               if (is_plus) {
-                                                       if (!*argp) {
-                                                               // FIXME: not enough args error
-                                                               break;
-                                                       } else if (strchr(*argp, ',') || strchr(*argp, ' ')) {
-                                                               err_invalidkey(client, chan), sendbuf(client);
-                                                               argp++;
-                                                               break;
-                                                       }
-                                                       if (chan->chankey)
-                                                               free(chan->chankey);
-                                                       chan->chankey = mystrdup(*argp);
-                                                       if (!chan->chankey)
-                                                               abort();
-                                               } else {
-                                                       free(chan->chankey);
-                                                       chan->chankey = NULL;
-                                                       if (*argp) // unused argument
-                                                               argp++;
-                                               }
-                                               copy_strf(&databuf, ":%s!%s@%s MODE %s %sk %s\r\n",
-                                                               client->nick, client->username, client->hostname,
-                                                               chan->name, is_plus?"+":"-", is_plus?*argp:"*");
-                                               chanlog(), sendbuf_chan(chan);
-                                               break;
-                                       case 'b':
-                                               list = &chan->listb;
-                                               goto set_list;
-                                       case 'e':
-                                               list = &chan->liste;
-                                               goto set_list;
-                                       case 'I':
-                                               list = &chan->listI;
-                                               goto set_list;
-                                       case 'q':
-                                               list = &chan->listq;
-                                               goto set_list;
-                                       case 'w':
-                                               if (!*argp) // TODO: error msg
-                                                       break;
-                                               if (argp[0][0] == 'o')
-                                                       list = &chan->listwo;
-                                               else if (argp[0][0] == 'v')
-                                                       list = &chan->listwv;
-                                               else
-                                                       break; // TODO: error msg
-                                               if (argp[0][1] != ':')
-                                                       break; // TODO: error msg
-                                               argp[0] += 2;
-                                               goto set_list;
-                                       set_list: {
-                                               if(!*argp) // TODO: error msg
-                                                       break;
-                                               char *mask = *argp++;
-                                               if (strchr(mask, ' '))
-                                                       break; // TODO: error msg
-                                               stringlower(mask);
-                                               if (map_set(list, mask, is_plus ? mask /* dummy */ : NULL, NULL) == -1)
-                                                       abort();
-                                               char which[2] = {*p, 0};
-                                               copy_strf(&databuf, ":%s!%s@%s MODE %s %s%s %s\r\n",
-                                                               client->nick, client->username, client->hostname,
-                                                               chan->name, is_plus?"+":"-", which, mask);
-                                               // TODO: limit to ops
-                                               chanlog(), sendbuf_chan(chan);
-                                               break;
-                                       }
-                                       case 'v':
-                                       case 'o': {
-                                               if(!*argp)
-                                                       break;
-                                               const char *nick = *argp++;
-                                               char which[2] = {*p, 0};
-                                               struct client_data *cl = findClient(nick);
-                                               if (!cl) {
-                                                       err_nosuchnick(client, nick), sendbuf(client);
-                                                       break;
-                                               }
-                                               if (!map_get(&chan->members, cl->key)) {
-                                                       err_usernotinchannel(client, cl->nick, chan), sendbuf(client);
-                                                       break;
-                                               }
-                                               if (map_set(*p == 'o' ? &chan->o : &chan->v, cl->key, is_plus ? cl : NULL, NULL) == -1)
-                                                       abort();
-                                               copy_strf(&databuf, ":%s!%s@%s MODE %s %s%s %s\r\n",
-                                                               client->nick, client->username, client->hostname,
-                                                               chan->name, is_plus?"+":"-", which, cl->nick);
-                                               sendbuf_chan(chan);
-                                               break;
-                                       }
-                                       default:
-                                               err_unknownmode(client, *p);
-                                               sendbuf(client);
-                                               break;
-                                       }
-                                       p++;
-                               }
+                               channel_mode(client, chan, args+1);
                        }
                }
        } else if(strcmp(command, "LIST") == 0) {
@@ -1728,6 +1560,179 @@ void channel_kill(struct channel *chan)
        free(chan->chankey);
        free(chan);
 }
+void channel_mode(struct client_data *client, struct channel *chan, char *args[]) {
+       int is_plus;
+       char *p = args[0];
+       switch (*p++) {
+               case '+': is_plus = 1; break;
+               case '-': is_plus = 0; break;
+               default:
+                       err_unknowncommand(client, "MODE"), sendbuf(client);
+                       return;
+       }
+       map_t *list;
+       char **argp = &args[1];
+       while (*p) {
+               switch (*p) {
+               case '+': is_plus = 1; break;
+               case '-': is_plus = 0; break;
+#define MSG_CHANDMODE(m) \
+               copy_strf(&databuf, ":%s!%s@%s MODE %s %s"m"\r\n", \
+                               client->nick, client->username, client->hostname, \
+                               chan->name, is_plus?"+":"-")
+               case 'P':
+                       if (!(client->umode & UMODE_OPER))
+                               break;
+                       SETBIT(chan->dmode, DMODE_PERSIST, is_plus);
+                       MSG_CHANDMODE("P");
+                       chanlog(), sendbuf_chan(chan);
+                       break;
+               case 'i':
+                       SETBIT(chan->dmode, DMODE_INVITEONLY, is_plus);
+                       MSG_CHANDMODE("i");
+                       chanlog(), sendbuf_chan(chan);
+                       break;
+               case 'm':
+                       SETBIT(chan->dmode, DMODE_MODERATED, is_plus);
+                       MSG_CHANDMODE("m");
+                       chanlog(), sendbuf_chan(chan);
+                       break;
+               case 'n':
+                       SETBIT(chan->dmode, DMODE_NOEXTERNAL, is_plus);
+                       MSG_CHANDMODE("n");
+                       chanlog(), sendbuf_chan(chan);
+                       break;
+               case 's':
+                       SETBIT(chan->dmode, DMODE_SECRET, is_plus);
+                       MSG_CHANDMODE("s");
+                       chanlog(), sendbuf_chan(chan);
+                       break;
+               case 't':
+                       SETBIT(chan->dmode, DMODE_TOPICPROT, is_plus);
+                       MSG_CHANDMODE("t");
+                       chanlog(), sendbuf_chan(chan);
+                       break;
+               case 'l':
+                       if (is_plus) {
+                               int x = 0;
+                               if (!*argp) {
+                                       // FIXME: not enough args error
+                               } else if (sscanf(*argp, "%u", &x) != 1 || x < 0) {
+                                       // FIXME: bad arg error
+                                       argp++;
+                               } else {
+                                       chan->member_limit = x;
+                                       copy_strf(&databuf, ":%s!%s@%s MODE %s +l %u\r\n",
+                                                       client->nick, client->username, client->hostname,
+                                                       chan->name, x);
+                                       chanlog(), sendbuf_chan(chan);
+                                       argp++;
+                               }
+                       } else {
+                               chan->member_limit = -1;
+                               MSG_CHANDMODE("l");
+                               chanlog(), sendbuf_chan(chan);
+                       }
+                       break;
+               case 'k':
+                       if (is_plus) {
+                               if (!*argp) {
+                                       // FIXME: not enough args error
+                                       break;
+                               } else if (strchr(*argp, ',') || strchr(*argp, ' ')) {
+                                       err_invalidkey(client, chan), sendbuf(client);
+                                       argp++;
+                                       break;
+                               }
+                               if (chan->chankey)
+                                       free(chan->chankey);
+                               chan->chankey = mystrdup(*argp);
+                               if (!chan->chankey)
+                                       abort();
+                       } else {
+                               free(chan->chankey);
+                               chan->chankey = NULL;
+                               if (*argp) // unused argument
+                                       argp++;
+                       }
+                       copy_strf(&databuf, ":%s!%s@%s MODE %s %sk %s\r\n",
+                                       client->nick, client->username, client->hostname,
+                                       chan->name, is_plus?"+":"-", is_plus?*argp:"*");
+                       chanlog(), sendbuf_chan(chan);
+                       break;
+               case 'b':
+                       list = &chan->listb;
+                       goto set_list;
+               case 'e':
+                       list = &chan->liste;
+                       goto set_list;
+               case 'I':
+                       list = &chan->listI;
+                       goto set_list;
+               case 'q':
+                       list = &chan->listq;
+                       goto set_list;
+               case 'w':
+                       if (!*argp) // TODO: error msg
+                               break;
+                       if (argp[0][0] == 'o')
+                               list = &chan->listwo;
+                       else if (argp[0][0] == 'v')
+                               list = &chan->listwv;
+                       else
+                               break; // TODO: error msg
+                       if (argp[0][1] != ':')
+                               break; // TODO: error msg
+                       argp[0] += 2;
+                       goto set_list;
+               set_list: {
+                       if(!*argp) // TODO: error msg
+                               break;
+                       char *mask = *argp++;
+                       if (strchr(mask, ' '))
+                               break; // TODO: error msg
+                       stringlower(mask);
+                       if (map_set(list, mask, is_plus ? mask /* dummy */ : NULL, NULL) == -1)
+                               abort();
+                       char which[2] = {*p, 0};
+                       copy_strf(&databuf, ":%s!%s@%s MODE %s %s%s %s\r\n",
+                                       client->nick, client->username, client->hostname,
+                                       chan->name, is_plus?"+":"-", which, mask);
+                       // TODO: limit to ops
+                       chanlog(), sendbuf_chan(chan);
+                       break;
+               }
+               case 'v':
+               case 'o': {
+                       if(!*argp)
+                               break;
+                       const char *nick = *argp++;
+                       char which[2] = {*p, 0};
+                       struct client_data *cl = findClient(nick);
+                       if (!cl) {
+                               err_nosuchnick(client, nick), sendbuf(client);
+                               break;
+                       }
+                       if (!map_get(&chan->members, cl->key)) {
+                               err_usernotinchannel(client, cl->nick, chan), sendbuf(client);
+                               break;
+                       }
+                       if (map_set(*p == 'o' ? &chan->o : &chan->v, cl->key, is_plus ? cl : NULL, NULL) == -1)
+                               abort();
+                       copy_strf(&databuf, ":%s!%s@%s MODE %s %s%s %s\r\n",
+                                       client->nick, client->username, client->hostname,
+                                       chan->name, is_plus?"+":"-", which, cl->nick);
+                       sendbuf_chan(chan);
+                       break;
+               }
+               default:
+                       err_unknownmode(client, *p);
+                       sendbuf(client);
+                       break;
+               }
+               p++;
+       }
+}
 struct client_data *findClient(const char *nickname)
 {
        char key[MAX_NICKLEN];
index 0a1f9e4..b9f88dd 100644 (file)
--- a/src/irc.h
+++ b/src/irc.h
@@ -21,5 +21,6 @@ void channel_sendnames(struct client_data *client, struct channel *chan);
 void channel_join(struct client_data *client, const char *channel, const char *chankey);
 void channel_part(struct client_data *client, struct channel *chan, const char *reason, struct client_data *kicker);
 void channel_kill(struct channel *chan);
+void channel_mode(struct client_data *client, struct channel *chan, char *args[]);
 extern struct dynarr databuf;
 #endif