From edd9790cdf61196e36dc68576a780250ba3f83d1 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 22 Jul 2020 18:57:59 +0200 Subject: [PATCH] Split files better --- CMakeLists.txt | 9 +- include/functions.h | 47 ++++ include/helpers.h | 7 +- include/mappings.h | 10 +- include/{structs.h => types.h} | 15 +- include/uirc.h | 30 +-- src/assemblers.c | 139 ++++++++++++ src/assemblers.h | 33 +++ src/helpers.c | 8 +- src/helpers.h | 77 +++++++ src/misc.c | 116 ++++++++++ src/misc.h | 36 +++ src/tokenizers.c | 117 ++++++++++ src/tokenizers.h | 35 +++ src/uirc.c | 401 --------------------------------- src/uirc.h | 2 - src/validators.c | 90 ++++++++ src/validators.h | 26 +++ 18 files changed, 750 insertions(+), 448 deletions(-) create mode 100644 include/functions.h rename include/{structs.h => types.h} (90%) create mode 100644 src/assemblers.c create mode 100644 src/assemblers.h create mode 100644 src/helpers.h create mode 100644 src/misc.c create mode 100644 src/misc.h create mode 100644 src/tokenizers.c create mode 100644 src/tokenizers.h delete mode 100644 src/uirc.c create mode 100644 src/validators.c create mode 100644 src/validators.h 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);