From: Egor Date: Sun, 8 May 2022 09:11:26 +0000 (+0300) Subject: handle chan modes in PRIVMSG/NOTICE X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=bc90b8478c9e2d857893abd75e2b03cc6d8ecc8b;p=patchyircd.git handle chan modes in PRIVMSG/NOTICE --- diff --git a/irc.c b/irc.c index d9f3b11..f0b9b04 100644 --- 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")) { diff --git a/ircfmt.c b/ircfmt.c index f6f9932..07290d3 100644 --- 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);