Split files better
This commit is contained in:
parent
5dde15f3b6
commit
edd9790cdf
|
@ -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)
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "types.h"
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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
|
|
@ -15,11 +15,12 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "structs.h"
|
||||
#include <stdbool.h>
|
||||
#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);
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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
|
||||
};
|
||||
|
|
|
@ -16,16 +16,17 @@
|
|||
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#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
|
|
@ -15,35 +15,13 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "helpers.h"
|
||||
#include "types.h"
|
||||
#include "mappings.h"
|
||||
#include "structs.h"
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#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
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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;
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "../include/types.h"
|
||||
#include "../include/mappings.h"
|
||||
#include "misc.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#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
|
|
@ -15,11 +15,9 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "../include/uirc.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
static IRC_Message imassm_mesg;
|
||||
char* RESERVED = "*";
|
||||
void clear_assm(void)
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../include/types.h"
|
||||
#include "../include/mappings.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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;
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "../include/mappings.h"
|
||||
#include "../include/types.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#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
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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;
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "../include/types.h"
|
||||
#include "../include/mappings.h"
|
||||
#include "misc.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#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
|
401
src/uirc.c
401
src/uirc.c
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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;
|
||||
}
|
|
@ -21,5 +21,3 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
int safe_strcpy(char** dest, const char* src, size_t lef);
|
||||
int safe_charcpy(char** dest, const char c, size_t lef);
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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;
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "../include/types.h"
|
||||
#include "../include/mappings.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
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);
|
Reference in New Issue