diff --git a/.clang-tidy b/.clang-tidy index 6511921..c0cc988 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,180 +1,6 @@ --- -Checks: 'clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,-*,clang-analyzer-core.*,clang-analyzer-optin.performance.*,clang-analyzer-optin.portability.*,clang-analyzer-nullability.*,clang-analyzer-security.*,clang-analyzer-unix.*,bugprone-*,misc-*,performance-*,readability-*,-*,clang-analyzer-core.*,clang-analyzer-optin.performance.*,clang-analyzer-optin.portability.*,clang-analyzer-nullability.*,clang-analyzer-security.*,clang-analyzer-unix.*,bugprone-*,misc-*,performance-*,readability-*,-readability-isolate-declaration,-readability-else-after-return,-readability-braces-around-statements,-*,clang-analyzer-core.*,clang-analyzer-optin.performance.*,clang-analyzer-optin.portability.*,clang-analyzer-nullability.*,clang-analyzer-security.*,clang-analyzer-unix.*,bugprone-*,misc-*,performance-*,readability-*,-readability-isolate-declaration,-readability-else-after-return,-readability-braces-around-statements,-readability-magic-numbers' +Checks: 'bugprone-*,performance-*,portability-*,readability-*,-readability-braces-around-statements,-readability-isolate-declaration,-readability-else-after-return,-readability-braces-around-statements,misc-*,modernize-*,clang-analyzer-core.*,clang-analyzer-security.*,clang-analyzer-unix.*,clang-analyzer-optin.portability.UnixAPI,clang-analyzer-optin.performance.Padding' WarningsAsErrors: '' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false FormatStyle: file -User: caskd -CheckOptions: - - key: bugprone-argument-comment.CommentBoolLiterals - value: '0' - - key: bugprone-argument-comment.CommentCharacterLiterals - value: '0' - - key: bugprone-argument-comment.CommentFloatLiterals - value: '0' - - key: bugprone-argument-comment.CommentIntegerLiterals - value: '0' - - key: bugprone-argument-comment.CommentNullPtrs - value: '0' - - key: bugprone-argument-comment.CommentStringLiterals - value: '0' - - key: bugprone-argument-comment.CommentUserDefinedLiterals - value: '0' - - key: bugprone-argument-comment.IgnoreSingleArgument - value: '0' - - key: bugprone-argument-comment.StrictMode - value: '0' - - key: bugprone-assert-side-effect.AssertMacros - value: assert - - key: bugprone-assert-side-effect.CheckFunctionCalls - value: '0' - - key: bugprone-dangling-handle.HandleClasses - value: 'std::basic_string_view;std::experimental::basic_string_view' - - key: bugprone-dynamic-static-initializers.HeaderFileExtensions - value: ',h,hh,hpp,hxx' - - key: bugprone-exception-escape.FunctionsThatShouldNotThrow - value: '' - - key: bugprone-exception-escape.IgnoredExceptions - value: '' - - key: bugprone-misplaced-widening-cast.CheckImplicitCasts - value: '0' - - key: bugprone-not-null-terminated-result.WantToUseSafeFunctions - value: '1' - - key: bugprone-signed-char-misuse.CharTypdefsToIgnore - value: '' - - key: bugprone-sizeof-expression.WarnOnSizeOfCompareToConstant - value: '1' - - key: bugprone-sizeof-expression.WarnOnSizeOfConstant - value: '1' - - key: bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression - value: '0' - - key: bugprone-sizeof-expression.WarnOnSizeOfThis - value: '1' - - key: bugprone-string-constructor.LargeLengthThreshold - value: '8388608' - - key: bugprone-string-constructor.WarnOnLargeLength - value: '1' - - key: bugprone-suspicious-enum-usage.StrictMode - value: '0' - - key: bugprone-suspicious-missing-comma.MaxConcatenatedTokens - value: '5' - - key: bugprone-suspicious-missing-comma.RatioThreshold - value: '0.200000' - - key: bugprone-suspicious-missing-comma.SizeThreshold - value: '5' - - key: bugprone-suspicious-string-compare.StringCompareLikeFunctions - value: '' - - key: bugprone-suspicious-string-compare.WarnOnImplicitComparison - value: '1' - - key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison - value: '0' - - key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit - value: '16' - - key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField - value: '1' - - key: bugprone-unused-return-value.CheckedFunctions - value: '::std::async;::std::launder;::std::remove;::std::remove_if;::std::unique;::std::unique_ptr::release;::std::basic_string::empty;::std::vector::empty' - - key: cert-dcl16-c.NewSuffixes - value: 'L;LL;LU;LLU' - - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField - value: '0' - - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors - value: '1' - - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic - value: '1' - - key: google-readability-braces-around-statements.ShortStatementLines - value: '1' - - key: google-readability-function-size.StatementThreshold - value: '800' - - key: google-readability-namespace-comments.ShortNamespaceLines - value: '10' - - key: google-readability-namespace-comments.SpacesBeforeComments - value: '2' - - key: misc-definitions-in-headers.HeaderFileExtensions - value: ',h,hh,hpp,hxx' - - key: misc-definitions-in-headers.UseHeaderFileExtension - value: '1' - - key: misc-throw-by-value-catch-by-reference.CheckThrowTemporaries - value: '1' - - key: misc-unused-parameters.StrictMode - value: '0' - - key: modernize-loop-convert.MaxCopySize - value: '16' - - key: modernize-loop-convert.MinConfidence - value: reasonable - - key: modernize-loop-convert.NamingStyle - value: CamelCase - - key: modernize-pass-by-value.IncludeStyle - value: llvm - - key: modernize-replace-auto-ptr.IncludeStyle - value: llvm - - key: modernize-use-nullptr.NullMacros - value: 'NULL' - - key: performance-faster-string-find.StringLikeClasses - value: 'std::basic_string' - - key: performance-for-range-copy.AllowedTypes - value: '' - - key: performance-for-range-copy.WarnOnAllAutoCopies - value: '0' - - key: performance-inefficient-string-concatenation.StrictMode - value: '0' - - key: performance-inefficient-vector-operation.EnableProto - value: '0' - - key: performance-inefficient-vector-operation.VectorLikeClasses - value: '::std::vector' - - key: performance-move-const-arg.CheckTriviallyCopyableMove - value: '1' - - key: performance-move-constructor-init.IncludeStyle - value: llvm - - key: performance-no-automatic-move.AllowedTypes - value: '' - - key: performance-type-promotion-in-math-fn.IncludeStyle - value: llvm - - key: performance-unnecessary-copy-initialization.AllowedTypes - value: '' - - key: performance-unnecessary-value-param.AllowedTypes - value: '' - - key: performance-unnecessary-value-param.IncludeStyle - value: llvm - - key: readability-function-size.BranchThreshold - value: '4294967295' - - key: readability-function-size.LineThreshold - value: '4294967295' - - key: readability-function-size.NestingThreshold - value: '4294967295' - - key: readability-function-size.ParameterThreshold - value: '4294967295' - - key: readability-function-size.StatementThreshold - value: '800' - - key: readability-function-size.VariableThreshold - value: '4294967295' - - key: readability-identifier-naming.IgnoreFailedSplit - value: '0' - - key: readability-implicit-bool-conversion.AllowIntegerConditions - value: '0' - - key: readability-implicit-bool-conversion.AllowPointerConditions - value: '0' - - key: readability-inconsistent-declaration-parameter-name.IgnoreMacros - value: '1' - - key: readability-inconsistent-declaration-parameter-name.Strict - value: '0' - - key: readability-redundant-member-init.IgnoreBaseInCopyConstructors - value: '0' - - key: readability-redundant-smartptr-get.IgnoreMacros - value: '1' - - key: readability-redundant-string-init.StringNames - value: '::std::basic_string' - - key: readability-simplify-boolean-expr.ChainedConditionalAssignment - value: '0' - - key: readability-simplify-boolean-expr.ChainedConditionalReturn - value: '0' - - key: readability-simplify-subscript-expr.Types - value: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' - - key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold - value: '3' - - key: readability-uppercase-literal-suffix.IgnoreMacros - value: '1' - - key: readability-uppercase-literal-suffix.NewSuffixes - value: '' -... - diff --git a/CMakeLists.txt b/CMakeLists.txt index 468b804..f139cf4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) project( uIRC - VERSION 2021.01.24 + VERSION 0.1 DESCRIPTION "Simple and lightweight IRC protocol helper" LANGUAGES C ) @@ -11,92 +11,80 @@ include(GNUInstallDirs) set(UIRC_VERSION "${PROJECT_VERSION}") add_compile_definitions(UIRC_VERSION="${UIRC_VERSION}") -OPTION(BUILD_HELPERS "Build message helpers" ON ) -OPTION(BUILD_VALIDATORS "Build message validators" ON ) -OPTION(BUILD_IRCV3 "Build IRCv3 components" ON ) +OPTION(BUILD_IRCV3 "Build IRCv3 components" OFF) +OPTION(BUILD_VALIDATORS "Build message validators" OFF) OPTION(BUILD_TESTS "Build tests for ctest" OFF) OPTION(BUILD_DOCS "Build documentation with doxygen" OFF) OPTION(CODE_ANALYZER "Analyze the code statically" OFF) OPTION(CODE_COVERAGE "Build with coverage tools" OFF) set(UIRC_SOURCE - src/assemblers.c - src/commands.c - src/converters.c - src/memory.c - src/string.c - src/tokenizers.c + src/assemblers/message.c + src/assemblers/user.c + src/tokenizers/message.c + src/tokenizers/user.c + src/memory/memory.c ) set(UIRC_HEADERS - src/public/assemblers.h - src/public/commands.h - src/public/converters.h - src/public/errors.h - src/public/modes.h - src/public/replies.h - src/public/tokenizers.h - src/public/types.h - src/public/uirc.h + src/uirc.h + src/ctcp.h + src/errors.h + src/modes.h + src/replies.h + src/types.h + src/assemblers/assemblers.h + src/tokenizers/tokenizers.h ) +# Libraries used +find_library(LLIST_PATH NAMES llist REQUIRED) +find_library(STRINGEXT_PATH NAMES stringext REQUIRED) +set(UIRC_LIBS ${STRINGEXT_PATH} ${LLIST_PATH}) + # # Features # if (BUILD_IRCV3) - message(STATUS "IRCv3 capabilities are going to be built.") - add_compile_definitions(UIRC_IRCV3) - set(UIRC_SOURCE ${UIRC_SOURCE} - src/tags.c - src/capabilities.c - ) - set(UIRC_HEADERS ${UIRC_HEADERS} - src/public/tags.h - src/public/capabilities.h + message(STATUS "IRCv3 capabilities enabled") + add_compile_definitions(UIRC_FEATURE_IRCV3) + set(UIRC_SOURCE + ${UIRC_SOURCE} + src/assemblers/tag.c + src/tokenizers/tags.c ) endif() if (BUILD_VALIDATORS) - message(STATUS "Message validators are going to be built.") - add_compile_definitions(UIRC_VALIDATORS) - set(UIRC_SOURCE ${UIRC_SOURCE} - src/validators.c + message(STATUS "Message validators enabled") + add_compile_definitions(UIRC_FEATURE_VALIDATORS) + set(UIRC_SOURCE + ${UIRC_SOURCE} + src/validators/validators.c ) - set(UIRC_HEADERS ${UIRC_HEADERS} - src/public/validators.h + set(UIRC_HEADERS + ${UIRC_HEADERS} + src/validators/validators.h ) endif() -if (BUILD_HELPERS) - message(STATUS "Helper functions are going to be built.") - add_compile_definitions(UIRC_HELPERS) -endif() if (BUILD_TESTS) message(STATUS "Tests are going to be built.") enable_testing() - macro(buildtest name source) - add_executable(${source} src/tests/${source}.c) - target_link_libraries(${source} uirc) - add_test(NAME ${name} COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${source}) + macro(buildtest categ name) + add_executable("uirc-test-${categ}-${name}" "src/tests/${categ}/${name}.c" src/tests/common.c) + target_link_libraries("uirc-test-${categ}-${name}" uirc) + add_test(NAME "${categ}/${name}" COMMAND "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/uirc-test-${categ}-${name}") endmacro() - buildtest(Tokenizer tokenizer) - buildtest(Overflow overflow) - buildtest(PrefixAssembler prefixassm) - buildtest(MessageAssembler msgassm) - buildtest(NumericCmds numericmds) - buildtest(IncorrectTrailing notrail) - buildtest(SpacedArguments spacedargs) - buildtest(StrTokMoveSave strtokmr) - buildtest(Junk junk) + buildtest(tokenizers tag) + buildtest(tokenizers user) + buildtest(tokenizers message) - if (BUILD_IRCV3) - buildtest(TagParser tagtok) - buildtest(TagAssembler tagassm) - if (BUILD_HELPERS) - buildtest(TimestampAssembly timestamp) - buildtest(TagBitMaskTknzr capbitmask) - endif() - endif() + buildtest(assemblers tag) + buildtest(assemblers user) + buildtest(assemblers message) + + buildtest(general fullloop) endif() if(BUILD_DOCS) find_package(Doxygen REQUIRED) @@ -105,11 +93,10 @@ if(BUILD_DOCS) set(DOXYGEN_MACRO_EXPANSION YES) set(DOXYGEN_EXPAND_ONLY_PREDEF YES) set(DOXYGEN_PREDEFINED - "UIRC_HELPERS" - "UIRC_IRCV3" + "UIRC_FEATURE_IRCV3" + "UIRC_FEATURE_VALIDATORS" ) doxygen_add_docs(docgen - src/public src/doc/main.doc README.md ALL @@ -119,6 +106,21 @@ endif() add_library(uirc ${UIRC_SOURCE}) +target_link_libraries(uirc ${UIRC_LIBS}) + +separate_arguments(UIRC_HEADERS) +set_target_properties(uirc PROPERTIES + C_STANDARD 99 + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + PUBLIC_HEADER "${UIRC_HEADERS}" +) + +install( + TARGETS uirc + LIBRARY + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/uirc" +) set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Werror") if (CMAKE_C_COMPILER_ID STREQUAL "GNU") @@ -133,16 +135,3 @@ elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") endif() endif() -separate_arguments(UIRC_HEADERS) -set_target_properties(uirc PROPERTIES - C_STANDARD 99 - VERSION ${UIRC_VERSION} - SOVERSION ${UIRC_VERSION} - PUBLIC_HEADER "${UIRC_HEADERS}" -) - -install( - TARGETS uirc - LIBRARY - PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/uirc" -) diff --git a/src/assemblers.c b/src/assemblers.c deleted file mode 100644 index 0bff421..0000000 --- a/src/assemblers.c +++ /dev/null @@ -1,274 +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 "public/assemblers.h" - -#include "private/mappings.h" -#include "private/memory.h" -#include "public/commands.h" -#include "public/errors.h" -#include "public/modes.h" -#include "public/tags.h" -#include "public/types.h" - -#include -#include -#include -#include -#include - -#ifdef UIRC_HELPERS -#define RESERVED "*" -void clear_assm(IRC_Message* imassm_mesg); -#endif /* UIRC_HELPERS */ - -signed long -Assm_user(char* buf, IRC_User* in, size_t len, bool useorig) -{ - assert(buf != NULL); - assert(in != NULL); - char* pos = buf; - if (in->nick == NULL && in->host != NULL) { - if (!safe_strcpy(&pos, in->host, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - } else if (in->nick != NULL) { - if (!safe_strcpy(&pos, in->nick, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - if (in->user != NULL) { - if (!safe_charcpy(&pos, '!', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - if (!safe_strcpy(&pos, in->user, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - } - if (useorig && in->orig != NULL) { - if (!safe_charcpy(&pos, '%', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - if (!safe_strcpy(&pos, in->orig, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - } - if (in->host != NULL) { - if (!safe_charcpy(&pos, '@', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - if (!safe_strcpy(&pos, in->host, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - } - } else - return ERR_UIRC_INVALID_FORMAT; - return pos - buf; -} - -#ifdef UIRC_IRCV3 -signed long -Assm_tags(char* buf, IRC_Tags* in, size_t len) -{ - assert(buf != NULL); - assert(in != NULL); - 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 - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - } else { - if (!safe_charcpy(&pos, ';', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - } - if ((*tagmps[i].assg).clientbound) { - if (!safe_charcpy(&pos, '+', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - } - if (!safe_strcpy(&pos, tagmps[i].name, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - if (*(*tagmps[i].assg).value != '\0') { - if (!safe_charcpy(&pos, '=', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - if (!safe_strcpy(&pos, (*tagmps[i].assg).value, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - } - } - } - return pos - buf; -} -#endif /* UIRC_IRCV3 */ - -signed long -Assm_mesg(char* buf, IRC_Message* in, size_t len) -{ - assert(buf != NULL); - assert(in != NULL); - char* pos = buf; - signed long cnt, ret; -#ifdef UIRC_IRCV3 - if ((ret = Assm_tags(pos, &in->tags, len - (size_t)(pos - buf))) < 0) return ret; - else if (ret != 0) { - pos += ret; - if (!safe_charcpy(&pos, ' ', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - } -#endif /* UIRC_IRCV3 */ - if (in->name.nick != NULL || in->name.host != NULL) { - if (!safe_charcpy(&pos, ':', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - if ((ret = Assm_user(pos, &in->name, len - (size_t)(pos - buf), false)) <= 0) return ret; - else - pos += ret; - if (!safe_charcpy(&pos, ' ', len - (size_t)(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 - (size_t)(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 - (size_t)(pos - buf) > strlen(in->args[i]) + 2 - && (cnt = snprintf(pos, len - (size_t)(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 - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR; - return pos - buf; -} - -#ifdef UIRC_HELPERS - -void -clear_assm(IRC_Message* imassm_mesg) -{ - memset((void*) imassm_mesg, '\0', sizeof(IRC_Message)); -} - -IRC_Message* -Assm_AUTO(IRC_Message* imassm_mesg, IRC_Command cmd, bool trailing, char** args, int req) -{ - clear_assm(imassm_mesg); - int i; - for (i = 0; args[i] != NULL && i < 15; i++) { imassm_mesg->args[i] = args[i]; } - if (i < req) return NULL; - imassm_mesg->trailing = trailing; - imassm_mesg->cmd = cmd; - return imassm_mesg; -} - -IRC_Message* -Assm_cmd_USER(IRC_Message* imassm_mesg, char* user, char* realname, int modes) -{ - if (user == NULL || modes < 0 || modes > (MBMASK_INVIS | MBMASK_WALLOPS)) return NULL; - clear_assm(imassm_mesg); - static char local_mode[2]; - snprintf(local_mode, 2, "%i", modes); - imassm_mesg->args[0] = user; - imassm_mesg->args[1] = local_mode; - imassm_mesg->args[2] = RESERVED; - imassm_mesg->args[3] = realname; - imassm_mesg->trailing = true; - imassm_mesg->cmd = USER; - return imassm_mesg; -} - -IRC_Message* -Assm_cmd_LINKS(IRC_Message* imassm_mesg, char* remoteserv, char* servmask) -{ - if (remoteserv != NULL && servmask == NULL) return NULL; - clear_assm(imassm_mesg); - imassm_mesg->args[0] = (remoteserv == NULL) ? servmask : remoteserv; - imassm_mesg->args[1] = (remoteserv == NULL) ? NULL : servmask; - imassm_mesg->cmd = LINKS; - return imassm_mesg; -} - -IRC_Message* -Assm_cmd_WHO(IRC_Message* imassm_mesg, char* mask, bool oper) -{ - static char* operator= "o"; - if (oper && mask == NULL) return NULL; - clear_assm(imassm_mesg); - imassm_mesg->args[0] = mask; - imassm_mesg->args[1] = (oper) ? operator: NULL; - imassm_mesg->cmd = WHO; - return imassm_mesg; -} - -IRC_Message* -Assm_cmd_WHOIS(IRC_Message* imassm_mesg, char* target, char* mask) -{ - if (mask == NULL) return NULL; - clear_assm(imassm_mesg); - imassm_mesg->args[0] = (target == NULL) ? mask : target; - imassm_mesg->args[1] = (target == NULL) ? NULL : mask; - imassm_mesg->cmd = WHOIS; - return imassm_mesg; -} - -IRC_Message* -Assm_cmd_WHOWAS(IRC_Message* imassm_mesg, char* nick, char* count, char* target) -{ - if (nick == NULL || (target != NULL && count == NULL)) return NULL; - clear_assm(imassm_mesg); - imassm_mesg->args[0] = nick; - imassm_mesg->args[1] = count; - imassm_mesg->args[2] = target; - imassm_mesg->cmd = WHOWAS; - return imassm_mesg; -} - -/* NOTE: This is what implementation you have to live with - * I would've just used the prefix to set the source but whatever - */ -IRC_Message* -Assm_cmd_PING(IRC_Message* imassm_mesg, char* source, char* target) -{ - if (source == NULL && target == NULL) return NULL; - clear_assm(imassm_mesg); - imassm_mesg->args[0] = (source != NULL) ? source : target; - imassm_mesg->args[1] = (source != NULL && target != NULL) ? target : NULL; - imassm_mesg->trailing = (source != NULL && target == NULL) ? true : false; - imassm_mesg->cmd = PING; - return imassm_mesg; -} - -IRC_Message* -Assm_cmd_SUMMON(IRC_Message* imassm_mesg, char* user, char* target, char* channel) -{ - if (user == NULL || (channel != NULL && target == NULL)) return NULL; - clear_assm(imassm_mesg); - imassm_mesg->args[0] = user; - imassm_mesg->args[1] = target; - imassm_mesg->args[2] = channel; - imassm_mesg->cmd = SUMMON; - return imassm_mesg; -} - -IRC_Message* -Assm_cmd_USERHOST(IRC_Message* imassm_mesg, char* users[]) -{ - if (users[0] == NULL) return NULL; - clear_assm(imassm_mesg); - for (unsigned int i = 0; i < 5 && users[i] != NULL; i++) imassm_mesg->args[i] = users[i]; - imassm_mesg->cmd = USERHOST; - return imassm_mesg; -} -/* NOTE: Limited to 14 nicks per command */ - -IRC_Message* -Assm_cmd_ISON(IRC_Message* imassm_mesg, char* users[]) -{ - if (users[0] == NULL) return NULL; - clear_assm(imassm_mesg); - for (unsigned int i = 0; i < 14 && users[i] != NULL; i++) { imassm_mesg->args[i] = users[i]; } - imassm_mesg->cmd = ISON; - return imassm_mesg; -} - -#endif /* UIRC_HELPERS */ diff --git a/src/assemblers/assemblers.h b/src/assemblers/assemblers.h new file mode 100644 index 0000000..4356068 --- /dev/null +++ b/src/assemblers/assemblers.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 . + */ + +/*! \file */ + +#include "../types.h" // IRC_User IRC_Message + +#include // bool +#include // size_t + +#ifndef UIRC_GUARD_PUBLIC_ASSEMBLERS +#define UIRC_GUARD_PUBLIC_ASSEMBLERS + +signed long uirc_assembler_user(char* buf, IRC_User* u, size_t len); + +#ifdef UIRC_FEATURE_IRCV3 +signed long uirc_assembler_tag(char* buf, const IRC_Tag* t, size_t len); +#endif /* UIRC_FEATURE_IRCV3*/ + +/*! + * \brief IRC_Message to string converter + * + * This assembles a IRC_Message struct to a string representation of a most size len + * The return value is either the lenght of the string or any of the uirc_errors errors + * \param[in] m IRC_Message struct that contains at least a command + * \param[in] len Maximum lenght of string + * \param[out] buf String representation of message (if successful) + * \warning in and buf SHOULD NOT be NULL, this will trigger a ASSERT so it's required to check it where needed + */ +signed long uirc_assembler_message(char* buf, IRC_Message* m, size_t len); +#endif /* UIRC_GUARD_PUBLIC_ASSEMBLERS */ + diff --git a/src/assemblers/message.c b/src/assemblers/message.c new file mode 100644 index 0000000..6d3bb0c --- /dev/null +++ b/src/assemblers/message.c @@ -0,0 +1,112 @@ +/* + * 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 "../errors.h" // ERR_UIRC_* +#include "../types.h" // IRC_Message +#include "assemblers.h" // Assm_mesg() Assm_tags() Assm_user() + +#include // assert() +#include // false +#include // NULL, snprintf() +#include // strlen() +#include // size_t + +signed long +uirc_assembler_message(char* buf, IRC_Message* m, size_t len) +{ + assert(buf != NULL); + assert(m != NULL); + + char* const sv = buf; + signed long ret; + +#ifdef UIRC_FEATURE_IRCV3 + if (m->tag_list != NULL && m->tag_list->content != NULL) { + for (llist_t* l = m->tag_list; l != NULL && l->content != NULL && ((IRC_Tag*) l->content)->key != NULL;) { + if (m->tag_list == l) { + if (len > 1) { + *(buf++) = '@'; + len--; + } else + return UIRC_ERR_BUFFER_FULL; + } else { + if (len > 1) { + *(buf++) = ';'; + len--; + } else + return UIRC_ERR_BUFFER_FULL; + } + + if ((ret = uirc_assembler_tag(buf, l->content, len)) >= 0) { + buf += (size_t) ret; + len -= (size_t) ret; + } else + return ret; + + if ((l = l->next) == NULL) { + if (len > 1) { + *(buf++) = ' '; + len--; + } else + return UIRC_ERR_BUFFER_FULL; + } + } + } +#endif /* UIRC_FEATURE_IRCV3 */ + if (m->source != NULL && (m->source->nick != NULL || m->source->host != NULL)) { + if (len > 1) { + *(buf++) = ':'; + len--; + } else + return UIRC_ERR_BUFFER_FULL; + + if ((ret = uirc_assembler_user(buf, m->source, len)) >= 0) { + buf += (size_t) ret; + len -= (size_t) ret; + } else + return ret; + + if (len > 1) { + *(buf++) = ' '; + len--; + } else + return UIRC_ERR_BUFFER_FULL; + } + + if (m->command != NULL) { + if (len < 2) return UIRC_ERR_BUFFER_FULL; + if ((ret = snprintf(buf, len, "%s ", m->command)) >= 0) { + buf += (size_t) ret; + len -= (size_t) ret; + } else + return UIRC_ERR_BUFFER_ERR; + } else + return UIRC_ERR_INVALID_FORMAT; + + for (unsigned int i = 0; i < IRC_MAXARGS && m->args[i] != NULL; i++) { + if (len < 2) return UIRC_ERR_BUFFER_FULL; + if ((ret = snprintf(buf, len, (i + 1 == IRC_MAXARGS || (m->args[i + 1] == NULL && m->trailing)) ? ":%s" : "%s ", m->args[i])) >= 0) { + buf += (size_t) ret; + len -= (size_t) ret; + } else + return UIRC_ERR_BUFFER_ERR; + } + + return (buf += ret) - sv; +} + diff --git a/src/assemblers/tag.c b/src/assemblers/tag.c new file mode 100644 index 0000000..5b42455 --- /dev/null +++ b/src/assemblers/tag.c @@ -0,0 +1,64 @@ +/* + * 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 "../errors.h" // ERR_UIRC_* +#include "../types.h" // IRC_Tag +#include "assemblers.h" // Assm_user() + +#include // assert() +#include // bool +#include // size_t +#include // NULL + +signed long +uirc_assembler_tag(char* buf, const IRC_Tag* t, size_t len) +{ + assert(buf != NULL); + assert(t != NULL); + assert(t->key != NULL); + + char* const sv = buf; + int res; + + if (t->clientbound) { + if (len > 1) { + *(buf++) = '+'; + len--; + } else + return UIRC_ERR_BUFFER_FULL; + } + + if (len < 1) return UIRC_ERR_BUFFER_FULL; + if ((res = snprintf(buf, len, "%s", t->key)) >= 0) { + buf += (size_t) res; + len -= (size_t) res; + } else + return UIRC_ERR_BUFFER_ERR; + + if (t->value != NULL) { + if (len < 1) return UIRC_ERR_BUFFER_FULL; + if ((res = snprintf(buf, len, "=%s", t->value)) >= 0) { + buf += (size_t) res; + len -= (size_t) res; + } else + return UIRC_ERR_BUFFER_ERR; + } + + return buf - sv; +} + diff --git a/src/assemblers/user.c b/src/assemblers/user.c new file mode 100644 index 0000000..2c6f188 --- /dev/null +++ b/src/assemblers/user.c @@ -0,0 +1,63 @@ +/* + * 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 "../errors.h" // ERR_UIRC_* +#include "../types.h" // IRC_User +#include "assemblers.h" // Assm_user() + +#include // assert() +#include // bool +#include // NULL +#include // size_t + +signed long +uirc_assembler_user(char* buf, IRC_User* u, size_t len) +{ + assert(buf != NULL); + assert(u != NULL); + + ssize_t res; + char* const sv = buf; + + if (u->nick != NULL) { + if (len < 1) return UIRC_ERR_BUFFER_FULL; + if ((res = snprintf(buf, len, "%s", u->nick)) >= 0) { + buf += (size_t) res; + len -= (size_t) res; + } else + return UIRC_ERR_BUFFER_ERR; + } + if (u->user != NULL) { + if (len < 1) return UIRC_ERR_BUFFER_FULL; + if ((res = snprintf(buf, len, "!%s", u->user)) >= 0) { + buf += (size_t) res; + len -= (size_t) res; + } else + return UIRC_ERR_BUFFER_ERR; + } + if (u->host != NULL) { + if (len < 1) return UIRC_ERR_BUFFER_FULL; + if ((res = snprintf(buf, len, (u->nick != NULL || u->user != NULL) ? "@%s" : "%s", u->host)) >= 0) { + buf += (size_t) res; + len -= (size_t) res; + } else + return UIRC_ERR_BUFFER_ERR; + } + return buf - sv; +} + diff --git a/src/capabilities.c b/src/capabilities.c deleted file mode 100644 index b11483d..0000000 --- a/src/capabilities.c +++ /dev/null @@ -1,70 +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 "public/capabilities.h" - -#include "public/errors.h" - -#include -#include -#include - -const char* const IRC_v3_Caps[] = { - [CAP_ACCOUNT_NOTIFY] = "account-notify", - [CAP_ACCOUNT_TAG] = "account-tag", - [CAP_AWAY_NOTIFY] = "away-notify", - [CAP_BATCH] = "batch", - [CAP_CAP_NOTIFY] = "cap-notify", - [CAP_CHANNEL_RENAME] = "channel-rename", - [CAP_CHGHOST] = "chghost", - [CAP_ECHO_MESSAGE] = "echo-message", - [CAP_EXTENDED_JOIN] = "extended-join", - [CAP_INVITE_NOTIFY] = "invite-notify", - [CAP_LABELED_RESPONSE] = "labeled-response", - [CAP_MESSAGE_TAGS] = "message-tags", - [CAP_MONITOR] = "monitor", - [CAP_MULTI_PREFIX] = "multi-prefix", - [CAP_MULTILINE] = "multiline", - [CAP_SASL] = "sasl", - [CAP_SERVER_TIME] = "server-time", - [CAP_SETNAME] = "setname", - [CAP_TLS] = "tls", - [CAP_USERHOST_IN_NAMES] = "userhost-in-names", -}; - -#ifdef UIRC_HELPERS -signed int -Tok_CAPS(char* caps) -{ - assert(caps != NULL); - int temp = 0; - char* cur = NULL; - if ((cur = strtok(caps, " ")) != NULL) { - do { - for (int i = 1; (unsigned long) i < (sizeof(IRC_v3_Caps) / sizeof(*IRC_v3_Caps)); i++) { - if (strcmp(IRC_v3_Caps[i], cur) == 0) { - temp |= CAPBIT(i); - break; - } - } - } while ((cur = strtok(NULL, " ")) != NULL); - } - return temp; -} -#endif /* UIRC_HELPERS */ - diff --git a/src/commands.c b/src/commands.c deleted file mode 100644 index a97abda..0000000 --- a/src/commands.c +++ /dev/null @@ -1,39 +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 "public/commands.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 /* UIRC_IRCV3 */ -}; diff --git a/src/converters.c b/src/converters.c deleted file mode 100644 index b9fd9fe..0000000 --- a/src/converters.c +++ /dev/null @@ -1,35 +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 "public/converters.h" - -#include "public/commands.h" -#include "public/errors.h" - -#include -#include - -signed short -Ircmd_stoi(const char* str) -{ - assert(str != NULL); - for (signed short i = UIRC_FCMD; i <= (signed short) UIRC_LCMD; i++) { - if (IRC_Cmds[i] != NULL && strcmp(IRC_Cmds[i], str) == 0) return i; - } - return ERR_UIRC_UNKNOWN_TOKEN; -} diff --git a/src/ctcp.h b/src/ctcp.h new file mode 100644 index 0000000..7359c58 --- /dev/null +++ b/src/ctcp.h @@ -0,0 +1,165 @@ +/* + * 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 . + */ + +/*! \file */ +#ifndef UIRC_GUARD_PUBLIC_CTCP +#define UIRC_GUARD_PUBLIC_CTCP + +#ifdef UIRC_FEATURE_CTCP +enum formatting { + IRC_CTCP_BOLD = 0x02, + IRC_CTCP_COLOR = 0x03, + IRC_CTCP_COLOR_HEX = 0x04, + IRC_CTCP_RESET = 0x0F, + IRC_CTCP_MONOSPACE = 0x11, + IRC_CTCP_REVERSE = 0x16, + IRC_CTCP_ITALICS = 0x1D, + IRC_CTCP_STRIKETHROUGH = 0x1E, + IRC_CTCP_UNDERLINE = 0x1F, +}; +enum colors { + IRC_CTCP_COLORS_WHITE = 0, + IRC_CTCP_COLORS_BLACK = 1, + IRC_CTCP_COLORS_BLUE, + IRC_CTCP_COLORS_GREEN, + IRC_CTCP_COLORS_RED, + IRC_CTCP_COLORS_BROWN, + IRC_CTCP_COLORS_MAGENTA, + IRC_CTCP_COLORS_ORANGE, + IRC_CTCP_COLORS_YELLOW, + IRC_CTCP_COLORS_LIGHT_GREEN, + IRC_CTCP_COLORS_CYAN, + IRC_CTCP_COLORS_LIGHT_CYAN, + IRC_CTCP_COLORS_LIGHT_BLUE, + IRC_CTCP_COLORS_PINK, + IRC_CTCP_COLORS_GREY, + IRC_CTCP_COLORS_LIGHT_GREY, + IRC_CTCP_COLORS_DEFAULT = 99, +}; +short UIRC_FORMAT_ANSI[] = { + [IRC_CTCP_COLORS_WHITE] = 97, + [IRC_CTCP_COLORS_BLACK] = 30, + [IRC_CTCP_COLORS_BLUE] = 34, + [IRC_CTCP_COLORS_GREEN] = 32, + [IRC_CTCP_COLORS_RED] = 31, + [IRC_CTCP_COLORS_BROWN] = 94, + [IRC_CTCP_COLORS_MAGENTA] = 35, + [IRC_CTCP_COLORS_ORANGE] = 166, + [IRC_CTCP_COLORS_YELLOW] = 33, + [IRC_CTCP_COLORS_LIGHT_GREEN] = 92, + [IRC_CTCP_COLORS_CYAN] = 36, + [IRC_CTCP_COLORS_LIGHT_CYAN] = 96, + [IRC_CTCP_COLORS_LIGHT_BLUE] = 94, + [IRC_CTCP_COLORS_PINK] = 127, + [IRC_CTCP_COLORS_GREY] = 90, + [IRC_CTCP_COLORS_LIGHT_GREY] = 37, + [IRC_CTCP_COLORS_DEFAULT] = 39, + [IRC_CTCP_BOLD] = 1, + [IRC_CTCP_RESET] = 0, + [IRC_CTCP_REVERSE] = 7, + [IRC_CTCP_ITALICS] = 3, + [IRC_CTCP_STRIKETHROUGH] = 9, + [IRC_CTCP_UNDERLINE] = 4, + [16] = 52, /* See https://modern.ircdocs.horse/formatting.html */ + [17] = 94, + [18] = 100, + [19] = 58, + [20] = 22, + [21] = 29, + [22] = 23, + [23] = 24, + [24] = 17, + [25] = 54, + [26] = 53, + [27] = 89, + [28] = 88, + [29] = 130, + [30] = 142, + [31] = 64, + [32] = 28, + [33] = 35, + [34] = 30, + [35] = 25, + [36] = 18, + [37] = 91, + [38] = 90, + [39] = 125, + [40] = 124, + [41] = 166, + [42] = 184, + [43] = 106, + [44] = 34, + [45] = 49, + [46] = 37, + [47] = 33, + [48] = 19, + [49] = 129, + [50] = 127, + [51] = 161, + [52] = 196, + [53] = 208, + [54] = 226, + [55] = 154, + [56] = 46, + [57] = 86, + [58] = 51, + [59] = 75, + [60] = 21, + [61] = 171, + [62] = 201, + [63] = 198, + [64] = 203, + [65] = 215, + [66] = 227, + [67] = 191, + [68] = 83, + [69] = 122, + [70] = 87, + [71] = 111, + [72] = 63, + [73] = 177, + [74] = 207, + [75] = 205, + [76] = 217, + [77] = 223, + [78] = 229, + [79] = 193, + [80] = 157, + [81] = 158, + [82] = 159, + [83] = 153, + [84] = 147, + [85] = 183, + [86] = 219, + [87] = 212, + [88] = 16, + [89] = 233, + [90] = 235, + [91] = 237, + [92] = 239, + [93] = 241, + [94] = 244, + [95] = 247, + [96] = 250, + [97] = 254, + [98] = 231, +}; +#endif /* UIRC_FEATURE_CTCP */ + +#endif /* UIRC_GUARD_PUBLIC_CTCP */ + diff --git a/src/public/errors.h b/src/errors.h similarity index 76% rename from src/public/errors.h rename to src/errors.h index beb04e7..0f71212 100644 --- a/src/public/errors.h +++ b/src/errors.h @@ -18,16 +18,15 @@ /*! \file */ -#ifndef UIRC_GUARD_ERRORS -#define UIRC_GUARD_ERRORS +#ifndef UIRC_GUARD_PUBLIC_ERRORS +#define UIRC_GUARD_PUBLIC_ERRORS enum uirc_errors { - ERR_UIRC_GENERIC = -1, - ERR_UIRC_INVALID_FORMAT = -2, - ERR_UIRC_BUFFER_ERR = -3, - ERR_UIRC_UNKNOWN_TOKEN = -4, - ERR_UIRC_VAL_FAILED = -5, + UIRC_ERROR_GENERIC = -1, + UIRC_ERR_BUFFER_FULL = -2, + UIRC_ERR_BUFFER_ERR = -3, + UIRC_ERR_INVALID_FORMAT = -4, }; -#endif /* UIRC_GUARD_ERRORS */ +#endif /* UIRC_GUARD_PUBLIC_ERRORS */ diff --git a/src/memory.c b/src/memory.c deleted file mode 100644 index 3aad0c5..0000000 --- a/src/memory.c +++ /dev/null @@ -1,46 +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 "private/memory.h" - -#include -#include -#include - -size_t -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; -} - -bool -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/memory/memory.c b/src/memory/memory.c new file mode 100644 index 0000000..bc1fe3f --- /dev/null +++ b/src/memory/memory.c @@ -0,0 +1,91 @@ +/* + * 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 "memory.h" + +#include "../types.h" // IRC_* + +#include // assert() +#include // llist_t remove_linked_list_elem() +#include // malloc_string() +#include // free() +#include // strcpy() + +// TODO: Indicate failure of this at any step and free previous if that happens +IRC_User* +uirc_malloc_user(const char* nick, const char* user, const char* real) +{ + IRC_User* ret; + if ((ret = malloc(sizeof(IRC_User))) != NULL) { + ret->nick = (nick == NULL) ? NULL : malloc_string(nick, strlen(nick)); + ret->user = (user == NULL) ? NULL : malloc_string(user, strlen(user)); + ret->real = (real == NULL) ? NULL : malloc_string(real, strlen(real)); + return ret; + } else + return NULL; +} + +llist_t* +uirc_malloc_tag(llist_t* prev, const char* key, const char* value) +{ + llist_t* tmp = NULL; + if ((tmp = allocate_linked_list_elem(sizeof(IRC_Tag))) == NULL) return NULL; + if (prev != NULL) prev->next = tmp; + ((IRC_Tag*) tmp->content)->key = malloc_string(key, strlen(key)); + ((IRC_Tag*) tmp->content)->value = malloc_string(value, strlen(value)); + return tmp; +} + +void +uirc_free_tag(IRC_Tag* t) +{ + assert(t != NULL); + free(t->key); + free(t->value); +} + +void +uirc_free_user(IRC_User* u) +{ + assert(u != NULL); + free(u->user); + free(u->nick); + free(u->real); +} + +void +uirc_free_message(IRC_Message* m) +{ + assert(m != NULL); + + free(m->command); + + for (unsigned short i = 0; m->args[i] != NULL; i++) free(m->args[i]); + + llist_t* t = m->tag_list; + for (; t != NULL; t = t->next) { + uirc_free_tag(t->content); + remove_linked_list_elem(t); + } + + if (m->source != NULL) { + uirc_free_user(m->source); + free(m->source); + } +} + diff --git a/src/public/tags.h b/src/memory/memory.h similarity index 61% rename from src/public/tags.h rename to src/memory/memory.h index 72fc4ce..3116755 100644 --- a/src/public/tags.h +++ b/src/memory/memory.h @@ -18,13 +18,18 @@ /*! \file */ -#include +#include "../types.h" // IRC_Tag IRC_User IRC_Meesage -#ifndef UIRC_GUARD_TAGS -#define UIRC_GUARD_TAGS +#include // llist_t -#ifdef UIRC_HELPERS -size_t Assm_tag_timestamp(char* buf, size_t len, time_t time); -#endif /* UIRC_HELPERS */ +#ifndef UIRC_GUARD_PUBLIC_MEMORY +#define UIRC_GUARD_PUBLIC_MEMORY + +IRC_User* uirc_malloc_user(const char* nick, const char* user, const char* real); +llist_t* uirc_malloc_tag(llist_t* prev, const char* key, const char* value); +void uirc_free_tag(IRC_Tag* t); +void uirc_free_user(IRC_User* u); +void uirc_free_message(IRC_Message* m); + +#endif /* UIRC_GUARD_PUBLIC_MEMORY */ -#endif /* UIRC_GUARD_TAGS */ diff --git a/src/public/modes.h b/src/modes.h similarity index 74% rename from src/public/modes.h rename to src/modes.h index a67877c..eab46e8 100644 --- a/src/public/modes.h +++ b/src/modes.h @@ -18,12 +18,15 @@ /*! \file */ -#ifndef UIRC_GUARD_MODES -#define UIRC_GUARD_MODES +#ifndef UIRC_GUARD_PUBLIC_MODES +#define UIRC_GUARD_PUBLIC_MODES -/* Mode bitmask values */ -#define MBMASK_WALLOPS 1 << 1 /* 010 */ -#define MBMASK_INVIS 1 << 2 /* 100 */ +/* Mode bitmask positions */ +// TODO: Add all modes in this bitmask +#define IRC_MODE_WALLOPS 1 +#define IRC_MODE_INVIS 2 -#endif /* UIRC_GUARD_MODES */ +#define MBMASK(MODEBIT) (1 << MODEBIT) + +#endif /* UIRC_GUARD_PUBLIC_MODES */ diff --git a/src/private/mappings.h b/src/private/mappings.h deleted file mode 100644 index ae13096..0000000 --- a/src/private/mappings.h +++ /dev/null @@ -1,35 +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 "../public/types.h" - -#include -#include -#include - -#ifndef UIRC_GUARD_MAPPINGS -#define UIRC_GUARD_MAPPINGS - -#ifdef UIRC_IRCV3 -struct tagmapping { - const char* const name; - IRC_Tag* assg; -}; -#endif /* UIRC_IRCV3 */ - -#endif /* UIRC_GUARD_MAPPINGS */ diff --git a/src/private/string.h b/src/private/string.h deleted file mode 100644 index 8639f02..0000000 --- a/src/private/string.h +++ /dev/null @@ -1,26 +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 . - */ - -#ifndef UIRC_GUARD_STRING -#define UIRC_GUARD_STRING - -void skip_spaces(char** addr); -char* strtok_mr(char** addr, const char* tokens); - -#endif /* UIRC_GUARD_STRING */ - diff --git a/src/public/assemblers.h b/src/public/assemblers.h deleted file mode 100644 index dfe8bd6..0000000 --- a/src/public/assemblers.h +++ /dev/null @@ -1,119 +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 . - */ - -/*! \file */ - -#include "types.h" - -#include - -#ifndef UIRC_GUARD_ASSEMBLERS -#define UIRC_GUARD_ASSEMBLERS - -signed long Assm_user(char* buf, IRC_User* in, size_t len, bool useorig); - -#ifdef UIRC_IRCV3 -signed long Assm_tags(char* buf, IRC_Tags* in, size_t len); -#endif /* UIRC_IRCV3*/ - -/*! - * \brief IRC_Message to string converter - * - * This assembles a IRC_Message struct to a string representation of a most size len - * The return value is either the lenght of the string or any of the uirc_errors errors - * \param[in] in IRC_Message struct that contains at least a command - * \param[in] len Maximum lenght of string - * \param[out] buf String representation of message (if successful) - * \warning in and buf SHOULD NOT be NULL, this will trigger a ASSERT so it's required to check it where needed - */ -signed long Assm_mesg(char* buf, IRC_Message* in, size_t len); - -#ifdef UIRC_HELPERS -IRC_Message* Assm_AUTO(IRC_Message* imassm_mesg, IRC_Command cmd, bool trailing, char** args, int req); -IRC_Message* Assm_cmd_USER(IRC_Message* imassm_mesg, char* user, char* realname, int modes); -IRC_Message* Assm_cmd_LINKS(IRC_Message* imassm_mesg, char* remoteserv, char* servmask); -IRC_Message* Assm_cmd_WHO(IRC_Message* imassm_mesg, char* mask, bool oper); -IRC_Message* Assm_cmd_WHOIS(IRC_Message* imassm_mesg, char* target, char* mask); -IRC_Message* Assm_cmd_WHOWAS(IRC_Message* imassm_mesg, char* nick, char* count, char* target); -IRC_Message* Assm_cmd_PING(IRC_Message* imassm_mesg, char* source, char* target); -IRC_Message* Assm_cmd_SUMMON(IRC_Message* imassm_mesg, char* user, char* target, char* channel); -IRC_Message* Assm_cmd_USERHOST(IRC_Message* imassm_mesg, char* users[]); -IRC_Message* Assm_cmd_ISON(IRC_Message* imassm_mesg, char* users[]); - -#define Assm_cmd_REHASH(mesg) Assm_AUTO(mesg, REHASH, false, (char*[]) { NULL }, 0) -#define Assm_cmd_DIE(mesg) Assm_AUTO(mesg, DIE, false, (char*[]) { NULL }, 0) -#define Assm_cmd_RESTART(mesg) Assm_AUTO(mesg, RESTART, false, (char*[]) { NULL }, 0) - -#define Assm_cmd_QUIT(mesg, message) Assm_AUTO(mesg, QUIT, true, (char*[]) { message, NULL }, 0) -#define Assm_cmd_MOTD(mesg, target) Assm_AUTO(mesg, MOTD, false, (char*[]) { target, NULL }, 0) -#define Assm_cmd_VERSION(mesg, target) Assm_AUTO(mesg, VERSION, false, (char*[]) { target, NULL }, 0) -#define Assm_cmd_TIME(mesg, target) Assm_AUTO(mesg, TIME, false, (char*[]) { target, NULL }, 0) -#define Assm_cmd_TRACE(mesg, target) Assm_AUTO(mesg, TRACE, false, (char*[]) { target, NULL }, 0) -#define Assm_cmd_ADMIN(mesg, target) Assm_AUTO(mesg, ADMIN, false, (char*[]) { target, NULL }, 0) -#define Assm_cmd_INFO(mesg, target) Assm_AUTO(mesg, INFO, false, (char*[]) { target, NULL }, 0) -#define Assm_cmd_AWAY(mesg, message) Assm_AUTO(mesg, AWAY, false, (char*[]) { message, NULL }, 0) - -#define Assm_cmd_PASS(mesg, password) Assm_AUTO(mesg, PASS, true, (char*[]) { password, NULL }, 1) -#define Assm_cmd_ERROR(mesg, message) Assm_AUTO(mesg, ERROR, true, (char*[]) { message, NULL }, 1) -#define Assm_cmd_WALLOPS(mesg, text) Assm_AUTO(mesg, WALLOPS, true, (char*[]) { text, NULL }, 1) -#define Assm_cmd_NICK(mesg, nickname) Assm_AUTO(mesg, NICK, false, (char*[]) { nickname, NULL }, 1) -#define Assm_cmd_USERS(mesg, target) Assm_AUTO(mesg, USERS, false, (char*[]) { target, NULL }, 1) - -#define Assm_cmd_NAMES(mesg, channels, target) Assm_AUTO(mesg, NAMES, false, (char*[]) { channels, target, NULL }, 0) -#define Assm_cmd_LIST(mesg, channels, target) Assm_AUTO(mesg, LIST, false, (char*[]) { channels, target, NULL }, 0) -#define Assm_cmd_LUSERS(mesg, mask, target) Assm_AUTO(mesg, LUSERS, false, (char*[]) { mask, target, NULL }, 0) -#define Assm_cmd_STATS(mesg, query, target) Assm_AUTO(mesg, STATS, false, (char*[]) { query, target, NULL }, 0) -#define Assm_cmd_SERVLIST(mesg, mask, type) Assm_AUTO(mesg, SERVLIST, false, (char*[]) { mask, type, NULL }, 0) - -#define Assm_cmd_JOIN(mesg, channels, keys) Assm_AUTO(mesg, JOIN, false, (char*[]) { channels, keys, NULL }, 1) -#define Assm_cmd_PART(mesg, channel, message) Assm_AUTO(mesg, PART, false, (char*[]) { channel, message, NULL }, 1) -/* NOTE: Use a non-NULL address (pointing at a "\0") as the topic to clear it and use a NULL address to check it - * Blame the protocol, not this >:C */ -#define Assm_cmd_TOPIC(mesg, channel, topic) Assm_AUTO(mesg, TOPIC, true, (char*[]) { channel, topic, NULL }, 1) -#define Assm_cmd_PONG(mesg, source, target) Assm_AUTO(mesg, PONG, true, (char*[]) { source, target, NULL }, 1) - -#define Assm_cmd_OPER(mesg, name, password) Assm_AUTO(mesg, OPER, true, (char*[]) { name, password, NULL }, 2) -#define Assm_cmd_SQUIT(mesg, server, comment) Assm_AUTO(mesg, SQUIT, true, (char*[]) { server, comment, NULL }, 2) -#define Assm_cmd_PRIVMSG(mesg, target, message) Assm_AUTO(mesg, PRIVMSG, true, (char*[]) { target, message, NULL }, 2) -#define Assm_cmd_NOTICE(mesg, target, text) Assm_AUTO(mesg, NOTICE, true, (char*[]) { target, text, NULL }, 2) -#define Assm_cmd_SQUERY(mesg, servicename, text) Assm_AUTO(mesg, SQUERY, true, (char*[]) { servicename, text, NULL }, 2) -#define Assm_cmd_KILL(mesg, nick, comment) Assm_AUTO(mesg, KILL, true, (char*[]) { nick, comment, NULL }, 2) -#define Assm_cmd_INVITE(mesg, nick, channel) Assm_AUTO(mesg, INVITE, false, (char*[]) { nick, channel, NULL }, 2) - -#define Assm_cmd_MODE(mesg, nickname, modes, modeparams) Assm_AUTO(mesg, MODE, false, (char*[]) { nickname, modes, modeparams, NULL }, 1) - -#define Assm_cmd_KICK(mesg, channels, users, comment) Assm_AUTO(mesg, KICK, true, (char*[]) { channels, users, comment, NULL }, 2) -#define Assm_cmd_CONNECT(mesg, target, port, remote) Assm_AUTO(mesg, CONNECT, false, (char*[]) { target, port, remote, NULL }, 2) - -#define Assm_cmd_SERVICE(mesg, nickname, distribution, type, info) \ - Assm_AUTO(mesg, SERVICE, true, (char*[]) { nickname, RESERVED, distribution, "0", RESERVED, info, NULL }, 6) - -#ifdef UIRC_IRCV3 -#define Assm_cmd_CAP_END(mesg) Assm_AUTO(mesg, CAP, false, (char*[]) { "END", NULL }, 0) -#define Assm_cmd_CAP_LIST(mesg) Assm_AUTO(mesg, CAP, false, (char*[]) { "LIST", NULL }, 0) - -#define Assm_cmd_CAP_LS(mesg, version) Assm_AUTO(mesg, CAP, false, (char*[]) { "LS", version, NULL }, 0) -#define Assm_cmd_CAP_REQ(mesg, caps) Assm_AUTO(mesg, CAP, true, (char*[]) { "REQ", caps, NULL }, 1) - -#define Assm_cmd_CAP_NEW(mesg, nick, caps) Assm_AUTO(mesg, CAP, true, (char*[]) { "NEW", nick, caps, NULL }, 2) -#define Assm_cmd_CAP_DEL(mesg, nick, caps) Assm_AUTO(mesg, CAP, true, (char*[]) { "DEL", nick, caps, NULL }, 2) -#endif /* UIRC_IRCV3 */ -#endif /* UIRC_HELPERS */ - -#endif /* UIRC_GUARD_ASSEMBLERS */ - diff --git a/src/public/capabilities.h b/src/public/capabilities.h deleted file mode 100644 index 731af18..0000000 --- a/src/public/capabilities.h +++ /dev/null @@ -1,81 +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 . - */ - -/*! \file */ - -#ifndef UIRC_GUARD_CAPABILITIES -#define UIRC_GUARD_CAPABILITIES - -/*! - * \brief Converts capability to bitmask value - * - * \param[in] cap Capability bit from \link caps \endlink - */ -#define CAPBIT(cap) (1 << (cap)) - -/*! - * \brief List of capabilities to be used as a bitmask - * - * \sa CAPBIT - * \sa https://ircv3.net/registry#capabilities - */ -enum caps { - CAP_ACCOUNT_NOTIFY, - CAP_ACCOUNT_TAG, - CAP_AWAY_NOTIFY, - CAP_BATCH, - CAP_CAP_NOTIFY, - CAP_CHANNEL_RENAME, - CAP_CHGHOST, - CAP_ECHO_MESSAGE, - CAP_EXTENDED_JOIN, - CAP_INVITE_NOTIFY, - CAP_LABELED_RESPONSE, - CAP_MESSAGE_TAGS, - CAP_MONITOR, - CAP_MULTI_PREFIX, - CAP_MULTILINE, - CAP_SASL, - CAP_SERVER_TIME, - CAP_SETNAME, - CAP_TLS, - CAP_USERHOST_IN_NAMES, -}; -#ifdef UIRC_HELPERS -/*! - * \brief Converts a string of capabilities to a bitmask - * - * This function converts all the capabilities from \link IRC_v3_Caps \endlink to a bitmask - * \param[in] caps String of capabilities separated by space - * \sa CAPBIT - * \sa caps - * \sa https://ircv3.net/registry#capabilities - */ -signed int Tok_CAPS(char* caps); -#endif /* UIRC_HELPERS */ - -/*! - * \brief String representations of IRCv3 capabilities - * - * This contains the capabilities from \link caps \endlink in their string form. - * \sa https://ircv3.net/registry#capabilities - */ -extern const char* const IRC_v3_Caps[]; - -#endif /* UIRC_GUARD_CAPABILITIES */ - diff --git a/src/public/commands.h b/src/public/commands.h deleted file mode 100644 index 030c3f5..0000000 --- a/src/public/commands.h +++ /dev/null @@ -1,146 +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 . - */ - -/*! \file */ - -#ifndef UIRC_GUARD_COMMANDS -#define UIRC_GUARD_COMMANDS - -#define UIRC_FCMD ADMIN -/*! - * \brief List of possible string commands - * - * This contains all the commands defined by RFC2812 (LIST, TIME, NAMES, QUIT ...) and extra ones defined by submodules - * It is used for mapping string commands to integers instead of storing them as strings - */ -enum commands { - /*! Used to find information about the administrator of the given server, or current server */ - ADMIN = 10, - /*! Clients can set an automatic reply string for any PRIVMSG commands directed at them */ - AWAY, - /*! Used to request a server to try to establish a new connection to another server immediately */ - CONNECT, - /*! Shutdown the server */ - DIE, - /*! Used by servers when reporting a serious or fatal error to its peers */ - ERROR, - /*! Return information describing the server */ - INFO, - /*! Invite a user to a channel */ - INVITE, - /*! Checks whether a given nickname is currently on IRC */ - ISON, - /*! Request to start listening to the specific channel */ - JOIN, - /*! Request the forced removal of a user from a channel */ - KICK, - /*! Closes client-server connection */ - KILL, - /*! List all servernames */ - LINKS, - /*! List channels and their topics */ - LIST, - /*! Get statistics about the size of the IRC network */ - LUSERS, - /*! Query and change the characteristics of a channel */ - MODE, - /*! Get the "Message Of The Day" of the given server */ - MOTD, - /*! List all nicknames that are visible to him */ - NAMES, - /*! Give user a nickname or change the existing one */ - NICK, - /*! Similar to PRIVMSG but without automatic replies - * \sa PRIVMSG */ - NOTICE, - /*! Obtain operator privileges */ - OPER, - /*! User sending the message is removed from the list of active members */ - PART, - /*! Set connection password */ - PASS, - /*! Test the presence of an active client or server at the other end of the connection - * \sa PING */ - PING, - /*! Reply to ping message - * \sa PONG */ - PONG, - /*! Send private messages between users or channels - * \sa NOTICE */ - PRIVMSG, - // TODO: Document the lines below - QUIT, - REHASH, - RESTART, - SERVER, - SERVICE, - SERVLIST, - SQUERY, - SQUIT, - STATS, - SUMMON, - TIME, - TOPIC, - TRACE, - USER, - USERHOST, - USERS, - VERSION, - WALLOPS, - WHO, - WHOIS, - WHOWAS, -#ifdef UIRC_IRCV3 - /*! \sa https://github.com/ircv3/ircv3-specifications/pull/276 */ - ACC, - /*! \sa https://ircv3.net/specs/extensions/account-notify-3.1 */ - ACCOUNT, - /*! \sa https://ircv3.net/specs/extensions/labeled-response */ - ACK, - /*! \sa https://ircv3.net/specs/extensions/sasl-3.1 */ - AUTHENTICATE, - /*! \sa https://ircv3.net/specs/extensions/batch-3.2 */ - BATCH, - /*! \sa https://ircv3.net/specs/core/capability-negotiation */ - CAP, - /*! \sa https://ircv3.net/specs/extensions/chghost-3.2 */ - CHGHOST, - /*! \sa https://ircv3.net/specs/extensions/standard-replies */ - FAIL, - /*! \sa https://ircv3.net/specs/core/monitor-3.2 */ - MONITOR, - /*! \sa https://ircv3.net/specs/extensions/standard-replies */ - NOTE, - /*! \sa https://github.com/ircv3/ircv3-specifications/pull/420 */ - RENAME, - /*! \sa https://github.com/ircv3/ircv3-specifications/pull/306 */ - RESUME, - /*! \sa https://ircv3.net/specs/extensions/setname */ - SETNAME, - /*! \sa https://ircv3.net/specs/extensions/standard-replies */ - WARN, - /*! \sa https://ircv3.net/specs/extensions/webirc */ - WEBIRC, -#define UIRC_LCMD WEBIRC -#else /* UIRC_IRCV3 */ -#define UIRC_LCMD WHOWAS -#endif /* UIRC_IRCV3 */ -}; -extern const char* const IRC_Cmds[]; - -#endif /* UIRC_GUARD_COMMANDS */ diff --git a/src/public/converters.h b/src/public/converters.h deleted file mode 100644 index 63f4135..0000000 --- a/src/public/converters.h +++ /dev/null @@ -1,26 +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 . - */ - -/*! \file */ - -#ifndef UIRC_GUARD_CONVERTERS -#define UIRC_GUARD_CONVERTERS - -signed short Ircmd_stoi(const char* str); - -#endif /* UIRC_GUARD_CONVERTERS */ diff --git a/src/public/replies.h b/src/public/replies.h deleted file mode 100644 index 757a979..0000000 --- a/src/public/replies.h +++ /dev/null @@ -1,186 +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 . - */ - -/*! \file */ - -#ifndef UIRC_GUARD_REPLIES -#define UIRC_GUARD_REPLIES - -enum replies { - RPL_WELCOME = 1, - RPL_YOURHOST = 2, - RPL_CREATED = 3, - RPL_MYINFO = 4, - RPL_BOUNCE = 5, - -#ifdef UIRC_IRCV3 - /* TO IRCv3 WG: - * Please, stop complicating implementations - * Get people in the WG that actually care about the protocol and understand why and how standards are written - * - * TO LIBRARY USERS: - * Read the above and go speak with them, or just don't use IRCv3 :) - */ - RPL_ISUPPORT = 5, -#endif /* UIRC_IRCV3 */ - - RPL_TRACELINK = 200, - RPL_TRACECONNECTING = 201, - RPL_TRACEHANDSHAKE = 202, - RPL_TRACEUNKNOWN = 203, - RPL_TRACEOPERATOR = 204, - RPL_TRACEUSER = 205, - RPL_TRACESERVER = 206, - RPL_TRACENEWTYPE = 208, - RPL_STATSLINKINFO = 211, - RPL_STATSCOMMANDS = 212, - RPL_STATSCLINE = 213, - RPL_STATSNLINE = 214, - RPL_STATSILINE = 215, - RPL_STATSKLINE = 216, - RPL_STATSYLINE = 218, - RPL_ENDOFSTATS = 219, - RPL_UMODEIS = 221, - RPL_STATSLLINE = 241, - RPL_STATSUPTIME = 242, - RPL_STATSOLINE = 243, - RPL_STATSHLINE = 244, - RPL_LUSERCLIENT = 251, - RPL_LUSEROP = 252, - RPL_LUSERUNKNOWN = 253, - RPL_LUSERCHANNELS = 254, - RPL_LUSERME = 255, - RPL_ADMINME = 256, - RPL_ADMINLOC1 = 257, - RPL_ADMINLOC2 = 258, - RPL_ADMINEMAIL = 259, - RPL_TRACELOG = 261, - RPL_NONE = 300, - RPL_AWAY = 301, - RPL_USERHOST = 302, - RPL_ISON = 303, - RPL_UNAWAY = 305, - RPL_NOWAWAY = 306, - RPL_WHOISUSER = 311, - RPL_WHOISSERVER = 312, - RPL_WHOISOPERATOR = 313, - RPL_WHOWASUSER = 314, - RPL_ENDOFWHO = 315, - RPL_WHOISIDLE = 317, - RPL_ENDOFWHOIS = 318, - RPL_WHOISCHANNELS = 319, - RPL_LISTSTART = 321, - RPL_LIST = 322, - RPL_LISTEND = 323, - RPL_CHANNELMODEIS = 324, - RPL_NOTOPIC = 331, - RPL_TOPIC = 332, - RPL_INVITING = 341, - RPL_SUMMONING = 342, - RPL_VERSION = 351, - RPL_WHOREPLY = 352, - RPL_NAMREPLY = 353, - RPL_LINKS = 364, - RPL_ENDOFLINKS = 365, - RPL_ENDOFNAMES = 366, - RPL_BANLIST = 367, - RPL_ENDOFBANLIST = 368, - RPL_ENDOFWHOWAS = 369, - RPL_INFO = 371, - RPL_MOTD = 372, - RPL_ENDOFINFO = 374, - RPL_MOTDSTART = 375, - RPL_ENDOFMOTD = 376, - RPL_YOUREOPER = 381, - RPL_REHASHING = 382, - RPL_TIME = 391, - RPL_USERSSTART = 392, - RPL_USERS = 393, - RPL_ENDOFUSERS = 394, - RPL_NOUSERS = 395, - - ERR_NOSUCHNICK = 401, - ERR_NOSUCHSERVER = 402, - ERR_NOSUCHCHANNEL = 403, - ERR_CANNOTSENDTOCHAN = 404, - ERR_TOOMANYCHANNELS = 405, - ERR_WASNOSUCHNICK = 406, - ERR_TOOMANYTARGETS = 407, - ERR_NOORIGIN = 409, - ERR_NORECIPIENT = 411, - ERR_NOTEXTTOSEND = 412, - ERR_NOTOPLEVEL = 413, - ERR_WILDTOPLEVEL = 414, - ERR_UNKNOWNCOMMAND = 421, - ERR_NOMOTD = 422, - ERR_NOADMININFO = 423, - ERR_FILEERROR = 424, - ERR_NONICKNAMEGIVEN = 431, - ERR_ERRONEUSNICKNAME = 432, - ERR_NICKNAMEINUSE = 433, - ERR_NICKCOLLISION = 436, - ERR_USERNOTINCHANNEL = 441, - ERR_NOTONCHANNEL = 442, - ERR_USERONCHANNEL = 443, - ERR_NOLOGIN = 444, - ERR_SUMMONDISABLED = 445, - ERR_USERSDISABLED = 446, - ERR_NOTREGISTERED = 451, - ERR_NEEDMOREPARAMS = 461, - ERR_ALREADYREGISTRED = 462, - ERR_NOPERMFORHOST = 463, - ERR_PASSWDMISMATCH = 464, - ERR_YOUREBANNEDCREEP = 465, - ERR_KEYSET = 467, - ERR_CHANNELISFULL = 471, - ERR_UNKNOWNMODE = 472, - ERR_INVITEONLYCHAN = 473, - ERR_BANNEDFROMCHAN = 474, - ERR_BADCHANNELKEY = 475, - ERR_NOPRIVILEGES = 481, - ERR_CHANOPRIVSNEEDED = 482, - ERR_CANTKILLSERVER = 483, - ERR_NOOPERHOST = 491, - ERR_UMODEUNKNOWNFLAG = 501, - ERR_USERSDONTMATCH = 502, - -#ifdef UIRC_IRCV3 - /* https://ircv3.net/registry */ - RPL_STARTTLS = 670, - ERR_STARTTLS = 691, - - RPL_MONONLINE = 730, - RPL_MONOFFLINE = 731, - RPL_MONLIST = 732, - RPL_ENDOFMONLIST = 733, - ERR_MOLISTFULL = 734, - - RPL_LOGGEDIN = 900, - RPL_LOGGEDOUT = 901, - ERR_NICKLOCKED = 902, - RPL_SASLSUCCESS = 903, - ERR_SASLFAIL = 904, - ERR_SASLTOOLONG = 905, - ERR_SASLABORTED = 906, - ERR_SASLALREADY = 907, - ERR_SASLMECHS = 908, -#endif /* UIRC_IRCV3 */ -}; - -#endif /* UIRC_GUARD_REPLIES */ - diff --git a/src/public/types.h b/src/public/types.h deleted file mode 100644 index 35fa1fc..0000000 --- a/src/public/types.h +++ /dev/null @@ -1,55 +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 . - */ - -/*! \file */ - -#include - -#ifndef UIRC_GUARD_TYPES -#define UIRC_GUARD_TYPES - -/*! - */ -typedef unsigned short IRC_Command; - -#ifdef UIRC_IRCV3 -typedef struct { - char* value; /* if present, it isn't NULL and if it has no value, it is "" */ - bool clientbound; -} IRC_Tag; -typedef struct { - /* See https://ircv3.net/registry#tags for more information */ - IRC_Tag account, batch, label, msgid, multiline_concat, time, typing, react, reply; -} IRC_Tags; -#endif /* UIRC_IRCV3 */ - -typedef struct { - char *nick, *user, *host, *orig, *real; -} IRC_User; -typedef struct { -#ifdef UIRC_IRCV3 - IRC_Tags tags; -#endif /* UIRC_IRCV3 */ - IRC_User name; - char* args[16]; /* 0-13 + trailing + NULL */ - bool trailing; /* Tells if the last argument is trailing */ - IRC_Command cmd; -} IRC_Message; - -#endif /* UIRC_GUARD_TYPES */ - diff --git a/src/replies.h b/src/replies.h new file mode 100644 index 0000000..aabf015 --- /dev/null +++ b/src/replies.h @@ -0,0 +1,186 @@ +/* + * 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 . + */ + +/*! \file */ + +#ifndef UIRC_GUARD_PUBLIC_REPLIES +#define UIRC_GUARD_PUBLIC_REPLIES + +enum replies { + IRC_RPL_WELCOME = 1, + IRC_RPL_YOURHOST = 2, + IRC_RPL_CREATED = 3, + IRC_RPL_MYINFO = 4, + IRC_RPL_BOUNCE = 5, + +#ifdef UIRC_FEATURE_IRCV3 + /* TO IRCv3 WG: + * Please, stop complicating implementations + * Get people in the WG that actually care about the protocol and understand why and how standards are written + * + * TO LIBRARY USERS: + * Read the above and go speak with them, or just don't use IRCv3 :) + */ + IRC_RPL_ISUPPORT = 5, +#endif /* UIRC_FEATURE_IRCV3 */ + + IRC_RPL_TRACELINK = 200, + IRC_RPL_TRACECONNECTING = 201, + IRC_RPL_TRACEHANDSHAKE = 202, + IRC_RPL_TRACEUNKNOWN = 203, + IRC_RPL_TRACEOPERATOR = 204, + IRC_RPL_TRACEUSER = 205, + IRC_RPL_TRACESERVER = 206, + IRC_RPL_TRACENEWTYPE = 208, + IRC_RPL_STATSLINKINFO = 211, + IRC_RPL_STATSCOMMANDS = 212, + IRC_RPL_STATSCLINE = 213, + IRC_RPL_STATSNLINE = 214, + IRC_RPL_STATSILINE = 215, + IRC_RPL_STATSKLINE = 216, + IRC_RPL_STATSYLINE = 218, + IRC_RPL_ENDOFSTATS = 219, + IRC_RPL_UMODEIS = 221, + IRC_RPL_STATSLLINE = 241, + IRC_RPL_STATSUPTIME = 242, + IRC_RPL_STATSOLINE = 243, + IRC_RPL_STATSHLINE = 244, + IRC_RPL_LUSERCLIENT = 251, + IRC_RPL_LUSEROP = 252, + IRC_RPL_LUSERUNKNOWN = 253, + IRC_RPL_LUSERCHANNELS = 254, + IRC_RPL_LUSERME = 255, + IRC_RPL_ADMINME = 256, + IRC_RPL_ADMINLOC1 = 257, + IRC_RPL_ADMINLOC2 = 258, + IRC_RPL_ADMINEMAIL = 259, + IRC_RPL_TRACELOG = 261, + IRC_RPL_NONE = 300, + IRC_RPL_AWAY = 301, + IRC_RPL_USERHOST = 302, + IRC_RPL_ISON = 303, + IRC_RPL_UNAWAY = 305, + IRC_RPL_NOWAWAY = 306, + IRC_RPL_WHOISUSER = 311, + IRC_RPL_WHOISSERVER = 312, + IRC_RPL_WHOISOPERATOR = 313, + IRC_RPL_WHOWASUSER = 314, + IRC_RPL_ENDOFWHO = 315, + IRC_RPL_WHOISIDLE = 317, + IRC_RPL_ENDOFWHOIS = 318, + IRC_RPL_WHOISCHANNELS = 319, + IRC_RPL_LISTSTART = 321, + IRC_RPL_LIST = 322, + IRC_RPL_LISTEND = 323, + IRC_RPL_CHANNELMODEIS = 324, + IRC_RPL_NOTOPIC = 331, + IRC_RPL_TOPIC = 332, + IRC_RPL_INVITING = 341, + IRC_RPL_SUMMONING = 342, + IRC_RPL_VERSION = 351, + IRC_RPL_WHOREPLY = 352, + IRC_RPL_NAMREPLY = 353, + IRC_RPL_LINKS = 364, + IRC_RPL_ENDOFLINKS = 365, + IRC_RPL_ENDOFNAMES = 366, + IRC_RPL_BANLIST = 367, + IRC_RPL_ENDOFBANLIST = 368, + IRC_RPL_ENDOFWHOWAS = 369, + IRC_RPL_INFO = 371, + IRC_RPL_MOTD = 372, + IRC_RPL_ENDOFINFO = 374, + IRC_RPL_MOTDSTART = 375, + IRC_RPL_ENDOFMOTD = 376, + IRC_RPL_YOUREOPER = 381, + IRC_RPL_REHASHING = 382, + IRC_RPL_TIME = 391, + IRC_RPL_USERSSTART = 392, + IRC_RPL_USERS = 393, + IRC_RPL_ENDOFUSERS = 394, + IRC_RPL_NOUSERS = 395, + + IRC_ERR_NOSUCHNICK = 401, + IRC_ERR_NOSUCHSERVER = 402, + IRC_ERR_NOSUCHCHANNEL = 403, + IRC_ERR_CANNOTSENDTOCHAN = 404, + IRC_ERR_TOOMANYCHANNELS = 405, + IRC_ERR_WASNOSUCHNICK = 406, + IRC_ERR_TOOMANYTARGETS = 407, + IRC_ERR_NOORIGIN = 409, + IRC_ERR_NORECIPIENT = 411, + IRC_ERR_NOTEXTTOSEND = 412, + IRC_ERR_NOTOPLEVEL = 413, + IRC_ERR_WILDTOPLEVEL = 414, + IRC_ERR_UNKNOWNCOMMAND = 421, + IRC_ERR_NOMOTD = 422, + IRC_ERR_NOADMININFO = 423, + IRC_ERR_FILEIRC_ERROR = 424, + IRC_ERR_NONICKNAMEGIVEN = 431, + IRC_ERR_IRC_ERRONEUSNICKNAME = 432, + IRC_ERR_NICKNAMEINUSE = 433, + IRC_ERR_NICKCOLLISION = 436, + IRC_ERR_USERNOTINCHANNEL = 441, + IRC_ERR_NOTONCHANNEL = 442, + IRC_ERR_USERONCHANNEL = 443, + IRC_ERR_NOLOGIN = 444, + IRC_ERR_SUMMONDISABLED = 445, + IRC_ERR_USERSDISABLED = 446, + IRC_ERR_NOTREGISTERED = 451, + IRC_ERR_NEEDMOREPARAMS = 461, + IRC_ERR_ALREADYREGISTRED = 462, + IRC_ERR_NOPERMFORHOST = 463, + IRC_ERR_PASSWDMISMATCH = 464, + IRC_ERR_YOUREBANNEDCREEP = 465, + IRC_ERR_KEYSET = 467, + IRC_ERR_CHANNELISFULL = 471, + IRC_ERR_UNKNOWNMODE = 472, + IRC_ERR_INVITEONLYCHAN = 473, + IRC_ERR_BANNEDFROMCHAN = 474, + IRC_ERR_BADCHANNELKEY = 475, + IRC_ERR_NOPRIVILEGES = 481, + IRC_ERR_CHANOPRIVSNEEDED = 482, + IRC_ERR_CANTKILLSERVER = 483, + IRC_ERR_NOOPERHOST = 491, + IRC_ERR_UMODEUNKNOWNFLAG = 501, + IRC_ERR_USERSDONTMATCH = 502, + +#ifdef UIRC_FEATURE_IRCV3 + /* https://ircv3.net/registry */ + IRC_RPL_STARTTLS = 670, + IRC_ERR_STARTTLS = 691, + + IRC_RPL_MONONLINE = 730, + IRC_RPL_MONOFFLINE = 731, + IRC_RPL_MONLIST = 732, + IRC_RPL_ENDOFMONLIST = 733, + IRC_ERR_MOLISTFULL = 734, + + IRC_RPL_LOGGEDIN = 900, + IRC_RPL_LOGGEDOUT = 901, + IRC_ERR_NICKLOCKED = 902, + IRC_RPL_SASLSUCCESS = 903, + IRC_ERR_SASLFAIL = 904, + IRC_ERR_SASLTOOLONG = 905, + IRC_ERR_SASLABORTED = 906, + IRC_ERR_SASLALREADY = 907, + IRC_ERR_SASLMECHS = 908, +#endif /* UIRC_FEATURE_IRCV3 */ +}; + +#endif /* UIRC_GUARD_PUBLIC_REPLIES */ + diff --git a/src/string.c b/src/string.c deleted file mode 100644 index becaebb..0000000 --- a/src/string.c +++ /dev/null @@ -1,47 +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 "private/string.h" - -#include - -void -skip_spaces(char** addr) -{ - for (; **addr == ' '; (*addr)++) - ; -} - -char* -strtok_mr(char** addr, const char* tokens) -{ - if (addr == NULL || *addr == NULL || !**addr || tokens == NULL) return NULL; - char* save = *addr; - const char* tok = NULL; - do { - if (!**addr) return save; - for (tok = tokens; *tok; tok++) { - if (**addr == *tok) { - **addr = '\0'; - break; - } - } - } while (*(*addr)++); - return save; -} - diff --git a/src/tags.c b/src/tags.c deleted file mode 100644 index 66ea48d..0000000 --- a/src/tags.c +++ /dev/null @@ -1,32 +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 "public/tags.h" - -#include -#include - -#ifdef UIRC_HELPERS -size_t -Assm_tag_timestamp(char* buf, size_t len, time_t time) -{ - assert(buf != NULL); - return strftime(buf, len, "%Y-%m-%dT%H:%M:%S.000Z", gmtime(&time)); -} -#endif /* UIRC_HELPERS */ - diff --git a/src/tests/assemblers/message.c b/src/tests/assemblers/message.c new file mode 100644 index 0000000..44258dd --- /dev/null +++ b/src/tests/assemblers/message.c @@ -0,0 +1,62 @@ +/* + * 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/assemblers.h" // Assm_mesg() +#include "../../types.h" // IRC_* +#include "../common.h" // expect() + +#include // assert() +#include // bool +#include // EXIT_SUCCESS + +#define KEY1 "msgid" +#define VAL1 "lol" +#define KEY2 "wow" +#define NICK "bazinga" +#define HOST "monke.uk" +#define COMMAND "NOTICE" +#define ARG1 "urmomgay" +#define TRAILING "what's up retard" + +int +main(void) +{ + IRC_Message m[] = { + { .command = COMMAND, .args = { ARG1, TRAILING, NULL }, .trailing = true }, + { .tag_list = &(llist_t) { .content = &(IRC_Tag) { .key = KEY1, .value = VAL1, .clientbound = true }, + .next = &(llist_t) { .content = &(IRC_Tag) { .key = KEY2 } } }, + .source = &(IRC_User) { .nick = NICK, .host = HOST }, + .command = COMMAND, + .args = { ARG1, TRAILING, NULL }, + .trailing = true }, + }; + const char* str[] = { COMMAND " " ARG1 " :" TRAILING, "@+" KEY1 "=" VAL1 ";" KEY2 " :" NICK "@" HOST " " COMMAND " " ARG1 " :" TRAILING }; + + char buf[513]; + signed long ret; + for (unsigned long i = 0; i < sizeof(str) / sizeof(*str); i++) { + if ((ret = uirc_assembler_message(buf, &m[i], sizeof(buf) / sizeof(char))) <= 0) { + printf("Failed to convert IRC_User struct to a string. %li\n", ret); + return EXIT_FAILURE; + } + expect(buf, str[i]); + print_irc_message(&m[i]); + } + return EXIT_SUCCESS; +} + diff --git a/src/tests/numericmds.c b/src/tests/assemblers/tag.c similarity index 50% rename from src/tests/numericmds.c rename to src/tests/assemblers/tag.c index 1bda666..d9f87e1 100644 --- a/src/tests/numericmds.c +++ b/src/tests/assemblers/tag.c @@ -16,32 +16,30 @@ * along with uIRC. If not, see . */ -#include "../public/assemblers.h" -#include "../public/replies.h" -#include "../public/types.h" +#include "../../assemblers/assemblers.h" // Assm_mesg() +#include "../common.h" // expect() -#include -#include -#include +#include // EXIT_SUCCESS EXIT_FAILURE + +#define key1 "msgid" +#define val1 "30" +#define key2 "time" +#define key3 "x" +#define val3 "spx" int main(void) { - char mesg[513] = { 0 }; - IRC_Message input = { - .cmd = RPL_WELCOME, - .args = { "hello", NULL }, - .trailing = true, - }; - signed long res; - if ((res = Assm_mesg(mesg, &input, 512)) <= 0) { - printf("Failed to assemble message. (%li)\n", res); - return EXIT_FAILURE; - } - char* expect = "001 :hello\r\n"; - if (strcmp(expect, mesg) != 0) { - printf("Assembled message mismatch.\nGot:\n%s\nbut expected:\n%s\n", mesg, expect); - return EXIT_FAILURE; + const char* str[] = { "+" key1 "=" val1, key2, key3 "=" val3 }; + const IRC_Tag tag[] = { { .key = key1, .value = val1, .clientbound = true }, { .key = key2 }, { .key = key3, .value = val3 } }; + char buf[513]; + signed long ret; + for (unsigned long i = 0; i < sizeof(str) / sizeof(*str); i++) { + if ((ret = uirc_assembler_tag(buf, &tag[i], sizeof(buf) / sizeof(char))) < 0) { + printf("Failed to convert tag %lu to \"%s\". Error %li\n", i, str[i], ret); + return EXIT_FAILURE; + } + expect(buf, str[i]); } return EXIT_SUCCESS; } diff --git a/src/tests/junk.c b/src/tests/assemblers/user.c similarity index 54% rename from src/tests/junk.c rename to src/tests/assemblers/user.c index c040b72..7e11c9e 100644 --- a/src/tests/junk.c +++ b/src/tests/assemblers/user.c @@ -16,25 +16,29 @@ * along with uIRC. If not, see . */ -#include "../public/tokenizers.h" -#include "../public/types.h" +#include "../../assemblers/assemblers.h" // Assm_user() +#include "../common.h" // expect() -#include -#include -#include +#include // EXIT_SUCCESS EXIT_FAILURE + +#define NICK "bruh" +#define USER "sound" +#define HOST "numero.dos" int main(void) { - char mesg[][513] = { - "", "NO ", "CM:", "@:", "@ ", "@ N", "@ N:", "\n", "\r", "AA x :\r", "9A x :\r", "XA x :\r", - }; - IRC_Message out = { 0 }; - for (unsigned long i = 0; i < sizeof(mesg) / sizeof(*mesg); i++) { - if (Tok_mesg(mesg[i], &out) == 1) { - printf("Message was parsed successfuly when it was junk.\nTest failed: #%lu %s\n", i, mesg[i]); + const char* str[] = { NICK "!" USER "@" HOST, HOST }; + IRC_User u[] = { { .nick = NICK, .user = USER, .host = HOST }, { .host = HOST } }; + char buf[513]; + signed long ret; + for (unsigned long i = 0; i < sizeof(str) / sizeof(*str); i++) { + if ((ret = uirc_assembler_user(buf, &u[i], sizeof(buf) / sizeof(char))) <= 0) { + printf("Failed to convert IRC_User struct to a string. %li\n", ret); return EXIT_FAILURE; } + expect(buf, str[i]); + print_irc_user(&u[i]); } return EXIT_SUCCESS; } diff --git a/src/tests/common.c b/src/tests/common.c new file mode 100644 index 0000000..7da349a --- /dev/null +++ b/src/tests/common.c @@ -0,0 +1,82 @@ +/* + * 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 "common.h" + +#include "../types.h" // IRC_Message + +#include // printf() +#include // exit() +#include // strcmp() + +#define DELIMITER "-------------\n" +#define PRINTVARORNULL(VAR) ((VAR != NULL) ? VAR : "NULL") + +void +expect(const char* var, const char* exp) +{ + if (strcmp(var, exp) != 0) { + printf("Expected \"%s\" but got \"%s\" instead.\n", exp, var); + exit(EXIT_FAILURE); + } +} + +void +print_irc_message(IRC_Message* ptr) +{ +#ifdef UIRC_FEATURE_IRCV3 + printf(DELIMITER); + + llist_t* tmp = ptr->tag_list; + for (; tmp != NULL; tmp = tmp->next) { print_irc_tag((IRC_Tag*) tmp->content); } +#endif /* UIRC_FEATURE_IRCV3 */ + + if (ptr->source != NULL) { print_irc_user(ptr->source); } + + if (ptr->command != NULL) printf("mc: %s\n", ptr->command); + + for (short i = 0; i < IRC_MAXARGS && ptr->args[i] != NULL; i++) { printf("marg[%i]: %s\n", i, ptr->args[i]); } + + printf(DELIMITER); +} + +#ifdef UIRC_FEATURE_IRCV3 +void +print_irc_tag(IRC_Tag* tag) +{ + printf(DELIMITER "tn: %s\n" + "tv: %s\n" + "tc: %i\n" DELIMITER, + PRINTVARORNULL(tag->key), + PRINTVARORNULL(tag->value), + tag->clientbound); +} +#endif /* UIRC_FEATURE_IRCV3 */ + +void +print_irc_user(IRC_User* user) +{ + printf(DELIMITER "un: %s\n" + "uu: %s\n" + "ur: %s\n" + "uh: %s\n" DELIMITER, + PRINTVARORNULL(user->nick), + PRINTVARORNULL(user->user), + PRINTVARORNULL(user->real), + PRINTVARORNULL(user->host)); +} diff --git a/src/private/memory.h b/src/tests/common.h similarity index 58% rename from src/private/memory.h rename to src/tests/common.h index 22d4c0a..d5350c7 100644 --- a/src/private/memory.h +++ b/src/tests/common.h @@ -16,14 +16,25 @@ * along with uIRC. If not, see . */ -#include -#include +#include "../types.h" // IRC_* -#ifndef UIRC_GUARD_MEMORY -#define UIRC_GUARD_MEMORY +#include // printf() +#include // exit() +#include // strcmp() -size_t safe_strcpy(char** dest, const char* src, size_t lef); -bool safe_charcpy(char** dest, char c, size_t lef); +#ifndef UIRC_GUARD_PRIVATE_COMMONTESTS +#define UIRC_GUARD_PRIVATE_COMMONTESTS -#endif /* UIRC_GUARD_MEMORY */ +#define ERRIFNULL(VAR, ...) \ + if (VAR == NULL) printf(__VA_ARGS__) + +void expect(const char* var, const char* exp); + +void print_irc_message(IRC_Message* ptr); +#ifdef UIRC_FEATURE_IRCV3 +void print_irc_tag(IRC_Tag* tag); +#endif /* UIRC_FEATURE_IRCV3 */ +void print_irc_user(IRC_User* user); + +#endif /* UIRC_GUARD_PRIVATE_COMMONTESTS */ diff --git a/src/tests/general/fullloop.c b/src/tests/general/fullloop.c new file mode 100644 index 0000000..53fd823 --- /dev/null +++ b/src/tests/general/fullloop.c @@ -0,0 +1,52 @@ +/* + * 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/assemblers.h" // Assm_mesg() +#include "../../tokenizers/tokenizers.h" // Tok_mesg() +#include "../../types.h" // IRC_User +#include "../common.h" // expect() + +#include // assert() +#include // EXIT_SUCCESS + +int +main(void) +{ + const char* str[] = { ":buddy@hostnet.com PRIVMSG #general :login hunter12", + "NOTICE * :nice cock bro", + "@day=13;willtolive=0 PRIVMSG you :helo", + ":mom!mother@localhost NOTICE #netadmin :johnny, your pizza is done" }; + + for (unsigned long i = 0; i < sizeof(str) / sizeof(*str); i++) { + IRC_Message* m = NULL; + if ((m = uirc_tokenizer_message(str[i])) == NULL) { + printf("Failed to convert string to IRC_Message struct.\n"); + return EXIT_FAILURE; + } + signed long ret; + char buf[513]; + if ((ret = uirc_assembler_message(buf, m, sizeof(buf) / sizeof(char))) <= 0) { + printf("Failed to convert IRC_Message struct to a string. (%li)\n", ret); + return EXIT_FAILURE; + } + expect(buf, str[i]); + print_irc_message(m); + } + + return EXIT_SUCCESS; +} diff --git a/src/tests/msgassm.c b/src/tests/msgassm.c deleted file mode 100644 index b7353ee..0000000 --- a/src/tests/msgassm.c +++ /dev/null @@ -1,56 +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 "../public/assemblers.h" -#include "../public/commands.h" -#include "../public/types.h" - -#include -#include -#include - -int -main(void) -{ - char mesg[513] = { 0 }; - IRC_Message input = { -#ifdef UIRC_IRCV3 - .tags = { .msgid = { .value = "10" } }, -#endif - .name = { .nick = "dad", .user = "dad-door", .host = "home.localhost" }, - .cmd = PRIVMSG, - .args = { "(You)", "are ya winning son?", NULL }, - .trailing = true, - }; - signed long res; - if ((res = Assm_mesg(mesg, &input, 512)) <= 0) { - printf("Failed to assemble message. (%li)\n", res); - return EXIT_FAILURE; - } - char* expect = -#ifdef UIRC_IRCV3 - "@msgid=10 " -#endif - ":dad!dad-door@home.localhost PRIVMSG (You) :are ya winning son?\r\n"; - if (strcmp(expect, mesg) != 0) { - printf("Assembled message mismatch.\nGot:\n%s\nbut expected:\n%s\n", mesg, expect); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - diff --git a/src/tests/notrail.c b/src/tests/notrail.c deleted file mode 100644 index bb1e75c..0000000 --- a/src/tests/notrail.c +++ /dev/null @@ -1,42 +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 "../public/tokenizers.h" -#include "../public/types.h" - -#include -#include -#include - -int -main(void) -{ - char mesg[513] = ":nick!user@host QUIT arg1 "; - IRC_Message parseout = { 0 }; - int res = 0; - if ((res = Tok_mesg(mesg, &parseout)) <= 0) { - printf("String could not be tokenized. %i\n", res); - return EXIT_FAILURE; - } - if (parseout.trailing) { - printf("Got unexpected trailing."); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - diff --git a/src/tests/overflow.c b/src/tests/overflow.c deleted file mode 100644 index 573cf20..0000000 --- a/src/tests/overflow.c +++ /dev/null @@ -1,49 +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 "../public/assemblers.h" -#include "../public/commands.h" -#include "../public/types.h" - -#include -#include -#include - -int -main(void) -{ - char mesg[513] = { 0 }; - IRC_Message input = { - .cmd = NOTICE, - .args = { "*", - "Cock and ball torture (CBT), penis torture or dick torture is a sexual activity involving application of pain or constriction to " - "the penis or testicles. This may involve directly painful activities, such as genital piercing, wax play, genital spanking, " - "squeezing, ball-busting, genital flogging, urethral play, tickle torture, erotic electrostimulation, kneeing or kicking. The " - "recipient of such activities may receive direct physical pleasure via masochism, or emotional pleasure through erotic humiliation, " - "or knowledge that the play is pleasing to a sadistic dominant. Many of these practices carry significant health risks.", - NULL }, - .trailing = true - }; - signed long i; - if ((i = Assm_mesg(mesg, &input, 512)) > 0) { - fprintf(stderr, "Got %li instead of < 0", i); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - diff --git a/src/tests/spacedargs.c b/src/tests/spacedargs.c deleted file mode 100644 index 6f81275..0000000 --- a/src/tests/spacedargs.c +++ /dev/null @@ -1,56 +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 "../public/commands.h" -#include "../public/tokenizers.h" -#include "../public/types.h" - -#include -#include -#include - -#define cmd "QUIT" -#define arg1 "arg1" -#define arg2 "arg2" -#define trailing "Finished!" - -int -main(void) -{ - char mesg[513] = cmd " " arg1 " " arg2 " :" trailing; - IRC_Message parseout; - int res = 0; - if ((res = Tok_mesg(mesg, &parseout)) <= 0) { - printf("String could not be tokenized. %i\n", res); - return EXIT_FAILURE; - } - if (strcmp(parseout.args[0], arg1) != 0) { - printf("Arg1 didn't match, got \"%s\" instead of \"%s\"\n", parseout.args[0], arg1); - return EXIT_FAILURE; - } - if (strcmp(parseout.args[1], arg2) != 0) { - printf("Arg2 didn't match, got \"%s\" instead of \"%s\"\n", parseout.args[1], arg2); - return EXIT_FAILURE; - } - if (strcmp(parseout.args[2], trailing) != 0) { - printf("Trailing didn't match, got \"%s\" instead of \"%s\"\n", parseout.args[2], trailing); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - diff --git a/src/tests/strtokmr.c b/src/tests/strtokmr.c deleted file mode 100644 index 196336a..0000000 --- a/src/tests/strtokmr.c +++ /dev/null @@ -1,54 +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 "../private/string.h" - -#include -#include -#include - -int -main(void) -{ - char* pointer = NULL; - if (strtok_mr(&pointer, "!") != NULL) return EXIT_FAILURE; - if (pointer != NULL) return EXIT_FAILURE; - - char test2[] = "hello"; - pointer = test2; - if (strtok_mr(&pointer, "!") == NULL) return EXIT_FAILURE; - if (*pointer != '\0') return EXIT_FAILURE; - - char test3[] = "hi!# hello!"; - pointer = test3; - if (strtok_mr(&pointer, "!#") == NULL) return EXIT_FAILURE; - if (pointer != test3 + 3) /* MUST point at # right after ! */ - return EXIT_FAILURE; - if (test3[2] != '\0') /* MUST replace ! with \0 */ - return EXIT_FAILURE; - if (strtok_mr(&pointer, "!#") == NULL) return EXIT_FAILURE; - if (pointer != test3 + 4) /* MUST point at whitespace right after # */ - return EXIT_FAILURE; - if (test3[3] != '\0') /* MUST replace # with \0 */ - return EXIT_FAILURE; - if (strtok_mr(&pointer, "!#") == NULL) return EXIT_FAILURE; - if (strtok_mr(&pointer, "!#") != NULL) return EXIT_FAILURE; - - return EXIT_SUCCESS; -} - diff --git a/src/tests/tagassm.c b/src/tests/tagassm.c deleted file mode 100644 index 60b3724..0000000 --- a/src/tests/tagassm.c +++ /dev/null @@ -1,42 +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 "../public/assemblers.h" -#include "../public/types.h" - -#include -#include -#include - -int -main(void) -{ - char mesg[513] = { 0 }; - IRC_Tags input = { .time = { .value = "now", .clientbound = true }, .msgid = { .value = "", .clientbound = false } }; - signed long res = 0; - if ((res = Assm_tags(mesg, &input, 512)) <= 0) { - printf("String could not be assembled. %li\n", res); - return EXIT_FAILURE; - } - if (strcmp(mesg, "@+time=now;msgid") != 0 && strcmp(mesg, "@msgid;+time=now") != 0) { - printf("String was not assembled properly. Have %s\n", mesg); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - diff --git a/src/tests/tagtok.c b/src/tests/tagtok.c deleted file mode 100644 index 0ea4dfb..0000000 --- a/src/tests/tagtok.c +++ /dev/null @@ -1,46 +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 "../public/tokenizers.h" -#include "../public/types.h" - -#include -#include -#include - -int -main(void) -{ - char mesg[513] = "@msgid=1s32;+time QUIT"; - IRC_Message parseout; - int res = 0; - if ((res = Tok_mesg(mesg, &parseout)) <= 0) { - printf("String could not be tokenized. %i\n", res); - return EXIT_FAILURE; - } - if (parseout.tags.msgid.value == NULL || strcmp(parseout.tags.msgid.value, "1s32") != 0) { - printf("Message ID was not properly parsed.\n"); - return EXIT_FAILURE; - } - if (parseout.tags.time.value == NULL || *parseout.tags.time.value != '\0' || !parseout.tags.time.clientbound) { - printf("Time was not properly parsed.\n"); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - diff --git a/src/tests/timestamp.c b/src/tests/timestamp.c deleted file mode 100644 index f414963..0000000 --- a/src/tests/timestamp.c +++ /dev/null @@ -1,35 +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 "../public/tags.h" -#include "../public/types.h" - -#include -#include -#include -#include - -int -main(void) -{ - char buffer[26]; - time_t res = 1130620230; - if (Assm_tag_timestamp(buffer, sizeof(buffer), res) && strcmp("2005-10-29T21:10:30.000Z", buffer) == 0) return EXIT_SUCCESS; - return EXIT_FAILURE; -} - diff --git a/src/tests/tokenizer.c b/src/tests/tokenizer.c deleted file mode 100644 index 500bd1f..0000000 --- a/src/tests/tokenizer.c +++ /dev/null @@ -1,69 +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 "../public/commands.h" -#include "../public/tokenizers.h" - -#include -#include -#include - -#define nickname "nick" -#define username "user" -#define hostname "host" -#define arg2 "Finished!" - -int -main(void) -{ - char mesg[2][513] = { -#ifdef UIRC_IRCV3 - "@+msgid=1s32;time;+reply;account=x " -#endif - ":" nickname "!" username "@" hostname " QUIT arg1 :" arg2, - "001 hell :sup cj" - }; - IRC_Message parseout = { 0 }; - int res = 0; - if ((res = Tok_mesg(mesg[0], &parseout)) <= 0) { - printf("String could not be tokenized. %i\n", res); - return EXIT_FAILURE; - } - if (parseout.args[1] == NULL || strcmp(parseout.args[1], arg2) != 0) { - printf("Unexpected result. Got %s instead of %s\n", parseout.args[1], arg2); - return EXIT_FAILURE; - } - if (parseout.name.user == NULL || strcmp(parseout.name.user, username) != 0) { - printf("Unexpected result. Got %s instead of %s\n", parseout.name.user, username); - return EXIT_FAILURE; - } - if (parseout.cmd != QUIT) { - printf("Unexpected command result. Got %i instead of %i\n", parseout.cmd, QUIT); - return EXIT_FAILURE; - } - if ((res = Tok_mesg(mesg[1], &parseout)) <= 0) { - printf("String could not be tokenized. %i\n", res); - return EXIT_FAILURE; - } - if (parseout.cmd != 1) { - printf("Unexpected command result. Got %i instead of %i\n", parseout.cmd, 1); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - diff --git a/src/tests/prefixassm.c b/src/tests/tokenizers/message.c similarity index 55% rename from src/tests/prefixassm.c rename to src/tests/tokenizers/message.c index 91a958b..5f2d6d3 100644 --- a/src/tests/prefixassm.c +++ b/src/tests/tokenizers/message.c @@ -16,27 +16,30 @@ * along with uIRC. If not, see . */ -#include "../public/assemblers.h" -#include "../public/types.h" +#include "../../tokenizers/tokenizers.h" // Tok_user() +#include "../../types.h" // IRC_User +#include "../common.h" // expect() -#include -#include -#include +#include // assert() +#include // EXIT_SUCCESS + +#define COMMAND "NOTICE" +#define ARG1 "urmomgay" +#define TRAILING "what's up retard" int main(void) { - char mesg[513] = { 0 }; - IRC_User input = { .nick = "durov", .user = "pavel", .host = "telegram.org" }; - signed long res = 0; - if ((res = Assm_user(mesg, &input, 512, false)) <= 0) { - printf("String could not be assembled. %li\n", res); - return EXIT_FAILURE; - } - if (strcmp(mesg, "durov!pavel@telegram.org") != 0) { - printf("String was not assembled properly. Have %s\n", mesg); + IRC_Message* m = uirc_tokenizer_message(COMMAND " " ARG1 " :" TRAILING); + ERRIFNULL(m, "Message wasn't tokenized successfully.\n"); + expect(m->command, COMMAND); + expect(m->args[0], ARG1); + expect(m->args[1], TRAILING); + if (!m->trailing) { + printf("Message wasn't trailing when it should've been.\n"); return EXIT_FAILURE; } + print_irc_message(m); return EXIT_SUCCESS; } diff --git a/src/tests/tokenizers/tag.c b/src/tests/tokenizers/tag.c new file mode 100644 index 0000000..f9efa93 --- /dev/null +++ b/src/tests/tokenizers/tag.c @@ -0,0 +1,63 @@ +/* + * 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/tokenizers.h" // Tok_tags() +#include "../common.h" // expect() + +#include // assert() +#include // llist_t +#include // EXIT_SUCCESS + +#define key1 "msgid" +#define val1 "30" +#define key2 "time" +#define key3 "x" +#define val3 "spx" + +int +main(void) +{ + IRC_Tag* cur = NULL; + llist_t* tags = uirc_tokenizer_tags("+" key1 "=" val1 ";" key2 ";" key3 "=" val3); + ERRIFNULL(tags, "Tags weren't tokenized successfully.\n"); + + cur = tags->content; + expect(cur->key, key1); + expect(cur->value, val1); + if (!cur->clientbound) { + printf("Tag #1 wasn't clientbound.\n"); + return EXIT_FAILURE; + } + print_irc_tag(cur); + + cur = (tags = tags->next)->content; + expect(cur->key, key2); + if (cur->clientbound) { + printf("Tag #2 was clientbound.\n"); + return EXIT_FAILURE; + } + print_irc_tag(cur); + + cur = (tags = tags->next)->content; + expect(cur->key, key3); + expect(cur->value, val3); + print_irc_tag(cur); + + return EXIT_SUCCESS; +} + diff --git a/src/tests/capbitmask.c b/src/tests/tokenizers/user.c similarity index 59% rename from src/tests/capbitmask.c rename to src/tests/tokenizers/user.c index 756c286..b7e923d 100644 --- a/src/tests/capbitmask.c +++ b/src/tests/tokenizers/user.c @@ -16,21 +16,26 @@ * along with uIRC. If not, see . */ -#include "../public/capabilities.h" +#include "../../tokenizers/tokenizers.h" // Tok_user() +#include "../../types.h" // IRC_User +#include "../common.h" // expect() -#include -#include -#include +#include // assert() +#include // EXIT_SUCCESS + +#define NICK "minion" +#define USER "banana" +#define HOST "freebanana.com" int main(void) { - char wcps[] = "multi-prefix sasl"; - if ((Tok_CAPS(wcps)) != (CAPBIT(CAP_MULTI_PREFIX) | CAPBIT(CAP_SASL))) return EXIT_FAILURE; - char multicaps[] = "sasl echo-message echo-message"; - if ((Tok_CAPS(multicaps)) != (CAPBIT(CAP_ECHO_MESSAGE) | CAPBIT(CAP_SASL))) return EXIT_FAILURE; - char nocaps[] = "random-cap unknown-cap wow"; - if ((Tok_CAPS(nocaps)) != 0) return EXIT_FAILURE; + IRC_User* user = uirc_tokenizer_user(NICK "!" USER "@" HOST); + ERRIFNULL(user, "User wasn't successfully tokenized.\n"); + expect(user->nick, NICK); + expect(user->user, USER); + expect(user->host, HOST); + print_irc_user(user); return EXIT_SUCCESS; } diff --git a/src/tokenizers.c b/src/tokenizers.c deleted file mode 100644 index 99065ef..0000000 --- a/src/tokenizers.c +++ /dev/null @@ -1,179 +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 "public/tokenizers.h" - -#include "private/mappings.h" -#include "private/string.h" -#include "public/commands.h" -#include "public/converters.h" -#include "public/errors.h" -#include "public/tags.h" -#include "public/types.h" - -#include -#include -#include -#include -#include -#include - -#ifdef UIRC_IRCV3 -signed int -Tok_tags(char* str, IRC_Tags* out) -{ - assert(str != NULL); - assert(out != NULL); - 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_mr(&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 /* UIRC_IRCV3 */ - -signed int -Tok_user(char* str, IRC_User* out, bool useorig) -{ - assert(str != NULL); - assert(out != NULL); - 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 */ - *(out->user++) = '\0'; - if (!*(out->nick = pos)) return ERR_UIRC_INVALID_FORMAT; - /* NOTE: De-facto standard below - * This assumes that every prefix without a '@host' and '!user' is itself a host prefix only - * It might be a actual nickname, but this is the most common around every network - * It is left to the user to decide and handle the result accordingly - */ - if (out->host == NULL && out->user == NULL) { - out->host = out->nick; - out->nick = NULL; - } - return 1; -} - -signed int -Tok_mesg(char* str, IRC_Message* out) -{ - assert(str != NULL); - assert(out != NULL); - int ret; - char *progr = str, *command; -#ifdef UIRC_IRCV3 - if (*progr == '@') { - char* tags; - if ((tags = strtok_mr(&progr, " ")) != NULL) { - if ((ret = Tok_tags(tags, &out->tags)) < 0) return ret; - } else - return ERR_UIRC_INVALID_FORMAT; - } - skip_spaces(&progr); -#endif /* UIRC_IRCV3 */ - if (*progr == ':') { - char* prefix; - if ((prefix = strtok_mr(&progr, " ")) != NULL) { - if ((ret = Tok_user(prefix, &out->name, false)) < 0) return ret; - } else - return ERR_UIRC_INVALID_FORMAT; - skip_spaces(&progr); - } - - if (isalnum(*progr) && (command = strtok_mr(&progr, " ")) != NULL) { - signed short temp; - if (isalpha(*command)) { - if ((temp = Ircmd_stoi(command)) < UIRC_FCMD || temp > UIRC_LCMD) return ERR_UIRC_UNKNOWN_TOKEN; - out->cmd = (IRC_Command) temp; - } else { - for (size_t l = 0; command[l]; l++) { - if (!isdigit(command[l])) return ERR_UIRC_INVALID_FORMAT; - } - out->cmd = (IRC_Command) atoi(command); - } - } else - return ERR_UIRC_INVALID_FORMAT; - skip_spaces(&progr); - - short i; - for (i = 0; i < 15 && *progr;) { - if (i == 14 || *progr == ':') { - out->args[i++] = (*progr == ':') ? progr + 1 : progr; - out->trailing = true; - break; - } else { - if ((out->args[i++] = strtok_mr(&progr, " ")) == NULL) return ERR_UIRC_INVALID_FORMAT; - skip_spaces(&progr); - } - } - out->args[i] = NULL; - return 1; -} - -#ifdef UIRC_HELPERS -void -Tok_cmd_PING(const IRC_Message* mesg, char** source, char** target) -{ - assert(mesg != NULL); - assert(source != NULL); - assert(target != NULL); - *source = (mesg->args[0] == NULL && mesg->trailing) ? mesg->args[2] : (mesg->args[1] != NULL) ? mesg->args[0] : NULL; - *target = (mesg->args[1] == NULL) ? mesg->args[0] : mesg->args[1]; -} -/* Use with WHOIS/LINKS - * (stands for first argument optional) - * [ ] - */ - -void -Tok_FArgOpt(const IRC_Message* mesg, char** optarg, char** reqarg) -{ - assert(mesg != NULL); - assert(optarg != NULL); - assert(reqarg != NULL); - *optarg = (mesg->args[1] != NULL) ? mesg->args[0] : NULL; - *reqarg = (mesg->args[1] != NULL) ? mesg->args[1] : mesg->args[0]; -} -#endif /* UIRC_HELPERS */ - diff --git a/src/tokenizers/message.c b/src/tokenizers/message.c new file mode 100644 index 0000000..2fcc870 --- /dev/null +++ b/src/tokenizers/message.c @@ -0,0 +1,119 @@ +/* + * 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 "../memory/memory.h" // Free_IRC_Message() +#include "../types.h" // IRC_Message +#include "tokenizers.h" // Tok_mesg() Tok_user() Tok_tags() + +#include // assert() +#include // malloc_string() strtok_mr() +#include // isalnum() +#include // NULL +#include // malloc() +#include // strlen() + +static void free_ctx(IRC_Message* msg, char* str); +static void skip_spaces(char** addr); + +IRC_Message* +uirc_tokenizer_message(const char* s) +{ + assert(s != NULL); + + IRC_Message* m = malloc(sizeof(IRC_Message)); + char* const ws = malloc_string(s, strlen(s)); + char* p = ws; + if (ws == NULL || m == NULL) { + free(ws); + free(m); + return NULL; + } + memset(m, 0, sizeof(IRC_Message)); + strcpy(ws, s); + +#ifdef UIRC_FEATURE_IRCV3 + if (*p == '@') { + p++; + const char* tmp = NULL; + if ((tmp = strtok_mr(&p, " ")) == NULL || (m->tag_list = uirc_tokenizer_tags(tmp)) == NULL) { + free_ctx(m, ws); + return NULL; + } + } + skip_spaces(&p); +#endif /* UIRC_FEATURE_IRCV3 */ + + if (*p == ':') { + const char* tmp = NULL; + p++; + if ((tmp = strtok_mr(&p, " ")) == NULL || (m->source = uirc_tokenizer_user(tmp)) == NULL) { + free_ctx(m, ws); + return NULL; + } + skip_spaces(&p); + } + + if (isalnum(*p)) { + const char* tmp = NULL; + if ((tmp = strtok_mr(&p, " ")) == NULL || (m->command = malloc_string(tmp, strlen(tmp))) == NULL) { + free_ctx(m, ws); + return NULL; + } + } else + return NULL; + skip_spaces(&p); + + short i; + for (i = 0; i < IRC_MAXARGS && *p;) { + if (i == IRC_MAXARGS - 1 || *p == ':') { + if (*p == ':') p++; + if ((m->args[i++] = malloc_string(p, strlen(p))) == NULL) { + free_ctx(m, ws); + return NULL; + } + m->trailing = true; + break; + } else { + const char* tmp = NULL; + if ((tmp = strtok_mr(&p, " ")) == NULL || (m->args[i++] = malloc_string(tmp, strlen(tmp))) == NULL) { + free_ctx(m, ws); + return NULL; + } + skip_spaces(&p); + } + m->args[i] = NULL; + } + free(ws); + return m; +} + +static void +free_ctx(IRC_Message* msg, char* str) +{ + uirc_free_message(msg); + free(msg); + free(str); +} + +static void +skip_spaces(char** addr) +{ + for (; **addr == ' '; (*addr)++) + ; +} + diff --git a/src/tokenizers/tags.c b/src/tokenizers/tags.c new file mode 100644 index 0000000..05e6483 --- /dev/null +++ b/src/tokenizers/tags.c @@ -0,0 +1,87 @@ +/* + * 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 "../memory/memory.h" // Free_IRC_Tag() +#include "../types.h" // IRC_Tag +#include "tokenizers.h" // uirc_tokenizer_tags() + +#include // assert() +#include // allocate_linked_list_elem() connect_linked_list_elem() remove_linked_list_elem() +#include // malloc_string() +#include // true +#include // free() +#include // strchr() + +static void free_ctx(llist_t* list, char* s); + +// TODO: Only tokenizer IRC_Tag and put the looping logic in uirc_tokenizer_message() + +llist_t* +uirc_tokenizer_tags(const char* s) +{ + assert(s != NULL); + + char* const ws = malloc_string(s, strlen(s)); + char * p = ws, *tmp; + llist_t * pl = NULL, *l = NULL; + + while ((tmp = strtok_mr(&p, ";")) != NULL) { + llist_t* cl; + if ((cl = allocate_linked_list_elem(sizeof(IRC_Tag))) == NULL) { + free_ctx(l, ws); + return NULL; + } + IRC_Tag* tag = (IRC_Tag*) cl->content; + + char* ckey = tmp; + if (*tmp == '+') { + ckey++; + tag->clientbound = true; + } + char* cval = strchr(ckey, '='); + if (cval != NULL) { + *(cval++) = '\0'; + if ((tag->value = malloc_string(cval, strlen(cval))) == NULL) { + free_ctx(l, ws); + return NULL; + } + } + if ((tag->key = malloc_string(ckey, strlen(ckey))) == NULL) { + free_ctx(l, ws); + return NULL; + } + + if (l == NULL) l = cl; + else + connect_linked_list_elem(pl, cl); + pl = cl; + } + return l; +} + +static void +free_ctx(llist_t* list, char* s) +{ + for (llist_t* c = list; c != NULL;) { + llist_t* l = c; + c = c->next; + uirc_free_tag(l->content); + remove_linked_list_elem(l); + } + free(s); +} diff --git a/src/public/tokenizers.h b/src/tokenizers/tokenizers.h similarity index 50% rename from src/public/tokenizers.h rename to src/tokenizers/tokenizers.h index adaba1c..090950f 100644 --- a/src/public/tokenizers.h +++ b/src/tokenizers/tokenizers.h @@ -18,63 +18,39 @@ /*! \file */ -#include "types.h" +#include "../types.h" // IRC_User -#include +#include // llist_t +#include // bool -#ifndef UIRC_GUARD_TOKENIZERS -#define UIRC_GUARD_TOKENIZERS +#ifndef UIRC_GUARD_PUBLIC_TOKENIZERS +#define UIRC_GUARD_PUBLIC_TOKENIZERS -#ifdef UIRC_IRCV3 +#ifdef UIRC_FEATURE_IRCV3 /*! * \brief Tokenize IRCv3 tags * * This function parses IRCv3 tags according to the specification at * \param[in] str String containing a IRC source with or without the ':' prefix - * \param[out] out Allocated IRC_User structure */ -signed int Tok_tags(char* str, IRC_Tags* out); -#endif /* UIRC_IRCV3 */ +llist_t* uirc_tokenizer_tags(const char* str); +#endif /* UIRC_FEATURE_IRCV3 */ /*! * \brief Tokenize a IRC message source. * * This function takes the source part of a message, pointing struct elements to parts of it. * \param[in] str String containing a IRC source with or without the ':' prefix - * \param[out] out Allocated IRC_User structure - * \param[in] useorig If '\%orig' should be considered in the parsing */ -signed int Tok_user(char* str, IRC_User* out, bool useorig); +IRC_User* uirc_tokenizer_user(const char* str); /*! * \brief Tokenize a IRC message string. * * This function takes a IRC Message and attempts to tokenize/parse it, pointing every element found to it's respective struct element * \param[in] str String containing a IRC message without the ending '\\r\\n' - * \param[out] out Allocated IRC_Message structure */ -signed int Tok_mesg(char* str, IRC_Message* out); +IRC_Message* uirc_tokenizer_message(const char* str); -#ifdef UIRC_HELPERS -/*! - * \brief A PING tokenizer/parser - * - * This function is a simple helper to get the source and target of a PING since the RFC has a "interesting" implementation - * \param[in] mesg IRC_Message struct containing the PING message - * \param[out] source Source of the PING (server) - * \param[out] target Target of the PING (server or client) - */ -void Tok_cmd_PING(const IRC_Message* mesg, char** source, char** target); -/*! - * \brief Tokenizer for cases where the first argument is optional - * - * This function is a private helper for cases where the first argument might be missing but the second isn't - * \param[in] mesg IRC_Message struct - * \param[out] optarg Optional argument if found or NULL - * \param[out] reqarg Required argument - */ -void Tok_FArgOpt(const IRC_Message* mesg, char** optarg, char** reqarg); -#endif /* UIRC_HELPERS */ - -#endif /* UIRC_GUARD_TOKENIZERS */ +#endif /* UIRC_GUARD_PUBLIC_TOKENIZERS */ diff --git a/src/tokenizers/user.c b/src/tokenizers/user.c new file mode 100644 index 0000000..0121968 --- /dev/null +++ b/src/tokenizers/user.c @@ -0,0 +1,75 @@ +/* + * 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 "../errors.h" // ERR_UIRC_* +#include "../memory/memory.h" // Free_IRC_User() +#include "../types.h" // IRC_User +#include "tokenizers.h" // Tok_user() + +#include // assert() +#include // malloc_string() +#include // bool +#include // malloc() +#include // strchr() + +static void free_ctx(IRC_User* u, char* s); + +IRC_User* +uirc_tokenizer_user(const char* s) +{ + assert(s != NULL); + + IRC_User* u = malloc(sizeof(IRC_User)); + char* const ws = malloc_string(s, strlen(s)); + char* tmp; + if (u == NULL || ws == NULL) { + free(u); + free(ws); + return NULL; + } + + if ((tmp = strchr(ws, '@')) != NULL) { + *(tmp++) = '\0'; + if ((u->host = malloc_string(tmp, strlen(tmp))) == NULL) { + free_ctx(u, ws); + return NULL; + } + } + if ((tmp = strchr(ws, '!')) != NULL) { + *(tmp++) = '\0'; + if ((u->user = malloc_string(tmp, strlen(tmp))) == NULL) { + free_ctx(u, ws); + return NULL; + } + } + if ((u->nick = malloc_string(ws, strlen(ws))) == NULL) { + free_ctx(u, ws); + return NULL; + } + + free(ws); + return u; +} + +static void +free_ctx(IRC_User* u, char* s) +{ + uirc_free_user(u); + free(u); + free(s); +} diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..34c40a1 --- /dev/null +++ b/src/types.h @@ -0,0 +1,81 @@ +/* + * 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 . + */ + +/*! \file */ + +#include // llist_t +#include // uintmax_t +#include // bool + +#ifndef UIRC_GUARD_PUBLIC_TYPES +#define UIRC_GUARD_PUBLIC_TYPES + +enum IRC_Buffer_Types { IRC_DIRECT, IRC_CHANNEL, IRC_GLOBAL }; + +typedef unsigned short IRC_Modes; +typedef uintmax_t IRC_Counter; + +#ifdef UIRC_FEATURE_IRCV3 +typedef struct { + char *key, *value; + bool clientbound; +} IRC_Tag; + +typedef struct { + char* name; + bool active; +} IRC_Capability; +#endif /* UIRC_FEATURE_IRCV3 */ + +typedef struct { + char * nick, *user, *host, *real; + IRC_Modes modes; + bool is_service; +} IRC_User; + +#define IRC_MAXARGS 15 + +typedef struct { + IRC_User* source; + char* command; + char* args[IRC_MAXARGS]; /* 0-13 + trailing, ended early with a NULL */ + bool trailing; /* Tells if the last argument is trailing */ +#ifdef UIRC_FEATURE_IRCV3 + llist_t* tag_list; +#endif /* UIRC_FEATURE_IRCV3 */ +} IRC_Message; + +typedef struct { + enum IRC_Buffer_Types type; + char * name, *topic, *key; + bool subscribed; + IRC_Modes modes; + llist_t * user_list, *message_list; +} IRC_Buffer; + +typedef struct { + char * addr, *svc; + IRC_User* user; + IRC_Buffer* buf_list; +#ifdef UIRC_FEATURE_IRCV3 + llist_t* cap_list; +#endif /* UIRC_FEATURE_IRCV3 */ +} IRC_Network; + +#endif /* UIRC_GUARD_PUBLIC_TYPES */ + diff --git a/src/public/uirc.h b/src/uirc.h similarity index 82% rename from src/public/uirc.h rename to src/uirc.h index e308194..ac58b83 100644 --- a/src/public/uirc.h +++ b/src/uirc.h @@ -17,19 +17,13 @@ */ #include "assemblers.h" -#include "commands.h" -#include "converters.h" #include "errors.h" #include "modes.h" #include "replies.h" #include "tokenizers.h" #include "types.h" -#ifdef UIRC_VALIDATORS +#ifdef UIRC_FEATURE_VALIDATORS #include "validators.h" -#endif /* UIRC_VALIDATORS */ +#endif /* UIRC_FEATURE_VALIDATORS */ -#ifdef UIRC_IRCV3 -#include "capabilities.h" -#include "tags.h" -#endif /* UIRC_IRCV3 */ diff --git a/src/validators.c b/src/validators/validators.c similarity index 72% rename from src/validators.c rename to src/validators/validators.c index 59bd700..6ee093f 100644 --- a/src/validators.c +++ b/src/validators/validators.c @@ -16,17 +16,16 @@ * along with uIRC. If not, see . */ -#include "public/validators.h" +#include "validators.h" -#include "public/errors.h" -#include "public/types.h" +#include "../errors.h" // ERR_UIRC_* -#include -#include -#include +#include // assert() +#include // NULL +#include // strchr() size_t -Val_type_nocrlf(const char* str) +uirc_validator_string_nocrlf(const char* str) { assert(str != NULL); const char* save = str; @@ -37,7 +36,7 @@ Val_type_nocrlf(const char* str) } size_t -Val_type_nospcl(const char* str) +uirc_validator_string_nospcl(const char* str) { assert(str != NULL); const char* save = str; @@ -48,7 +47,7 @@ Val_type_nospcl(const char* str) } size_t -Val_type_noblcm(const char* str) +uirc_validator_string_noblcm(const char* str) { assert(str != NULL); const char* save = str; @@ -58,8 +57,10 @@ Val_type_noblcm(const char* str) return (size_t)(str - save); } +// TODO: Make this read only +// TODO: Improve the logic for this size_t -Val_channame(char* chan) +uirc_validator_buffer_channel(char* chan) { assert(chan != NULL); if (*chan != '#' && *chan != '+' && *chan != '!' && *chan != '&') return 0; @@ -67,20 +68,20 @@ Val_channame(char* chan) 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) { + if (uirc_validator_string_nospcl(chan) != 1 || uirc_validator_string_nocrlf(chan) != 1 || uirc_validator_string_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; + if (uirc_validator_string_nospcl(chan) != 1 || uirc_validator_string_nocrlf(chan) != 1 || uirc_validator_string_noblcm(chan) != 1) return 0; return (size_t)(save - chan); } // TODO: Work on the logic for this signed short -Val_mesg(IRC_Message* mesg) +uirc_validator_message(IRC_Message* mesg) { assert(mesg != NULL); for (unsigned int i = 0; mesg->args[i] != NULL; i++) { diff --git a/src/public/validators.h b/src/validators/validators.h similarity index 63% rename from src/public/validators.h rename to src/validators/validators.h index 2608022..053c15b 100644 --- a/src/public/validators.h +++ b/src/validators/validators.h @@ -18,18 +18,18 @@ /*! \file */ -#include "types.h" +#include "../types.h" // IRC_Message #include -#ifndef UIRC_GUARD_VALIDATORS -#define UIRC_GUARD_VALIDATORS +#ifndef UIRC_GUARD_PUBLIC_VALIDATORS +#define UIRC_GUARD_PUBLIC_VALIDATORS -size_t Val_type_nocrlf(const char* str); -size_t Val_type_nospcl(const char* str); -size_t Val_type_noblcm(const char* str); -size_t Val_channame(char* chan); -signed short Val_mesg(IRC_Message* mesg); +size_t uirc_validator_string_nocrlf(const char* str); +size_t uirc_validator_string_nospcl(const char* str); +size_t uirc_validator_string_noblcm(const char* str); +size_t uirc_validator_buffer_channel(char* chan); +signed short uirc_validator_message(IRC_Message* mesg); -#endif /* UIRC_GUARD_VALIDATORS */ +#endif /* UIRC_GUARD_PUBLIC_VALIDATORS */