From: Egor Date: Mon, 2 May 2022 16:52:53 +0000 (+0300) Subject: add user MODE command X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=622262fea6a8b4f960e50ba15758560438de7bfd;p=patchyircd.git add user MODE command --- diff --git a/common.h b/common.h index b8f5cd1..499bffc 100644 --- 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 --- 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; inick, nickname, 32) == 0) { + return clients[i]; + } + } + return NULL; +} diff --git a/irc.h b/irc.h index a48cc8c..c3dedb0 100644 --- 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 --- a/util.c +++ b/util.c @@ -1,9 +1,8 @@ #include "util.h" #include #include - -void append_str(struct dynarr *d, const char *s){ - int len = strlen(s); +#include +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 --- 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, ...);