]> PatchyGit - patchyircd.git/commitdiff
handle chan modes in PRIVMSG/NOTICE
authorEgor <egor@patchysicp.xyz>
Sun, 8 May 2022 09:11:26 +0000 (12:11 +0300)
committerEgor <egor@patchysicp.xyz>
Sun, 8 May 2022 09:11:26 +0000 (12:11 +0300)
irc.c
ircfmt.c

diff --git a/irc.c b/irc.c
index d9f3b11..f0b9b04 100644 (file)
--- a/irc.c
+++ b/irc.c
@@ -20,16 +20,23 @@ void sendbuf_chan(struct channel *chan) {
                        sendbuf(cl);
                } while (trie_findnext(&f) == 1);
 }
-void sendbuf_chan_sans_self(struct client_data *client, struct channel *chan) {
+void sendbuf_list_sans_self(struct client_data *client, struct trie_node **ls, int cookie) {
        struct trie_find *f = NULL;
-       if (trie_findfirst(&f, &chan->members) == 1)
+       if (trie_findfirst(&f, ls) == 1)
                do {
                        struct client_data *cl = f->n->value;
-                       if (client != cl)
+                       if (client != cl) {
+                               if (cookie) {
+                                       if (cookie != cl->cookie)
+                                               cl->cookie = cookie;
+                                       else
+                                               continue;
+                               }
                                sendbuf(cl);
+                       }
                } while (trie_findnext(&f) == 1);
 }
-void sendbuf_visible(struct client_data *client) {
+int get_cookie() {
        static int cookie = 0;
        if (++cookie == 0) {
                // handle overflow
@@ -41,6 +48,10 @@ void sendbuf_visible(struct client_data *client) {
                        } while (trie_findnext(&f) == 1);
                cookie++;
        }
+       return cookie;
+}
+void sendbuf_visible(struct client_data *client) {
+       int cookie = get_cookie();
        struct trie_find *f1 = NULL, *f2 = NULL;
        if (trie_findfirst(&f1, &client->channels) == 1)
                do {
@@ -307,11 +318,31 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                if (argc < 2) // FIXME: error message
                        return 0;
                (command[0] == 'P' ? msg_privmsg : msg_notice)(client, args[0], args[1]);
-               if (args[0][0] == '#' || args[0][0] == '&') {
-                       struct channel *chan = findChannel(args[0]);
+               // TODO: extra target forms such as nick@server #hostmask $servermask
+               int is_modmsg = !!strchr("@+", args[0][0]);
+               if (strchr("#&", args[0][is_modmsg])) {
+                       struct channel *chan = findChannel(args[0]+is_modmsg);
                        if (!chan)
                                return err_nosuchchannel(client, args[0]), sendbuf(client), 0;
-                       sendbuf_chan_sans_self(client, chan);
+                       // TODO: check bans
+                       if (chan->dmode & DMODE_NOEXTERNAL && !trie_get(&chan->members, client->key))
+                               return err_cannotsendtochan(client, chan->name), sendbuf(client), 0;
+                       if (chan->dmode & DMODE_MODERATED && !trie_get(&chan->v, client->key) && !trie_get(&chan->o, client->key))
+                               return err_cannotsendtochan(client, chan->name), sendbuf(client), 0;
+                       switch (args[0][0]) {
+                       default:
+                               sendbuf_list_sans_self(client, &chan->members, 0);
+                               break;
+                       case '+': {
+                               int cookie = get_cookie();
+                               sendbuf_list_sans_self(client, &chan->v, cookie);
+                               sendbuf_list_sans_self(client, &chan->o, cookie);
+                               break;
+                       }
+                       case '@':
+                               sendbuf_list_sans_self(client, &chan->o, 0);
+                               break;
+                       }
                } else {
                        struct client_data *cl = findClient(args[0]);
                        if (!cl) {
@@ -415,7 +446,7 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                                struct channel *chan = findChannel(nick);
                                if (!chan)
                                        return err_nosuchchannel(client, nick), sendbuf(client), 0;
-                               if (!trie_get(&chan->o, client->key)
+                               if (!trie_get(&chan->o, client->key))
                                        return 0; // TODO: error
                                if (argc == 2) { // Type A channel modes
                                        if (!strcmp(args[1], "+b")) {
index f6f9932..07290d3 100644 (file)
--- a/ircfmt.c
+++ b/ircfmt.c
@@ -236,11 +236,11 @@ void err_nosuchchannel(struct client_data *client, const char *channel) // 403
 {
        copy_strf(&databuf, ":%s 403 %s %s :No such channel\r\n", hostname, client->nick, channel);
 }
-#if 0
 void err_cannotsendtochan(struct client_data *client, const char *channel) // 404
 {
        copy_strf(&databuf, ":%s 404 %s %s :Cannot send to channel\r\n", hostname, client->nick, channel);
 }
+#if 0
 void err_toomanychannels(struct client_data *client, const char *channel) // 405
 {
        copy_strf(&databuf, ":%s 405 %s %s :You have joined too many channels\r\n", hostname, client->nick, channel);