/* * 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 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 /* UIRC_IRCV3 */ 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 /* UIRC_IRCV3*/ 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; }