diff --git a/CMakeLists.txt b/CMakeLists.txt
index fa42e4f..158c6c3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,10 +18,15 @@ if ( BUILD_TESTS )
enable_testing()
add_subdirectory(tests)
endif()
-set(build_FILES src/uirc.c)
+set(build_FILES
+ src/assemblers.c
+ src/misc.c
+ src/tokenizers.c
+ src/validators.c
+)
if ( USE_HELPERS )
message("Helper functions are going to be built.")
- set(build_FILES src/uirc.c src/helpers.c)
+ set(build_FILES ${build_FILES} src/helpers.c)
endif()
add_library(uirc SHARED ${build_FILES})
set_property(TARGET uirc PROPERTY C_STANDARD 99)
diff --git a/include/functions.h b/include/functions.h
new file mode 100644
index 0000000..8534a3a
--- /dev/null
+++ b/include/functions.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
+ * Copyright (c) 2019, 2020 Alex-David Denes
+ *
+ * uIRC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uIRC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uIRC. If not, see .
+*/
+#include "types.h"
+#include
+#include
+
+#ifndef _UIRC_INCLUDED_FUNCT
+#define _UIRC_INCLUDED_FUNCT
+/* Tokenizers: They take a string in and point their struct element pointers at tokens and end tokens with '\0' */
+extern signed int Tok_mesg(char* str, IRC_Message* out);
+extern signed int Tok_user(char* str, IRC_User* out, bool useorig);
+#ifdef UIRC_IRCV3
+extern signed int Tok_tags(char* str, IRC_Tags* out);
+#endif
+
+/* Assemblers: They return the amount of bytes written and write directly at buf */
+extern signed int Assm_mesg(char* buf, IRC_Message* in, size_t len);
+extern signed int Assm_user(char* buf, IRC_User* in, size_t len, bool useorig);
+#ifdef UIRC_IRCV3
+extern signed int Assm_tags(char* buf, IRC_Tags* in, size_t len);
+#endif
+
+/* Validators: They check that the parsed message is valid and follows the standard */
+extern signed int Val_mesg(IRC_Message* mesg);
+extern signed int Val_channame(char* chan);
+extern signed int Val_type_nocrlf(char* str);
+extern signed int Val_type_nospcl(char* str);
+extern signed int Val_type_noblcm(char* str);
+
+/* Converters: They convert from one format to another */
+extern signed int Ircmd_stoi(char* str);
+#endif
diff --git a/include/helpers.h b/include/helpers.h
index 7d9234c..4c578c3 100644
--- a/include/helpers.h
+++ b/include/helpers.h
@@ -15,11 +15,12 @@
* You should have received a copy of the GNU General Public License
* along with uIRC. If not, see .
*/
-#include "structs.h"
#include
+#include "types.h"
#ifdef UIRC_HELPERS
-#ifndef _UIRC_HELPERS_INCLUDED
-#define _UIRC_HELPERS_INCLUDED
+
+#ifndef _UIRC_INCLUDED_HELPERS
+#define _UIRC_INCLUDED_HELPERS
extern IRC_Message* Assm_cmd_NICK(char* nick);
extern IRC_Message* Assm_cmd_USER(char* user, char* realname, int modes);
extern IRC_Message* Assm_cmd_PASS(char* password);
diff --git a/include/mappings.h b/include/mappings.h
index 3183d17..726e725 100644
--- a/include/mappings.h
+++ b/include/mappings.h
@@ -15,8 +15,8 @@
* You should have received a copy of the GNU General Public License
* along with uIRC. If not, see .
*/
-#ifndef _UIRC_ENUMS_INCLUDED
-#define _UIRC_ENUMS_INCLUDED
+#ifndef _UIRC_INCLUDED_ENUMS
+#define _UIRC_INCLUDED_ENUMS
#define ERR_UIRC_GENERIC -1
#define ERR_UIRC_NULL_ARGS -2
@@ -29,9 +29,11 @@
#define MBMASK_WALLOPS 2 /* 010 */
#define MBMASK_INVIS 4 /* 100 */
+extern const char* const IRC_Cmds[];
+
#define UIRC_FCMD ADMIN
enum commands {
- ADMIN,
+ ADMIN = 10,
AWAY,
CONNECT,
DIE,
@@ -94,7 +96,9 @@ enum commands {
WARN, /* https://ircv3.net/specs/extensions/standard-replies */
WEBIRC, /* https://ircv3.net/specs/extensions/webirc */
#define UIRC_LCMD WEBIRC
+
#else
+
#define UIRC_LCMD WHOWAS
#endif
};
diff --git a/include/structs.h b/include/types.h
similarity index 90%
rename from include/structs.h
rename to include/types.h
index afa4ede..bbaf995 100644
--- a/include/structs.h
+++ b/include/types.h
@@ -16,16 +16,17 @@
* along with uIRC. If not, see .
*/
#include
-#ifndef _UIRC_STRUCTS_INCLUDED
-#define _UIRC_STRUCTS_INCLUDED
+#ifndef _UIRC_INCLUDED_TYPES
+#define _UIRC_INCLUDED_TYPES
#ifdef UIRC_IRCV3
-typedef struct uirc_tag {
+typedef struct {
char* value; /* if present, it isn't NULL and if it has no value, it is "" (aka '\0') */
bool clientbound;
} IRC_Tag;
#endif
-typedef struct name {
+
+typedef struct {
char* nick;
char* user;
char* host;
@@ -35,8 +36,9 @@ typedef struct name {
/* This is how a full user source would look like
* NOTE: 'real (Real name)' may only be used in special contexts other than communication.
* nick!user%orig@host */
+
#ifdef UIRC_IRCV3
-typedef struct uirc_tags {
+typedef struct {
/* See https://ircv3.net/registry#tags for more information */
IRC_Tag account;
IRC_Tag batch;
@@ -49,7 +51,8 @@ typedef struct uirc_tags {
IRC_Tag reply;
} IRC_Tags;
#endif
-typedef struct uirc_message {
+
+typedef struct {
#ifdef UIRC_IRCV3
IRC_Tags tags;
#endif
diff --git a/include/uirc.h b/include/uirc.h
index 1a30692..c7c7e19 100644
--- a/include/uirc.h
+++ b/include/uirc.h
@@ -15,35 +15,13 @@
* You should have received a copy of the GNU General Public License
* along with uIRC. If not, see .
*/
+
#include "helpers.h"
+#include "types.h"
#include "mappings.h"
-#include "structs.h"
-#include
-#include
+#include "functions.h"
#ifndef UIRC_INCLUDED
#define UIRC_INCLUDED
-extern const char* const uirc_ircmd[];
-/* Tokenizers: They take a string in and point their struct element pointers at tokens and end tokens with '\0' */
-extern signed int Tok_mesg(char* str, IRC_Message* out);
-extern signed int Tok_user(char* str, IRC_User* out, bool useorig);
-#ifdef UIRC_IRCV3
-extern signed int Tok_tags(char* str, IRC_Tags* out);
-#endif
-
-/* Assemblers: They return the amount of bytes written and write directly at buf */
-extern signed int Assm_mesg(char* buf, IRC_Message* in, size_t len);
-extern signed int Assm_user(char* buf, IRC_User* in, size_t len, bool useorig);
-#ifdef UIRC_IRCV3
-extern signed int Assm_tags(char* buf, IRC_Tags* in, size_t len);
-#endif
-
-/* Validators: They check that the parsed message is valid and follows the standard */
-extern signed int Val_mesg(IRC_Message* mesg);
-extern signed int Val_channame(char* chan);
-extern signed int Val_type_nocrlf(char* str);
-extern signed int Val_type_nospcl(char* str);
-extern signed int Val_type_noblcm(char* str);
-
-extern signed int Ircmd_stoi(char* str);
+#define UIRC_VERSION 0.6
#endif
diff --git a/src/assemblers.c b/src/assemblers.c
new file mode 100644
index 0000000..54540c9
--- /dev/null
+++ b/src/assemblers.c
@@ -0,0 +1,139 @@
+/*
+ * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
+ * Copyright (c) 2019, 2020 Alex-David Denes
+ *
+ * uIRC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uIRC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uIRC. If not, see .
+*/
+#include "assemblers.h"
+
+signed int Assm_mesg(char* buf, IRC_Message* in, size_t len)
+{
+ if (buf == NULL || in == NULL)
+ return ERR_UIRC_BUFFER_ERR;
+ char* pos = buf;
+ unsigned int cnt;
+ signed int ret;
+#ifdef UIRC_IRCV3
+ if ((ret = Assm_tags(pos, &in->tags, len - (pos - buf))) >= 0)
+ pos += ret;
+ else
+ return ret;
+#endif
+ if (in->name.nick != NULL || in->name.host != NULL) {
+ if (!safe_charcpy(&pos, ':', len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ if ((ret = Assm_user(pos, &in->name, len - (pos - buf), false)) <= 0)
+ return ret;
+ else
+ pos += ret;
+ if (!safe_charcpy(&pos, ' ', len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ }
+ if ((IRC_Cmds[in->cmd] != NULL) && len - (pos - buf) > (cnt = strlen(IRC_Cmds[in->cmd])) + 1 && strcpy(pos, IRC_Cmds[in->cmd]) != NULL)
+ pos += cnt;
+ else
+ return ERR_UIRC_GENERIC;
+ for (unsigned int i = 0; i < 14 && in->args[i] != NULL; i++) {
+ if (len - (pos - buf) > strlen(in->args[i]) + 2 && (cnt = snprintf(pos, len - (pos - buf), " %s", in->args[i])) > 0)
+ pos += cnt;
+ else
+ return ERR_UIRC_BUFFER_ERR;
+ }
+ if (in->trailing != NULL) {
+ if (len - (pos - buf) > strlen(in->trailing) + 3 && (cnt = snprintf(pos, len - (pos - buf), " :%s", in->trailing)) > 0)
+ pos += cnt;
+ else
+ return ERR_UIRC_GENERIC;
+ }
+ if (!safe_strcpy(&pos, "\r\n", len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ return pos - buf;
+}
+
+#ifdef UIRC_IRCV3
+signed int Assm_tags(char* buf, IRC_Tags* in, size_t len)
+{
+ if (buf == NULL || in == NULL)
+ return ERR_UIRC_NULL_ARGS;
+ char* pos = buf;
+ struct tagmapping tagmps[] = {
+ {.name = "time", .assg = &in->time},
+ {.name = "account", .assg = &in->account},
+ {.name = "batch", .assg = &in->batch},
+ {.name = "label", .assg = &in->label},
+ {.name = "msgid", .assg = &in->msgid},
+ {.name = "multiline-concat", .assg = &in->multiline_concat},
+ {.name = "typing", .assg = &in->typing},
+ {.name = "react", .assg = &in->react},
+ {.name = "reply", .assg = &in->reply}};
+ for (unsigned int i = 0; i < sizeof(tagmps) / sizeof(struct tagmapping); i++) {
+ if ((*tagmps[i].assg).value != NULL) {
+ if (pos == buf) {
+ if (!safe_charcpy(&pos, '@', len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ } else {
+ if (!safe_charcpy(&pos, ';', len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ }
+ if ((*tagmps[i].assg).clientbound) {
+ if (!safe_charcpy(&pos, '+', len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ }
+ if (!safe_strcpy(&pos, tagmps[i].name, len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ if (*(*tagmps[i].assg).value != '\0') {
+ if (!safe_charcpy(&pos, '=', len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ if (!safe_strcpy(&pos, (*tagmps[i].assg).value, len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ }
+ }
+ }
+ return pos - buf;
+}
+#endif
+
+signed int Assm_user(char* buf, IRC_User* in, size_t len, bool useorig)
+{
+ if (buf == NULL || in == NULL)
+ return ERR_UIRC_NULL_ARGS;
+ char* pos = buf;
+ if (in->nick == NULL && in->host != NULL) {
+ if (!safe_strcpy(&pos, in->host, len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ } else if (in->nick != NULL) {
+ if (!safe_strcpy(&pos, in->nick, len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ if (in->user != NULL) {
+ if (!safe_charcpy(&pos, '!', len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ if (!safe_strcpy(&pos, in->user, len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ }
+ if (useorig && in->orig != NULL) {
+ if (!safe_charcpy(&pos, '%', len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ if (!safe_strcpy(&pos, in->orig, len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ }
+ if (in->host != NULL) {
+ if (!safe_charcpy(&pos, '@', len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ if (!safe_strcpy(&pos, in->host, len - (pos - buf)))
+ return ERR_UIRC_BUFFER_ERR;
+ }
+ } else
+ return ERR_UIRC_NULL_ARGS;
+ return pos - buf;
+}
diff --git a/src/assemblers.h b/src/assemblers.h
new file mode 100644
index 0000000..1a02570
--- /dev/null
+++ b/src/assemblers.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
+ * Copyright (c) 2019, 2020 Alex-David Denes
+ *
+ * uIRC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uIRC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uIRC. If not, see .
+*/
+#include "../include/types.h"
+#include "../include/mappings.h"
+#include "misc.h"
+#include
+#include
+
+#ifndef _UIRC_INCLUDED_ASSM
+#define _UIRC_INCLUDED_ASSM
+signed int Assm_mesg(char* buf, IRC_Message* in, size_t len);
+
+#ifdef UIRC_IRCV3
+signed int Assm_tags(char* buf, IRC_Tags* in, size_t len);
+#endif
+
+signed int Assm_user(char* buf, IRC_User* in, size_t len, bool useorig);
+#endif
diff --git a/src/helpers.c b/src/helpers.c
index 5459291..a41156e 100644
--- a/src/helpers.c
+++ b/src/helpers.c
@@ -15,11 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with uIRC. If not, see .
*/
-#include "../include/uirc.h"
-#include
-#include
-#include
-#include
+
+#include "helpers.h"
+
static IRC_Message imassm_mesg;
char* RESERVED = "*";
void clear_assm(void)
diff --git a/src/helpers.h b/src/helpers.h
new file mode 100644
index 0000000..4f620d8
--- /dev/null
+++ b/src/helpers.h
@@ -0,0 +1,77 @@
+/*
+ * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
+ * Copyright (c) 2019, 2020 Alex-David Denes
+ *
+ * uIRC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uIRC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uIRC. If not, see .
+*/
+
+#include "../include/types.h"
+#include "../include/mappings.h"
+#include
+#include
+#include
+#include
+
+#ifndef _UIRC_INCLUDED_ASSM
+#define _UIRC_INCLUDED_ASSM
+void clear_assm(void);
+IRC_Message* Assm_cmd_NICK(char* nick);
+IRC_Message* Assm_cmd_USER(char* user, char* realname, int modes);
+IRC_Message* Assm_cmd_PASS(char* password);
+IRC_Message* Assm_cmd_OPER(char* name, char* password);
+IRC_Message* Assm_cmd_MODE(char* nick, char* modes, char* modeparams);
+IRC_Message* Assm_cmd_SERVICE(char* nickname, char* distribution, char* type, char* info);
+IRC_Message* Assm_cmd_QUIT(char* mesg);
+IRC_Message* Assm_cmd_SQUIT(char* server, char* comment);
+IRC_Message* Assm_cmd_JOIN(char* channels, char* keys);
+IRC_Message* Assm_cmd_PART(char* channel, char* message);
+IRC_Message* Assm_cmd_TOPIC(char* channel, char* topic);
+IRC_Message* Assm_cmd_NAMES(char* channels, char* target);
+IRC_Message* Assm_cmd_LIST(char* channels, char* target);
+IRC_Message* Assm_cmd_INVITE(char* nick, char* channel);
+IRC_Message* Assm_cmd_KICK(char* channels, char* users, char* comment);
+IRC_Message* Assm_cmd_PRIVMSG(char* target, char* message);
+IRC_Message* Assm_cmd_NOTICE(char* target, char* text);
+IRC_Message* Assm_cmd_MOTD(char* target);
+IRC_Message* Assm_cmd_LUSERS(char* mask, char* target);
+IRC_Message* Assm_cmd_VERSION(char* target);
+IRC_Message* Assm_cmd_STATS(char* query, char* target);
+IRC_Message* Assm_cmd_LINKS(char* remoteserv, char* servmask);
+IRC_Message* Assm_cmd_TIME(char* target);
+IRC_Message* Assm_cmd_CONNECT(char* target, char* port, char* remote);
+IRC_Message* Assm_cmd_TRACE(char* target);
+IRC_Message* Assm_cmd_ADMIN(char* target);
+IRC_Message* Assm_cmd_INFO(char* target);
+IRC_Message* Assm_cmd_SERVLIST(char* mask, char* type);
+IRC_Message* Assm_cmd_SQUERY(char* servicename, char* text);
+IRC_Message* Assm_cmd_WHO(char* mask, bool oper);
+IRC_Message* Assm_cmd_WHOIS(char* target, char* mask);
+IRC_Message* Assm_cmd_WHOWAS(char* nick, char* count, char* target);
+IRC_Message* Assm_cmd_KILL(char* nick, char* comment);
+IRC_Message* Assm_cmd_PING(char* source, char* target);
+IRC_Message* Assm_cmd_PONG(char* source, char* target);
+IRC_Message* Assm_cmd_ERROR(char* message);
+IRC_Message* Assm_cmd_AWAY(char* mesg);
+IRC_Message* Assm_cmd_REHASH(void);
+IRC_Message* Assm_cmd_DIE(void);
+IRC_Message* Assm_cmd_RESTART(void);
+IRC_Message* Assm_cmd_SUMMON(char* user, char* target, char* channel);
+IRC_Message* Assm_cmd_USERS(char* target);
+IRC_Message* Assm_cmd_WALLOPS(char* text);
+IRC_Message* Assm_cmd_USERHOST(char* users[]);
+IRC_Message* Assm_cmd_ISON(char* users[]);
+
+void Tok_cmd_PING(IRC_Message* mesg, char** source, char** target);
+void Tok_FArgOpt(IRC_Message* mesg, char** optarg, char** reqarg);
+#endif
diff --git a/src/misc.c b/src/misc.c
new file mode 100644
index 0000000..90b767c
--- /dev/null
+++ b/src/misc.c
@@ -0,0 +1,116 @@
+/*
+ * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
+ * Copyright (c) 2019, 2020 Alex-David Denes
+ *
+ * uIRC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uIRC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uIRC. If not, see .
+*/
+#include "misc.h"
+
+const char* const IRC_Cmds[] = {
+ [ADMIN] = "ADMIN",
+ [AWAY] = "AWAY",
+ [CONNECT] = "CONNECT",
+ [DIE] = "DIE",
+ [ERROR] = "ERROR",
+ [INFO] = "INFO",
+ [INVITE] = "INVITE",
+ [ISON] = "ISON",
+ [JOIN] = "JOIN",
+ [KICK] = "KICK",
+ [KILL] = "KILL",
+ [LINKS] = "LINKS",
+ [LIST] = "LIST",
+ [LUSERS] = "LUSERS",
+ [MODE] = "MODE",
+ [MOTD] = "MOTD",
+ [NAMES] = "NAMES",
+ [NICK] = "NICK",
+ [NOTICE] = "NOTICE",
+ [OPER] = "OPER",
+ [PART] = "PART",
+ [PASS] = "PASS",
+ [PING] = "PING",
+ [PONG] = "PONG",
+ [PRIVMSG] = "PRIVMSG",
+ [QUIT] = "QUIT",
+ [REHASH] = "REHASH",
+ [RESTART] = "RESTART",
+ [SERVER] = "SERVER",
+ [SERVICE] = "SERVICE",
+ [SERVLIST] = "SERVLIST",
+ [SQUERY] = "SQUERY",
+ [SQUIT] = "SQUIT",
+ [STATS] = "STATS",
+ [SUMMON] = "SUMMON",
+ [TIME] = "TIME",
+ [TOPIC] = "TOPIC",
+ [TRACE] = "TRACE",
+ [USERHOST] = "USERHOST",
+ [USERS] = "USERS",
+ [USER] = "USER",
+ [VERSION] = "VERSION",
+ [WALLOPS] = "WALLOPS",
+ [WHOIS] = "WHOIS",
+ [WHOWAS] = "WHOWAS",
+ [WHO] = "WHO",
+#ifdef UIRC_IRCV3
+ [ACCOUNT] = "ACCOUNT",
+ [ACC] = "ACC",
+ [ACK] = "ACK",
+ [AUTHENTICATE] = "AUTHENTICATE",
+ [BATCH] = "BATCH",
+ [CAP] = "CAP",
+ [CHGHOST] = "CHGHOST",
+ [FAIL] = "FAIL",
+ [MONITOR] = "MONITOR",
+ [NOTE] = "NOTE",
+ [RENAME] = "RENAME",
+ [RESUME] = "RESUME",
+ [SETNAME] = "SETNAME",
+ [WARN] = "WARN",
+ [WEBIRC] = "WEBIRC"
+#endif
+};
+
+signed int Ircmd_stoi(char* str)
+{
+ if (str == NULL)
+ return ERR_UIRC_NULL_ARGS;
+ for (unsigned short i = UIRC_FCMD; i <= UIRC_LCMD; i++) {
+ if (IRC_Cmds[i] != NULL && strcmp(IRC_Cmds[i], str) == 0)
+ return i;
+ }
+ return ERR_UIRC_UNKNOWN_TOKEN;
+}
+
+int safe_strcpy(char** dest, const char* src, size_t lef)
+{
+ size_t cnt;
+ if (lef > (cnt = strlen(src)) + 1) {
+ strcpy(*dest, src);
+ *dest += cnt;
+ return cnt;
+ } else
+ return 0;
+}
+
+int safe_charcpy(char** dest, const char c, size_t lef)
+{
+ if (lef > 1) {
+ *(*dest)++ = c;
+ **dest = '\0';
+ return 1;
+ } else
+ return 0;
+}
diff --git a/src/misc.h b/src/misc.h
new file mode 100644
index 0000000..851d947
--- /dev/null
+++ b/src/misc.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
+ * Copyright (c) 2019, 2020 Alex-David Denes
+ *
+ * uIRC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uIRC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uIRC. If not, see .
+*/
+#include "../include/mappings.h"
+#include "../include/types.h"
+#include
+#include
+
+#ifndef _UIRC_INCLUDED_MISC
+#define _UIRC_INCLUDED_MISC
+
+#ifdef UIRC_IRCV3
+struct tagmapping {
+ const char* const name;
+ IRC_Tag* assg;
+};
+#endif
+
+signed int Ircmd_stoi(char* str);
+int safe_strcpy(char** dest, const char* src, size_t lef);
+int safe_charcpy(char** dest, const char c, size_t lef);
+#endif
diff --git a/src/tokenizers.c b/src/tokenizers.c
new file mode 100644
index 0000000..293b41f
--- /dev/null
+++ b/src/tokenizers.c
@@ -0,0 +1,117 @@
+/*
+ * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
+ * Copyright (c) 2019, 2020 Alex-David Denes
+ *
+ * uIRC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uIRC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uIRC. If not, see .
+*/
+#include "tokenizers.h"
+
+signed int Tok_mesg(char* str, IRC_Message* out)
+{
+ if (str == NULL || out == NULL)
+ return ERR_UIRC_NULL_ARGS;
+ int ret;
+ char *progr = str, *command;
+#ifdef UIRC_IRCV3
+ if (*progr == '@') {
+ char* tags;
+ if ((tags = strtok_r(progr, " ", &progr)) != NULL) {
+ if ((ret = Tok_tags(tags, &out->tags)) < 0)
+ return ret;
+ } else
+ return ERR_UIRC_INVALID_FORMAT;
+ }
+#endif
+ if (*progr == ':') {
+ char* prefix;
+ if ((prefix = strtok_r(progr, " ", &progr)) != NULL) {
+ if ((ret = Tok_user(prefix, &out->name, false)) < 0)
+ return ret;
+ } else
+ return ERR_UIRC_INVALID_FORMAT;
+ }
+
+ if ((command = strtok_r(NULL, " ", &progr)) != NULL) {
+ if (!(out->cmd = (isalpha(*command)) ? Ircmd_stoi(command) : atoi(command)))
+ return ERR_UIRC_UNKNOWN_TOKEN;
+ } else {
+ return ERR_UIRC_INVALID_FORMAT;
+ }
+
+ int i;
+ for (i = 0; *progr != ':' && i < 14 && *progr; i++) {
+ if ((out->args[i] = strtok_r(NULL, " ", &progr)) == NULL)
+ return ERR_UIRC_INVALID_FORMAT;
+ }
+ out->args[i] = NULL;
+ if (*progr)
+ out->trailing = (*progr == ':') ? progr + 1 : progr;
+ return 1;
+}
+
+#ifdef UIRC_IRCV3
+signed int Tok_tags(char* str, IRC_Tags* out)
+{
+ if (str == NULL || out == NULL)
+ return ERR_UIRC_NULL_ARGS;
+ char *cval, *cpos = str, *ctag = NULL;
+ bool clientbound;
+ const struct tagmapping tagmps[] = {
+ {.name = "time", .assg = &out->time},
+ {.name = "account", .assg = &out->account},
+ {.name = "batch", .assg = &out->batch},
+ {.name = "label", .assg = &out->label},
+ {.name = "msgid", .assg = &out->msgid},
+ {.name = "multiline-concat", .assg = &out->multiline_concat},
+ {.name = "typing", .assg = &out->typing},
+ {.name = "react", .assg = &out->react},
+ {.name = "reply", .assg = &out->reply}};
+ if (*cpos == '@')
+ cpos++;
+ while ((ctag = strtok_r(NULL, "; ", &cpos)) != NULL) {
+ clientbound = false;
+ if (*ctag == '+') {
+ ctag++;
+ clientbound = true;
+ }
+ if ((cval = strchr(ctag, '=')) != NULL)
+ *(cval++) = '\0';
+ for (unsigned int i = 0; i < sizeof(tagmps) / sizeof(struct tagmapping); i++) {
+ if (!strcmp(ctag, tagmps[i].name)) {
+ /* If the tag is present we point it to the value if given, or to the delimiter ('\0')
+ * This is done for a few reasons. First, we have a non-null address so we show that
+ * the tag is present and second, we have no value that way
+ */
+ (*tagmps[i].assg).value = (cval != NULL) ? cval : ctag + strlen(ctag);
+ (*tagmps[i].assg).clientbound = clientbound;
+ }
+ }
+ }
+ return 1;
+}
+#endif
+
+signed int Tok_user(char* str, IRC_User* out, bool useorig)
+{
+ char* pos = (*str == ':') ? str + 1 : str;
+ if ((out->host = strchr(pos, '@')) != NULL)
+ *(out->host++) = '\0';
+ if (useorig && (out->orig = strchr(pos, '%')) != NULL)
+ *(out->orig++) = '\0';
+ if ((out->user = strchr(pos, '!')) != NULL) /* RFC2812 says this cannot be here without the host but RFC1459 says it can, we accept both options */
+ *((char*)out->user++) = '\0';
+ if (!*(out->nick = pos)) /* NOTE: This may be the server instead of a nick according to RFC2812, it is left to the library out to decide how to interpret this based on the context. */
+ return ERR_UIRC_INVALID_FORMAT;
+ return 1;
+}
diff --git a/src/tokenizers.h b/src/tokenizers.h
new file mode 100644
index 0000000..7d5a584
--- /dev/null
+++ b/src/tokenizers.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
+ * Copyright (c) 2019, 2020 Alex-David Denes
+ *
+ * uIRC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uIRC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uIRC. If not, see .
+*/
+#include "../include/types.h"
+#include "../include/mappings.h"
+#include "misc.h"
+#include
+#include
+#include
+#include
+
+#ifndef _UIRC_INCLUDED_TKNIZ
+#define _UIRC_INCLUDED_TKNIZ
+signed int Tok_mesg(char* str, IRC_Message* out);
+
+#ifdef UIRC_IRCV3
+signed int Tok_tags(char* str, IRC_Tags* out);
+#endif
+
+signed int Tok_user(char* str, IRC_User* out, bool useorig);
+#endif
diff --git a/src/uirc.c b/src/uirc.c
deleted file mode 100644
index f74d7ef..0000000
--- a/src/uirc.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
- * Copyright (c) 2019, 2020 Alex-David Denes
- *
- * uIRC is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * any later version.
- *
- * uIRC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with uIRC. If not, see .
-*/
-#include "uirc.h"
-
-const char* const uirc_ircmd[] = {
- [ADMIN] = "ADMIN",
- [AWAY] = "AWAY",
- [CONNECT] = "CONNECT",
- [DIE] = "DIE",
- [ERROR] = "ERROR",
- [INFO] = "INFO",
- [INVITE] = "INVITE",
- [ISON] = "ISON",
- [JOIN] = "JOIN",
- [KICK] = "KICK",
- [KILL] = "KILL",
- [LINKS] = "LINKS",
- [LIST] = "LIST",
- [LUSERS] = "LUSERS",
- [MODE] = "MODE",
- [MOTD] = "MOTD",
- [NAMES] = "NAMES",
- [NICK] = "NICK",
- [NOTICE] = "NOTICE",
- [OPER] = "OPER",
- [PART] = "PART",
- [PASS] = "PASS",
- [PING] = "PING",
- [PONG] = "PONG",
- [PRIVMSG] = "PRIVMSG",
- [QUIT] = "QUIT",
- [REHASH] = "REHASH",
- [RESTART] = "RESTART",
- [SERVER] = "SERVER",
- [SERVICE] = "SERVICE",
- [SERVLIST] = "SERVLIST",
- [SQUERY] = "SQUERY",
- [SQUIT] = "SQUIT",
- [STATS] = "STATS",
- [SUMMON] = "SUMMON",
- [TIME] = "TIME",
- [TOPIC] = "TOPIC",
- [TRACE] = "TRACE",
- [USERHOST] = "USERHOST",
- [USERS] = "USERS",
- [USER] = "USER",
- [VERSION] = "VERSION",
- [WALLOPS] = "WALLOPS",
- [WHOIS] = "WHOIS",
- [WHOWAS] = "WHOWAS",
- [WHO] = "WHO",
-#ifdef UIRC_IRCV3
- [ACCOUNT] = "ACCOUNT",
- [ACC] = "ACC",
- [ACK] = "ACK",
- [AUTHENTICATE] = "AUTHENTICATE",
- [BATCH] = "BATCH",
- [CAP] = "CAP",
- [CHGHOST] = "CHGHOST",
- [FAIL] = "FAIL",
- [MONITOR] = "MONITOR",
- [NOTE] = "NOTE",
- [RENAME] = "RENAME",
- [RESUME] = "RESUME",
- [SETNAME] = "SETNAME",
- [WARN] = "WARN",
- [WEBIRC] = "WEBIRC"
-#endif
-};
-
-#ifdef UIRC_IRCV3
-struct tagmapping {
- const char* const name;
- IRC_Tag* assg;
-};
-#endif
-signed int Ircmd_stoi(char* str)
-{
- if (str == NULL)
- return ERR_UIRC_NULL_ARGS;
- for (unsigned short i = UIRC_FCMD; i <= UIRC_LCMD; i++) {
- if (uirc_ircmd[i] != NULL && strcmp(uirc_ircmd[i], str) == 0)
- return i;
- }
- return ERR_UIRC_UNKNOWN_TOKEN;
-}
-signed int Assm_mesg(char* buf, IRC_Message* in, size_t len)
-{
- if (buf == NULL || in == NULL)
- return ERR_UIRC_BUFFER_ERR;
- char* pos = buf;
- unsigned int cnt;
- signed int ret;
-
-#ifdef UIRC_IRCV3
- if ((ret = Assm_tags(pos, &in->tags, len - (pos - buf))) >= 0)
- pos += ret;
- else
- return ret;
-#endif
- if (in->name.nick != NULL || in->name.host != NULL) {
- if (!safe_charcpy(&pos, ':', len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- if ((ret = Assm_user(pos, &in->name, len - (pos - buf), false)) <= 0)
- return ret;
- else
- pos += ret;
- if (!safe_charcpy(&pos, ' ', len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- }
- if ((uirc_ircmd[in->cmd] != NULL) && len - (pos - buf) > (cnt = strlen(uirc_ircmd[in->cmd])) + 1 && strcpy(pos, uirc_ircmd[in->cmd]) != NULL)
- pos += cnt;
- else
- return ERR_UIRC_GENERIC;
- for (unsigned int i = 0; i < 14 && in->args[i] != NULL; i++) {
- if (len - (pos - buf) > strlen(in->args[i]) + 2 && (cnt = snprintf(pos, len - (pos - buf), " %s", in->args[i])) > 0)
- pos += cnt;
- else
- return ERR_UIRC_BUFFER_ERR;
- }
- if (in->trailing != NULL) {
- if (len - (pos - buf) > strlen(in->trailing) + 3 && (cnt = snprintf(pos, len - (pos - buf), " :%s", in->trailing)) > 0)
- pos += cnt;
- else
- return ERR_UIRC_GENERIC;
- }
- if (!safe_strcpy(&pos, "\r\n", len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- return pos - buf;
-}
-#ifdef UIRC_IRCV3
-signed int Assm_tags(char* buf, IRC_Tags* in, size_t len)
-{
- if (buf == NULL || in == NULL)
- return ERR_UIRC_NULL_ARGS;
- char* pos = buf;
- struct tagmapping tagmps[] = {
- {.name = "time", .assg = &in->time},
- {.name = "account", .assg = &in->account},
- {.name = "batch", .assg = &in->batch},
- {.name = "label", .assg = &in->label},
- {.name = "msgid", .assg = &in->msgid},
- {.name = "multiline-concat", .assg = &in->multiline_concat},
- {.name = "typing", .assg = &in->typing},
- {.name = "react", .assg = &in->react},
- {.name = "reply", .assg = &in->reply}};
- for (unsigned int i = 0; i < sizeof(tagmps) / sizeof(struct tagmapping); i++) {
- if ((*tagmps[i].assg).value != NULL) {
- if (pos == buf) {
- if (!safe_charcpy(&pos, '@', len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- } else {
- if (!safe_charcpy(&pos, ';', len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- }
- if ((*tagmps[i].assg).clientbound) {
- if (!safe_charcpy(&pos, '+', len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- }
- if (!safe_strcpy(&pos, tagmps[i].name, len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- if (*(*tagmps[i].assg).value != '\0') {
- if (!safe_charcpy(&pos, '=', len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- if (!safe_strcpy(&pos, (*tagmps[i].assg).value, len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- }
- }
- }
- return pos - buf;
-}
-#endif
-signed int Assm_user(char* buf, IRC_User* in, size_t len, bool useorig)
-{
- if (buf == NULL || in == NULL)
- return ERR_UIRC_NULL_ARGS;
- char* pos = buf;
- if (in->nick == NULL && in->host != NULL) {
- if (!safe_strcpy(&pos, in->host, len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- } else if (in->nick != NULL) {
- if (!safe_strcpy(&pos, in->nick, len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- if (in->user != NULL) {
- if (!safe_charcpy(&pos, '!', len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- if (!safe_strcpy(&pos, in->user, len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- }
- if (useorig && in->orig != NULL) {
- if (!safe_charcpy(&pos, '%', len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- if (!safe_strcpy(&pos, in->orig, len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- }
- if (in->host != NULL) {
- if (!safe_charcpy(&pos, '@', len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- if (!safe_strcpy(&pos, in->host, len - (pos - buf)))
- return ERR_UIRC_BUFFER_ERR;
- }
- } else
- return ERR_UIRC_NULL_ARGS;
- return pos - buf;
-}
-signed int Tok_mesg(char* str, IRC_Message* out)
-{
- if (str == NULL || out == NULL)
- return ERR_UIRC_NULL_ARGS;
- int ret;
- char *progr = str, *command;
-#ifdef UIRC_IRCV3
- if (*progr == '@') {
- char* tags;
- if ((tags = strtok_r(progr, " ", &progr)) != NULL) {
- if ((ret = Tok_tags(tags, &out->tags)) < 0)
- return ret;
- } else
- return ERR_UIRC_INVALID_FORMAT;
- }
-#endif
- if (*progr == ':') {
- char* prefix;
- if ((prefix = strtok_r(progr, " ", &progr)) != NULL) {
- if ((ret = Tok_user(prefix, &out->name, false)) < 0)
- return ret;
- } else
- return ERR_UIRC_INVALID_FORMAT;
- }
-
- if ((command = strtok_r(NULL, " ", &progr)) != NULL) {
- if (!(out->cmd = (isalpha(*command)) ? Ircmd_stoi(command) : atoi(command)))
- return ERR_UIRC_UNKNOWN_TOKEN;
- } else {
- return ERR_UIRC_INVALID_FORMAT;
- }
-
- int i;
- for (i = 0; *progr != ':' && i < 14 && *progr; i++) {
- if ((out->args[i] = strtok_r(NULL, " ", &progr)) == NULL)
- return ERR_UIRC_INVALID_FORMAT;
- }
- out->args[i] = NULL;
- if (*progr)
- out->trailing = (*progr == ':') ? progr + 1 : progr;
- return 1;
-}
-#ifdef UIRC_IRCV3
-signed int Tok_tags(char* str, IRC_Tags* out)
-{
- if (str == NULL || out == NULL)
- return ERR_UIRC_NULL_ARGS;
- char *cval, *cpos = str, *ctag = NULL;
- bool clientbound;
- const struct tagmapping tagmps[] = {
- {.name = "time", .assg = &out->time},
- {.name = "account", .assg = &out->account},
- {.name = "batch", .assg = &out->batch},
- {.name = "label", .assg = &out->label},
- {.name = "msgid", .assg = &out->msgid},
- {.name = "multiline-concat", .assg = &out->multiline_concat},
- {.name = "typing", .assg = &out->typing},
- {.name = "react", .assg = &out->react},
- {.name = "reply", .assg = &out->reply}};
- if (*cpos == '@')
- cpos++;
- while ((ctag = strtok_r(NULL, "; ", &cpos)) != NULL) {
- clientbound = false;
- if (*ctag == '+') {
- ctag++;
- clientbound = true;
- }
- if ((cval = strchr(ctag, '=')) != NULL)
- *(cval++) = '\0';
- for (unsigned int i = 0; i < sizeof(tagmps) / sizeof(struct tagmapping); i++) {
- if (!strcmp(ctag, tagmps[i].name)) {
- /* If the tag is present we point it to the value if given, or to the delimiter ('\0')
- * This is done for a few reasons. First, we have a non-null address so we show that
- * the tag is present and second, we have no value that way
- */
- (*tagmps[i].assg).value = (cval != NULL) ? cval : ctag + strlen(ctag);
- (*tagmps[i].assg).clientbound = clientbound;
- }
- }
- }
- return 1;
-}
-#endif
-signed int Tok_user(char* str, IRC_User* out, bool useorig)
-{
- char* pos = (*str == ':') ? str + 1 : str;
- if ((out->host = strchr(pos, '@')) != NULL)
- *(out->host++) = '\0';
- if (useorig && (out->orig = strchr(pos, '%')) != NULL)
- *(out->orig++) = '\0';
- if ((out->user = strchr(pos, '!')) != NULL) /* RFC2812 says this cannot be here without the host but RFC1459 says it can, we accept both options */
- *((char*)out->user++) = '\0';
- if (!*(out->nick = pos)) /* NOTE: This may be the server instead of a nick according to RFC2812, it is left to the library out to decide how to interpret this based on the context. */
- return ERR_UIRC_INVALID_FORMAT;
- return 1;
-}
-signed int Val_mesg(IRC_Message* mesg)
-{
- if (mesg == NULL)
- return ERR_UIRC_NULL_ARGS;
- for (unsigned int i = 0; i < 14 && mesg->args[i] != NULL; i++) {
- if (Val_type_nocrlf(mesg->args[i]) != 1)
- return ERR_UIRC_VAL_FAILED;
- if (Val_type_nospcl(mesg->args[i]) != 1)
- return ERR_UIRC_VAL_FAILED;
- }
- if (mesg->trailing != NULL) {
- if (Val_type_nocrlf(mesg->trailing) != 1)
- return ERR_UIRC_VAL_FAILED;
- }
- return 1;
-}
-signed int Val_type_nocrlf(char* str)
-{
- if (str == NULL)
- return ERR_UIRC_NULL_ARGS;
- for (; *str; str++) {
- if (*str == '\r' || *str == '\n')
- return 0;
- }
- return 1;
-}
-signed int Val_type_nospcl(char* str)
-{
- if (str == NULL)
- return ERR_UIRC_NULL_ARGS;
- for (; *str; str++) {
- if (*str == ' ' || *str == ':')
- return 0;
- }
- return 1;
-}
-signed int Val_type_noblcm(char* str)
-{
- if (str == NULL)
- return ERR_UIRC_NULL_ARGS;
- for (; *str; str++) {
- if (*str == '\a' || *str == ',')
- return 0;
- }
- return 1;
-}
-signed int Val_channame(char* chan)
-{
- if (chan == NULL)
- return ERR_UIRC_NULL_ARGS;
- if (*chan != '#' || *chan != '+' || *chan != '!' || *chan != '&')
- return 0;
- char* clps = ++chan;
- if ((clps = strchr(chan, ':')) != NULL) {
- *clps = '\0';
- if (Val_type_nospcl(chan) != 1 || Val_type_nocrlf(chan) != 1 || Val_type_noblcm(chan) != 1) {
- *clps = ':';
- return 0;
- }
- *clps = ':';
- chan = ++clps;
- }
- if (Val_type_nospcl(chan) != 1 || Val_type_nocrlf(chan) != 1 || Val_type_noblcm(chan) != 1)
- return 0;
- return 1;
-}
-int safe_strcpy(char** dest, const char* src, size_t lef)
-{
- size_t cnt;
- if (lef > (cnt = strlen(src)) + 1) {
- strcpy(*dest, src);
- *dest += cnt;
- return cnt;
- } else
- return 0;
-}
-int safe_charcpy(char** dest, const char c, size_t lef)
-{
- if (lef > 1) {
- *(*dest)++ = c;
- **dest = '\0';
- return 1;
- } else
- return 0;
-}
diff --git a/src/uirc.h b/src/uirc.h
index 88b7fee..d16f6a5 100644
--- a/src/uirc.h
+++ b/src/uirc.h
@@ -21,5 +21,3 @@
#include
#include
#include
-int safe_strcpy(char** dest, const char* src, size_t lef);
-int safe_charcpy(char** dest, const char c, size_t lef);
diff --git a/src/validators.c b/src/validators.c
new file mode 100644
index 0000000..0db85f9
--- /dev/null
+++ b/src/validators.c
@@ -0,0 +1,90 @@
+
+/*
+ * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
+ * Copyright (c) 2019, 2020 Alex-David Denes
+ *
+ * uIRC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uIRC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uIRC. If not, see .
+*/
+#include "validators.h"
+
+signed int Val_mesg(IRC_Message* mesg)
+{
+ if (mesg == NULL)
+ return ERR_UIRC_NULL_ARGS;
+ for (unsigned int i = 0; i < 14 && mesg->args[i] != NULL; i++) {
+ if (Val_type_nocrlf(mesg->args[i]) != 1)
+ return ERR_UIRC_VAL_FAILED;
+ if (Val_type_nospcl(mesg->args[i]) != 1)
+ return ERR_UIRC_VAL_FAILED;
+ }
+ if (mesg->trailing != NULL) {
+ if (Val_type_nocrlf(mesg->trailing) != 1)
+ return ERR_UIRC_VAL_FAILED;
+ }
+ return 1;
+}
+
+signed int Val_type_nocrlf(char* str)
+{
+ if (str == NULL)
+ return ERR_UIRC_NULL_ARGS;
+ for (; *str; str++) {
+ if (*str == '\r' || *str == '\n')
+ return 0;
+ }
+ return 1;
+}
+
+signed int Val_type_nospcl(char* str)
+{
+ if (str == NULL)
+ return ERR_UIRC_NULL_ARGS;
+ for (; *str; str++) {
+ if (*str == ' ' || *str == ':')
+ return 0;
+ }
+ return 1;
+}
+
+signed int Val_type_noblcm(char* str)
+{
+ if (str == NULL)
+ return ERR_UIRC_NULL_ARGS;
+ for (; *str; str++) {
+ if (*str == '\a' || *str == ',')
+ return 0;
+ }
+ return 1;
+}
+
+signed int Val_channame(char* chan)
+{
+ if (chan == NULL)
+ return ERR_UIRC_NULL_ARGS;
+ if (*chan != '#' || *chan != '+' || *chan != '!' || *chan != '&')
+ return 0;
+ char* clps = ++chan;
+ if ((clps = strchr(chan, ':')) != NULL) {
+ *clps = '\0';
+ if (Val_type_nospcl(chan) != 1 || Val_type_nocrlf(chan) != 1 || Val_type_noblcm(chan) != 1) {
+ *clps = ':';
+ return 0;
+ }
+ *clps = ':';
+ chan = ++clps;
+ }
+ if (Val_type_nospcl(chan) != 1 || Val_type_nocrlf(chan) != 1 || Val_type_noblcm(chan) != 1)
+ return 0;
+ return 1;
+}
diff --git a/src/validators.h b/src/validators.h
new file mode 100644
index 0000000..77ee137
--- /dev/null
+++ b/src/validators.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of uIRC. (https://git.redxen.eu/caskd/uIRC)
+ * Copyright (c) 2019, 2020 Alex-David Denes
+ *
+ * uIRC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uIRC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uIRC. If not, see .
+*/
+#include "../include/types.h"
+#include "../include/mappings.h"
+#include
+#include
+signed int Val_mesg(IRC_Message* mesg);
+signed int Val_type_nocrlf(char* str);
+signed int Val_type_nospcl(char* str);
+signed int Val_type_noblcm(char* str);
+signed int Val_channame(char* chan);