This repository has been archived on 2021-04-17. You can view files and clone it, but cannot push or open issues or pull requests.
uIRC/src/assemblers.c

147 lines
5.0 KiB
C

/*
* 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 long Assm_mesg(char* buf, IRC_Message* in, size_t len)
{
if (buf == NULL || in == NULL)
return ERR_UIRC_BUFFER_ERR;
char* pos = buf;
signed long cnt, ret;
#ifdef UIRC_IRCV3
if ((ret = Assm_tags(pos, &in->tags, len - (unsigned long)(pos - buf))) < 0)
return ret;
else if (ret != 0) {
pos += ret;
if (!safe_charcpy(&pos, ' ', len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
}
#endif
if (in->name.nick != NULL || in->name.host != NULL) {
if (!safe_charcpy(&pos, ':', len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
if ((ret = Assm_user(pos, &in->name, len - (unsigned long)(pos - buf), false)) <= 0)
return ret;
else
pos += ret;
if (!safe_charcpy(&pos, ' ', len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
}
if (in->cmd < UIRC_FCMD || in->cmd > UIRC_LCMD) {
if ((cnt = snprintf(pos, 4, "%.3i", in->cmd)) == 3)
pos += cnt;
else
return ERR_UIRC_UNKNOWN_TOKEN;
} else {
if (IRC_Cmds[in->cmd] != NULL) {
size_t cmdlen = strlen(IRC_Cmds[in->cmd]);
if (len - (unsigned long)(pos - buf) > cmdlen && strcpy(pos, IRC_Cmds[in->cmd]) != NULL)
pos += cmdlen;
else
return ERR_UIRC_UNKNOWN_TOKEN;
}
}
for (unsigned int i = 0; in->args[i] != NULL; i++) {
if (len - (unsigned long)(pos - buf) > strlen(in->args[i]) + 2 && (cnt = snprintf(pos, len - (unsigned long)(pos - buf), (in->args[i + 1] == NULL && in->trailing) ? " :%s" : " %s", in->args[i])) > 0)
pos += cnt;
else
return ERR_UIRC_BUFFER_ERR;
}
if (!safe_strcpy(&pos, "\r\n", len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
return pos - buf;
}
#ifdef UIRC_IRCV3
signed long 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 - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
} else {
if (!safe_charcpy(&pos, ';', len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
}
if ((*tagmps[i].assg).clientbound) {
if (!safe_charcpy(&pos, '+', len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
}
if (!safe_strcpy(&pos, tagmps[i].name, len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
if (*(*tagmps[i].assg).value != '\0') {
if (!safe_charcpy(&pos, '=', len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, (*tagmps[i].assg).value, len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
}
}
}
return pos - buf;
}
#endif
signed long 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 - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
} else if (in->nick != NULL) {
if (!safe_strcpy(&pos, in->nick, len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
if (in->user != NULL) {
if (!safe_charcpy(&pos, '!', len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->user, len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
}
if (useorig && in->orig != NULL) {
if (!safe_charcpy(&pos, '%', len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->orig, len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
}
if (in->host != NULL) {
if (!safe_charcpy(&pos, '@', len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->host, len - (unsigned long)(pos - buf)))
return ERR_UIRC_BUFFER_ERR;
}
} else
return ERR_UIRC_NULL_ARGS;
return pos - buf;
}