]> PatchyGit - patchyircd.git/commitdiff
add user MODE command
authorEgor <egor@patchysicp.xyz>
Mon, 2 May 2022 16:52:53 +0000 (19:52 +0300)
committerEgor <egor@patchysicp.xyz>
Mon, 2 May 2022 16:52:53 +0000 (19:52 +0300)
common.h
irc.c
irc.h
util.c
util.h

index b8f5cd1..499bffc 100644 (file)
--- a/common.h
+++ b/common.h
@@ -3,6 +3,11 @@
 #include "NetSock/netsock.h"
 #include "config.h"
 
+#define UMODE_INVISIBLE 1
+#define UMODE_OPER 2
+#define UMODE_LOPER 4
+#define UMODE_REGISTERED 8
+#define UMODE_WALLOPS 16
 struct client_data {
        SOCKET FD;
        char   type;
@@ -11,6 +16,7 @@ struct client_data {
        char   buf[2048];
        size_t bufLen;
        size_t bufCap;
+       char   umode;
 };
 extern struct client_data  *clients[CLIENTS];
 extern        fd_set       readfds;
diff --git a/irc.c b/irc.c
index 6a5fbc3..98fc751 100644 (file)
--- a/irc.c
+++ b/irc.c
@@ -74,7 +74,82 @@ int processPacket(struct client_data *client) {
                return 1;
        } else if(strncmp(packet, "PONG", 4) == 0) {
                // Do nothing
+       } else if(strncmp(packet, "MODE ", 5) == 0) {
+               char *p = packet+5;
+               char *start_nick = p;
+               while (*p != ' ' && *p != '\n')
+                       p++;
+               char *end_nick = p;
+               if (*end_nick == '\n') { // get mode
+                       *end_nick = '\0';
+                       if (*start_nick != '#') {
+                               struct client_data *cl = findClient(start_nick);
+                               if (!cl) {
+                                       append_strf(&databuf, ":irc.patchysicp.xyz 401 %s %s :No such nick/channel\n", client->nick, start_nick-1);
+                                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                                       return 0;
+                               }
+                               append_strf(&databuf, ":irc.patchysicp.xyz 221 %s +", client->nick);
+                               if (cl->umode & UMODE_INVISIBLE) append_str(&databuf, "i");
+                               if (cl->umode & UMODE_OPER) append_str(&databuf, "o");
+                               if (cl->umode & UMODE_LOPER) append_str(&databuf, "O");
+                               if (cl->umode & UMODE_REGISTERED) append_str(&databuf, "r");
+                               if (cl->umode & UMODE_WALLOPS) append_str(&databuf, "w");
+                               append_str(&databuf, "\n");
+                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                       } else {
+                               append_strf(&databuf, ":irc.patchysicp.xyz 324 %s %s +nt\n", client->nick, start_nick);
+                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                       }
+               } else { // set mode
+                       *end_nick = '\0';
+                       if (*start_nick != '#') {
+                               struct client_data *cl = findClient(start_nick);
+                               if (!cl) {
+                                       append_strf(&databuf, ":irc.patchysicp.xyz 401 %s %s :No such nick/channel\n", client->nick, start_nick-1);
+                                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                                       return 0;
+                               }
+                               if (client->FD != cl->FD) {
+                                       append_strf(&databuf, ":irc.patchysicp.xyz 502 %s :Can't change mode for other users\n", client->nick);
+                                       send_log(client->FD, databuf.buf, databuf.len, 0);
+                                       return 0;
+                               }
+                               if (*++p == ':')
+                                       p++;
+                               int off;
+                               switch (*p++) {
+                                       case '+': off = 0; break;
+                                       case '-': off = 1; break;
+                                       default:
+                                               *end_nick = ' ';
+                                               goto unknown;
+                               }
+                               while (*p != ' ' && *p != '\n') {
+                                       switch (*p) {
+                                       case 'i':
+                                               if (off) {
+                                                       append_strf(&databuf, ":irc.patchysicp.xyz MODE %s -i\n", client->nick);
+                                                       cl->umode &= ~UMODE_INVISIBLE;
+                                               } else {
+                                                       append_strf(&databuf, ":irc.patchysicp.xyz MODE %s +i\n", client->nick);
+                                                       cl->umode |= UMODE_INVISIBLE;
+                                               }
+                                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                                               break;
+                                       default:
+                                               append_strf(&databuf, ":irc.patchysicp.xyz 501 %s :Unknown MODE flag\n", client->nick);
+                                               send_log(client->FD, databuf.buf, databuf.len, 0);
+                                       }
+                                       p++;
+                               }
+                       } else {
+                               *end_nick = ' ';
+                               goto unknown;
+                       }
+               }
        } else {
+unknown:
                printf("Unknown packet: %s", packet);
                // Inform user of error
                append_str(&databuf, ":irc.patchysicp.xyz 421 ");
@@ -84,7 +159,6 @@ int processPacket(struct client_data *client) {
                send_log(client->FD, databuf.buf, databuf.len, 0);
                fflush(stdout);
        }
-       // End GitHub Copilot
        return 0;
 }
 
@@ -193,3 +267,13 @@ void setNick(struct client_data *client, char* nickname, size_t size) {
        client->nickLen = strlen(client->nick);
        return;
 }
+struct client_data *findClient(const char *nickname)
+{
+       for(int i=0; i<CLIENTS; i++) {
+               if(clients[i] == 0) continue;
+               if(strncmp(clients[i]->nick, nickname, 32) == 0) {
+                       return clients[i];
+               }
+       }
+       return NULL;
+}
diff --git a/irc.h b/irc.h
index a48cc8c..c3dedb0 100644 (file)
--- a/irc.h
+++ b/irc.h
@@ -9,6 +9,7 @@ int processPacket(struct client_data *client);
 void newUser(struct client_data *client);
 void sendMOTD(struct client_data *client);
 void setNick(struct client_data *client, char* nickname, size_t size);
+struct client_data *findClient(const char *nickname);
 extern struct dynarr databuf;
 
 #endif
diff --git a/util.c b/util.c
index f674f71..20f6881 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,9 +1,8 @@
 #include "util.h"
 #include <stdio.h>
 #include <string.h>
-
-void append_str(struct dynarr *d, const char *s){
-       int len = strlen(s);
+#include <stdarg.h>
+void append_strn(struct dynarr *d, const char *s, int len){
        if (d->len + len > d->cap){
                while (d->len + len > d->cap)
                        d->cap *= 2;
@@ -17,3 +16,28 @@ void append_str(struct dynarr *d, const char *s){
        d->buf[d->len] = 0;
        d->buf[d->cap] = 0;
 }
+void append_str(struct dynarr *d, const char *s){
+       append_strn(d, s, strlen(s));
+}
+void append_strf(struct dynarr *d, const char *s, ...){
+       va_list ap;
+       va_start(ap, s);
+       for (;;) {
+               char *end = strchr(s, '%');
+               if (!end) {
+                       append_str(d, s);
+                       break;
+               }
+               if (end[1] == 's') { // %s
+                       append_strn(d, s, end-s);
+                       append_str(d, va_arg(ap, char *));
+                       s = end + 2;
+               } else if (end[1] == '%') { // %%
+                       append_strn(d, s, end-s+1);
+                       s = end + 2;
+               } else { // invalid
+                       break;
+               }
+       }
+       va_end(ap);
+}
diff --git a/util.h b/util.h
index 2896a6d..1c0d235 100644 (file)
--- a/util.h
+++ b/util.h
@@ -7,3 +7,4 @@ struct dynarr {
 };
 
 void append_str(struct dynarr *d, const char *s);
+void append_strf(struct dynarr *d, const char *s, ...);