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 ");
send_log(client->FD, databuf.buf, databuf.len, 0);
fflush(stdout);
}
- // End GitHub Copilot
return 0;
}
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;
+}
#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;
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);
+}