├── .github └── workflows │ ├── ccpp.yml │ └── codeql-v2.yml ├── .gitignore ├── API.md ├── CHANGELOG.md ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── _config.yml ├── cmake-modules ├── CMakeUninstall.cmake.in ├── CTestCustom.cmake.in ├── FindCheck.cmake ├── FindSubunit.cmake └── OrcaniaConfig.cmake.in ├── doc └── doxygen.cfg ├── include ├── orcania-cfg.h.in └── orcania.h ├── liborcania.pc.in ├── src ├── Makefile ├── base64.c ├── memory.c └── orcania.c ├── test ├── .gitignore ├── Makefile ├── memory_test.c ├── pointer_list_test.c ├── run_test.sh ├── split_test.c └── str_test.c └── tools └── base64url ├── .gitignore ├── Makefile ├── README.md ├── base64url.1 └── base64url.c /.github/workflows/ccpp.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | jobs: 4 | build: 5 | 6 | runs-on: ubuntu-latest 7 | 8 | steps: 9 | - uses: actions/checkout@v1 10 | - name: install dependencies 11 | run: | 12 | sudo apt-get update 13 | sudo apt-get install -y cmake pkg-config check libsubunit-dev cppcheck doxygen valgrind 14 | - name: cppcheck 15 | run: cppcheck --force --enable=warning,missingInclude --error-exitcode=1 . 16 | - name: build 17 | run: | 18 | mkdir build 19 | cd build 20 | cmake -DBUILD_ORCANIA_TESTING=on -DBUILD_ORCANIA_DOCUMENTATION=on .. 21 | make test package doc 22 | sudo make install 23 | cd .. 24 | make 25 | make clean check 26 | -------------------------------------------------------------------------------- /.github/workflows/codeql-v2.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL V3" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "master" ] 20 | schedule: 21 | - cron: '42 7 * * 0' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | # Runner size impacts CodeQL analysis time. To learn more, please see: 27 | # - https://gh.io/recommended-hardware-resources-for-running-codeql 28 | # - https://gh.io/supported-runners-and-hardware-resources 29 | # - https://gh.io/using-larger-runners 30 | # Consider using larger runners for possible analysis time improvements. 31 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 32 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 33 | permissions: 34 | actions: read 35 | contents: read 36 | security-events: write 37 | 38 | strategy: 39 | fail-fast: false 40 | matrix: 41 | language: [ 'cpp' ] 42 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] 43 | # Use only 'java' to analyze code written in Java, Kotlin or both 44 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both 45 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 46 | 47 | steps: 48 | - name: Checkout repository 49 | uses: actions/checkout@v3 50 | 51 | # Initializes the CodeQL tools for scanning. 52 | - name: Initialize CodeQL 53 | uses: github/codeql-action/init@v3 54 | with: 55 | languages: ${{ matrix.language }} 56 | # If you wish to specify custom queries, you can do so here or in a config file. 57 | # By default, queries listed here will override any specified in a config file. 58 | # Prefix the list here with "+" to use these queries and those in the config file. 59 | 60 | # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 61 | # queries: security-extended,security-and-quality 62 | 63 | 64 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). 65 | # If this step fails, then you should remove it and run the build manually (see below) 66 | - name: Autobuild 67 | uses: github/codeql-action/autobuild@v3 68 | 69 | # ℹ️ Command-line programs to run using the OS shell. 70 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 71 | 72 | # If the Autobuild fails above, remove it and uncomment the following three lines. 73 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 74 | 75 | - run: | 76 | sudo apt-get update 77 | sudo apt-get install -y cmake pkg-config doxygen 78 | mkdir build 79 | cd build 80 | cmake -DBUILD_ORCANIA_DOCUMENTATION=on .. 81 | make 82 | make doc 83 | sudo make install 84 | 85 | - name: Perform CodeQL Analysis 86 | uses: github/codeql-action/analyze@v3 87 | with: 88 | category: "/language:${{matrix.language}}" 89 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.so.* 4 | *.a 5 | *.pc 6 | *.log 7 | orcania-cfg.h 8 | -------------------------------------------------------------------------------- /API.md: -------------------------------------------------------------------------------- 1 | # Orcania library 2 | 3 | Potluck with different functions for different purposes that can be shared among C programs. 4 | 5 | This is a small library intended to provide low-level functionalities in my other libraries and programs. 6 | 7 | The functionalities are divided into 4 categories: 8 | 9 | ## String functions 10 | 11 | - Wrappers for `string.h`: functions like `strcpy`, `strcmp` or `strchr` that will not segfault if a parameter is `NULL` 12 | - `split_string` and afiliated functions: split a string using a separator match or join a split string 13 | 14 | ## Pointer list structure 15 | 16 | Simple structure to store and manipulate any kind of pointer in an array. 17 | 18 | ## Base64 functions 19 | 20 | Encode, decode in base64 and base64url format. 21 | 22 | ## Memory functions 23 | 24 | Replace glib `malloc/realloc/free` functions with user-defined memory functions. 25 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Orcania Changelog 2 | 3 | ## 2.3.4 4 | 5 | - Minor bugfixes 6 | - Build with flag `-Wpedantic` 7 | 8 | ## 2.3.3 9 | 10 | - Enforce base64decode 11 | 12 | ## 2.3.2 13 | 14 | - Improve cmake script and MSVC support 15 | - Build with flag `-Wconversion` 16 | 17 | ## 2.3.1 18 | 19 | - Minor bugfixes 20 | 21 | ## 2.3.0 22 | 23 | - Add `o_base64_encode_alloc`, `o_base64_decode_alloc`, `o_base64url_encode_alloc`, `o_base64url_decode_alloc`, `o_base64url_2_base64_alloc`, `o_base64_2_base64url_alloc` 24 | - Fix pkg-config file with absolute path for `CMAKE_INSTALL_{INCLUDE,LIB}DIR`, Closes #27 25 | 26 | ## 2.2.2 27 | 28 | - Add `o_strnullempty` 29 | - Breaking: `trimwhitespace` now returns `const char *` instead of `char *`, might give compiler warning 30 | - Refactor `o_base64*` functions 31 | 32 | ## 2.2.1 33 | 34 | - Add ld flags in liborcania.pc on static build 35 | 36 | ## 2.2.0 37 | 38 | - Add command-line tool `base64url` which is similar to GNU `base64` tool but for `base64url` format 39 | 40 | ## 2.1.1 41 | 42 | - Harmonize and fix license 43 | - Fix doc generator 44 | - Rework mstrcatf 45 | - Fix pkgconfig install on Makefile 46 | - Add simple API documentation summary 47 | 48 | ## 2.1.0 49 | 50 | - Add doxygen documentation 51 | - Add functions `pointer_list_clean_free`, `pointer_list_remove_at_free` and `pointer_list_remove_pointer_free` 52 | - `split_string` returns `size_t` 53 | - Add functions `o_strnchr` and `o_strrnchr` 54 | - Add function `trimcharacter` 55 | - Improve `o_base64_decode` if input data is invalid 56 | 57 | ## 2.0.1 58 | 59 | - Fix double free() on `pointer_list_remove_at` 60 | - Fix build for MacOSX (thanks JohnAZoidberg!) 61 | - Clean build process 62 | - Fix config option STRTSR so cmake and makefile will use the same name 63 | 64 | ## 2.0.0 65 | 66 | - Add struct _pointer_list to manage arrays of pointers 67 | - Add string_array_join, string_array_size 68 | - Add o_base64url_encode and o_base64url_decode, and o_base64url_2_base64 to convert base64 url format to base64 69 | - Remove jansson related functions and dependency 70 | - Install pkgconfig file when using Makefile 71 | 72 | ## 1.2.9 73 | 74 | - Add build flag to force inline implementation of strstr if the host system is 75 | not known to implement strstr but isn't listed as so, like FreeRTOS 76 | Thanks to Dirk Uhlemann 77 | - Avoid babelouest/ulfius#84 78 | 79 | ## 1.2.8 80 | 81 | - Fix build with Makefile 82 | - Improve build config file and install headers 83 | 84 | ## 1.2.7 85 | 86 | - Add config file orcania-cfg.h dynamically built with the options 87 | 88 | ## 1.2.6 89 | 90 | - Add Travis CI 91 | - Change cmake option BUILD_TESTING to BUILD_YDER_TESTING 92 | - Add RPM in CMake script package 93 | 94 | ## 1.2.5 95 | 96 | - Fix pkgconfig file 97 | 98 | ## 1.2.4 99 | 100 | - Fix CMake build when /usr/local is not present in default build path 101 | 102 | ## 1.2.3 103 | 104 | - Fix Makefile soname 105 | 106 | ## 1.2.2 107 | 108 | - Upgrade Makefile 109 | 110 | ## 1.2.1 111 | 112 | - Fix string_array_has_trimmed_value 113 | 114 | ## 1.2.0 115 | 116 | - Add CMake installation script 117 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Orcania library 3 | # 4 | # CMake file used to build all programs 5 | # 6 | # Copyright 2018 Silvio Clecio 7 | # Copyright 2018-2022 Nicolas Mora 8 | # 9 | # This program is free software; you can redistribute it and/or 10 | # modify it under the terms of the MIT License 11 | # 12 | # This library is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15 | # 16 | 17 | cmake_minimum_required(VERSION 3.5) 18 | 19 | project(orcania C) 20 | 21 | set(CMAKE_C_STANDARD 99) 22 | if (NOT MSVC) 23 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror") 24 | endif() 25 | 26 | # library info 27 | 28 | set(PROJECT_DESCRIPTION "Potluck with different functions for different purposes that can be shared among programs") 29 | set(PROJECT_HOMEPAGE_URL "https://github.com/babelouest/orcania/") 30 | set(PROJECT_BUGREPORT_PATH "https://github.com/babelouest/orcania/issues") 31 | set(LIBRARY_VERSION_MAJOR "2") 32 | set(LIBRARY_VERSION_MINOR "3") 33 | set(LIBRARY_VERSION_PATCH "4") 34 | 35 | set(PROJECT_VERSION "${LIBRARY_VERSION_MAJOR}.${LIBRARY_VERSION_MINOR}.${LIBRARY_VERSION_PATCH}") 36 | set(PROJECT_VERSION_MAJOR ${LIBRARY_VERSION_MAJOR}) 37 | set(PROJECT_VERSION_MINOR ${LIBRARY_VERSION_MINOR}) 38 | set(PROJECT_VERSION_PATCH ${LIBRARY_VERSION_PATCH}) 39 | 40 | set(ORCANIA_LIBS) 41 | 42 | if (${LIBRARY_VERSION_MAJOR} VERSION_LESS 10) 43 | set (LIBRARY_VERSION_MAJOR_PAD "0${LIBRARY_VERSION_MAJOR}") 44 | else () 45 | set (LIBRARY_VERSION_MAJOR_PAD "${LIBRARY_VERSION_MAJOR}") 46 | endif () 47 | if (${LIBRARY_VERSION_MINOR} VERSION_LESS 10) 48 | set (LIBRARY_VERSION_MINOR_PAD "0${LIBRARY_VERSION_MINOR}") 49 | else () 50 | set (LIBRARY_VERSION_MINOR_PAD "${LIBRARY_VERSION_MINOR}") 51 | endif () 52 | if (${LIBRARY_VERSION_PATCH} VERSION_LESS 10) 53 | set (LIBRARY_VERSION_PATCH_PAD "0${LIBRARY_VERSION_PATCH}") 54 | else () 55 | set (LIBRARY_VERSION_PATCH_PAD "${LIBRARY_VERSION_PATCH}") 56 | endif () 57 | set(PROJECT_VERSION_NUMBER "${LIBRARY_VERSION_MAJOR_PAD}${LIBRARY_VERSION_MINOR_PAD}${LIBRARY_VERSION_PATCH_PAD}") 58 | 59 | set(LIBRARY_VERSION "${LIBRARY_VERSION_MAJOR}.${LIBRARY_VERSION_MINOR}.${LIBRARY_VERSION_PATCH}") 60 | set(LIBRARY_SOVERSION "${LIBRARY_VERSION_MAJOR}.${LIBRARY_VERSION_MINOR}") 61 | 62 | # cmake modules 63 | 64 | set(O_CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules) 65 | list(APPEND CMAKE_MODULE_PATH "${O_CMAKE_MODULE_PATH}") 66 | 67 | include(GNUInstallDirs) 68 | include(CheckSymbolExists) 69 | include(CMakePackageConfigHelpers) 70 | 71 | # check if _GNU_SOURCE is available 72 | 73 | if (NOT _GNU_SOURCE) 74 | check_symbol_exists(__GNU_LIBRARY__ "features.h" _GNU_SOURCE) 75 | 76 | if (NOT _GNU_SOURCE) 77 | unset(_GNU_SOURCE CACHE) 78 | check_symbol_exists(_GNU_SOURCE "features.h" _GNU_SOURCE) 79 | endif () 80 | endif () 81 | 82 | if (_GNU_SOURCE) 83 | add_definitions(-D_GNU_SOURCE) 84 | endif () 85 | 86 | # directories and source 87 | 88 | set(INC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) 89 | set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) 90 | set(BASE64URL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tools/base64url) 91 | 92 | set(LIB_SRC 93 | ${INC_DIR}/orcania.h # allow many IDEs to find and edit it 94 | ${SRC_DIR}/base64.c 95 | ${SRC_DIR}/memory.c 96 | ${SRC_DIR}/orcania.c) 97 | 98 | option(WITH_STRSTR "Use inline implementation of strstr" OFF) 99 | if (WITH_STRSTR) 100 | set(O_STRSTR ON) 101 | else () 102 | set(O_STRSTR OFF) 103 | endif () 104 | 105 | set(PKGCONF_REQ "") 106 | set(PKGCONF_REQ_PRIVATE "") 107 | 108 | # build orcania-cfg.h file 109 | configure_file(${INC_DIR}/orcania-cfg.h.in ${PROJECT_BINARY_DIR}/orcania-cfg.h) 110 | set (CMAKE_EXTRA_INCLUDE_FILES ${PROJECT_BINARY_DIR}) 111 | 112 | option(BUILD_SHARED "Build shared library." ON) 113 | option(BUILD_STATIC "Build static library." OFF) 114 | 115 | if (NOT BUILD_STATIC AND NOT BUILD_SHARED) 116 | message(FATAL_ERROR "BUILD_SHARED and BUILD_STATIC cannot be both disabled") 117 | endif () 118 | 119 | # static library 120 | 121 | if (BUILD_STATIC) 122 | add_library(orcania_static STATIC ${LIB_SRC}) 123 | add_library(Orcania::Orcania-static ALIAS orcania_static) 124 | target_include_directories(orcania_static 125 | PUBLIC "$" 126 | PUBLIC "$" 127 | PUBLIC "$") 128 | target_link_libraries(orcania_static PRIVATE ${ORCANIA_LIBS}) 129 | target_compile_definitions(orcania_static PUBLIC O_STATIC_LIBRARY) 130 | set_target_properties(orcania_static PROPERTIES 131 | PUBLIC_HEADER "${INC_DIR}/orcania.h;${PROJECT_BINARY_DIR}/orcania-cfg.h" 132 | OUTPUT_NAME orcania 133 | EXPORT_NAME Orcania-static) 134 | if (MSVC) 135 | set_target_properties(orcania_static PROPERTIES 136 | OUTPUT_NAME orcania-static) 137 | endif () 138 | if (NOT MSVC) 139 | target_compile_options(orcania_static PRIVATE -Wextra -Wconversion -Wpedantic) 140 | endif () 141 | set(orcania_lib orcania_static) 142 | endif () 143 | 144 | # shared library 145 | 146 | if (BUILD_SHARED) 147 | add_library(orcania SHARED ${LIB_SRC}) 148 | add_library(Orcania::Orcania ALIAS orcania) 149 | target_include_directories(orcania 150 | PUBLIC "$" 151 | PUBLIC "$" 152 | PUBLIC "$") 153 | target_link_libraries(orcania PRIVATE ${ORCANIA_LIBS}) 154 | set_target_properties(orcania PROPERTIES 155 | PUBLIC_HEADER "${INC_DIR}/orcania.h;${PROJECT_BINARY_DIR}/orcania-cfg.h" 156 | VERSION "${LIBRARY_VERSION}" 157 | SOVERSION "${LIBRARY_SOVERSION}" 158 | WINDOWS_EXPORT_ALL_SYMBOLS TRUE 159 | EXPORT_NAME Orcania) 160 | if (WIN32) 161 | set_target_properties(orcania PROPERTIES 162 | SUFFIX "-${LIBRARY_VERSION_MAJOR}.dll") 163 | endif () 164 | if (NOT MSVC) 165 | target_compile_options(orcania PRIVATE -Wextra -Wconversion -Wpedantic) 166 | endif () 167 | set(orcania_lib orcania) 168 | endif () 169 | 170 | # documentation 171 | 172 | option(BUILD_ORCANIA_DOCUMENTATION "Build the documentation." OFF) 173 | if (BUILD_ORCANIA_DOCUMENTATION) 174 | find_package(Doxygen) 175 | if (DOXYGEN_FOUND) 176 | set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/doc/doxygen.cfg) 177 | set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/doxyfile) 178 | 179 | configure_file(${doxyfile_in} ${doxyfile} @ONLY) 180 | 181 | add_custom_target(doc 182 | COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile_in} 183 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 184 | COMMENT "Generating documentation with Doxygen" 185 | VERBATIM) 186 | 187 | else () 188 | message(FATAL_ERROR "Doxygen is needed to build the documentation.") 189 | endif () 190 | endif () 191 | 192 | # build base64url 193 | 194 | option(BUILD_BASE64URL "Build base64url application." ON) 195 | 196 | if (BUILD_BASE64URL) 197 | add_executable(base64url ${BASE64URL_DIR}/base64url.c ${INC_DIR}/orcania.h ${PROJECT_BINARY_DIR}/orcania-cfg.h) 198 | set_target_properties(base64url PROPERTIES SKIP_BUILD_RPATH TRUE) 199 | if (NOT MSVC) 200 | target_compile_options(base64url PRIVATE -Wextra -Wconversion -Wpedantic) 201 | endif () 202 | target_link_libraries(base64url PRIVATE ${orcania_lib}) 203 | install(TARGETS base64url RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 204 | install(FILES ${BASE64URL_DIR}/base64url.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 COMPONENT runtime) 205 | endif () 206 | 207 | # tests 208 | 209 | option(BUILD_ORCANIA_TESTING "Build the testing tree." OFF) # because we do not use include(CTest) 210 | 211 | if (BUILD_ORCANIA_TESTING) 212 | find_package(Check) 213 | if (CHECK_FOUND) 214 | if (NOT WIN32 AND NOT APPLE) 215 | find_package(Subunit REQUIRED) 216 | endif () 217 | 218 | enable_testing() 219 | 220 | set(CMAKE_CTEST_COMMAND ctest -V) 221 | 222 | set(TST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test) 223 | set(TEST_LIBS ${orcania_lib} Check::Check) 224 | if (NOT WIN32) 225 | find_package(Threads REQUIRED) 226 | list(APPEND TEST_LIBS Threads::Threads m) 227 | endif () 228 | if (NOT APPLE AND NOT MSVC) 229 | list(APPEND TEST_LIBS rt) 230 | endif () 231 | if (NOT WIN32 AND NOT APPLE) 232 | list(APPEND TEST_LIBS Subunit::Subunit rt) 233 | endif () 234 | 235 | set(TESTS 236 | str_test 237 | split_test 238 | memory_test 239 | pointer_list_test) 240 | 241 | configure_file( 242 | "${O_CMAKE_MODULE_PATH}/CTestCustom.cmake.in" 243 | "${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake" 244 | @ONLY) 245 | 246 | foreach (t ${TESTS}) 247 | add_executable(${t} EXCLUDE_FROM_ALL ${TST_DIR}/${t}.c) 248 | target_include_directories(${t} PUBLIC ${TST_DIR}) 249 | target_link_libraries(${t} PRIVATE ${TEST_LIBS}) 250 | add_test(NAME ${t} 251 | WORKING_DIRECTORY ${TST_DIR} 252 | COMMAND ${t}) 253 | endforeach () 254 | endif () 255 | endif () 256 | 257 | # install target 258 | 259 | if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") 260 | set(PKGCONFIG_TARGET_INCLUDES "${CMAKE_INSTALL_INCLUDEDIR}") 261 | else() 262 | set(PKGCONFIG_TARGET_INCLUDES "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") 263 | endif() 264 | 265 | if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") 266 | set(PKGCONFIG_TARGET_LIBDIR "${CMAKE_INSTALL_LIBDIR}") 267 | else() 268 | set(PKGCONFIG_TARGET_LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}") 269 | endif() 270 | 271 | option(INSTALL_HEADER "Install the header files" ON) # Install orcania.h or not 272 | 273 | configure_file(liborcania.pc.in liborcania.pc @ONLY) 274 | 275 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/liborcania.pc 276 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) 277 | 278 | set(TARGETS ) 279 | if (BUILD_SHARED) 280 | list(APPEND TARGETS orcania) 281 | endif () 282 | if (BUILD_STATIC) 283 | list(APPEND TARGETS orcania_static) 284 | endif () 285 | 286 | if (INSTALL_HEADER) 287 | install(TARGETS ${TARGETS} EXPORT OrcaniaExports 288 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 289 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 290 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 291 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 292 | else () 293 | install(TARGETS ${TARGETS} EXPORT OrcaniaExports 294 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 295 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 296 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 297 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 298 | endif () 299 | 300 | if (INSTALL_HEADER) 301 | set(ORCANIA_INSTALL_CMAKEDIR_DEFAULT "${CMAKE_INSTALL_LIBDIR}/cmake/Orcania") 302 | if (WIN32 AND NOT MINGW) 303 | set(ORCANIA_INSTALL_CMAKEDIR_DEFAULT "cmake") 304 | endif () 305 | set(ORCANIA_INSTALL_CMAKEDIR ${ORCANIA_INSTALL_CMAKEDIR_DEFAULT} CACHE STRING "Location where to install the cmake config files") 306 | 307 | install(EXPORT OrcaniaExports DESTINATION "${ORCANIA_INSTALL_CMAKEDIR}" 308 | NAMESPACE "Orcania::" 309 | FILE "OrcaniaTargets.cmake") 310 | 311 | configure_package_config_file(cmake-modules/OrcaniaConfig.cmake.in OrcaniaConfig.cmake 312 | INSTALL_DESTINATION "${ORCANIA_INSTALL_CMAKEDIR}") 313 | write_basic_package_version_file(OrcaniaConfigVersion.cmake 314 | COMPATIBILITY AnyNewerVersion) 315 | 316 | install(FILES 317 | "${PROJECT_BINARY_DIR}/OrcaniaConfig.cmake" 318 | "${PROJECT_BINARY_DIR}/OrcaniaConfigVersion.cmake" 319 | DESTINATION "${ORCANIA_INSTALL_CMAKEDIR}") 320 | endif () 321 | 322 | # uninstall target 323 | 324 | if (NOT TARGET uninstall) 325 | configure_file( 326 | "${O_CMAKE_MODULE_PATH}/CMakeUninstall.cmake.in" 327 | "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" 328 | IMMEDIATE @ONLY) 329 | add_custom_target(uninstall 330 | COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) 331 | endif () 332 | 333 | # packaging 334 | 335 | set(CPACK_PACKAGE_VERSION_MAJOR ${LIBRARY_VERSION_MAJOR}) 336 | set(CPACK_PACKAGE_VERSION_MINOR ${LIBRARY_VERSION_MINOR}) 337 | set(CPACK_PACKAGE_VERSION_PATCH ${LIBRARY_VERSION_PATCH}) 338 | 339 | if (INSTALL_HEADER) 340 | set(PACKAGE_FILE_NAME 341 | "lib${CMAKE_PROJECT_NAME}-dev_${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") 342 | else () 343 | set(PACKAGE_FILE_NAME 344 | "lib${CMAKE_PROJECT_NAME}_${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") 345 | endif () 346 | set(PACKAGE_IGNORED_FILES 347 | "${CMAKE_CURRENT_BINARY_DIR}/;/.git/;.gitignore;~$;${CPACK_SOURCE_IGNORE_FILES}") 348 | 349 | set(CPACK_GENERATOR ) 350 | set(CPACK_PACKAGE_NAME "liborcania") 351 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Potluck for C programs") 352 | set(CPACK_PACKAGE_VERSION_MAJOR ${LIBRARY_VERSION_MAJOR}) 353 | set(CPACK_PACKAGE_VERSION_MINOR ${LIBRARY_VERSION_MINOR}) 354 | set(CPACK_PACKAGE_VERSION_PATCH ${LIBRARY_VERSION_PATCH}) 355 | set(CPACK_PACKAGE_FILE_NAME ${PACKAGE_FILE_NAME}) 356 | 357 | option(BUILD_TGZ "Build a TAR.GZ for your system" OFF) 358 | if (BUILD_TGZ) 359 | list(APPEND CPACK_GENERATOR TGZ) 360 | set(CPACK_SOURCE_GENERATOR "TGZ") 361 | set(CPACK_SOURCE_PACKAGE_FILE_NAME ${PACKAGE_FILE_NAME}) 362 | set(CPACK_SOURCE_IGNORE_FILES ${PACKAGE_IGNORED_FILES}) 363 | endif () 364 | 365 | option(BUILD_DEB "Build a DEB for your system" OFF) 366 | if (BUILD_DEB) 367 | list(APPEND CPACK_GENERATOR DEB) 368 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER "mail@babelouest.org") 369 | set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${PROJECT_DESCRIPTION}) 370 | set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/babelouest/orcania") 371 | set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.4)") 372 | endif () 373 | 374 | option(BUILD_RPM "Build a RPM for your system" OFF) 375 | if (BUILD_RPM) 376 | list(APPEND CPACK_GENERATOR RPM) 377 | set(CPACK_RPM_PACKAGE_LICENSE "LGPL") 378 | set(CPACK_RPM_PACKAGE_URL "http://babelouest.github.io/orcania/") 379 | endif () 380 | 381 | 382 | include(CPack) 383 | 384 | add_custom_target(dist_o 385 | COMMAND ${CMAKE_MAKE_PROGRAM} package_source) 386 | 387 | message(STATUS "Force inline implementation of strstr: ${WITH_STRSTR}") 388 | message(STATUS "Build shared library: ${BUILD_SHARED}") 389 | message(STATUS "Build static library: ${BUILD_STATIC}") 390 | message(STATUS "Build testing tree: ${BUILD_ORCANIA_TESTING}") 391 | message(STATUS "Install the header files: ${INSTALL_HEADER}") 392 | message(STATUS "Build TAR.GZ package: ${BUILD_TGZ}") 393 | message(STATUS "Build DEB package: ${BUILD_DEB}") 394 | message(STATUS "Build RPM package: ${BUILD_RPM}") 395 | message(STATUS "Build documentation: ${BUILD_ORCANIA_DOCUMENTATION}") 396 | message(STATUS "Build base64url application: ${BUILD_BASE64URL}") 397 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | (This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.) 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | {description} 474 | Copyright (C) {year} {fullname} 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | {signature of Ty Coon}, 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Orcania Framework 3 | # 4 | # Makefile used to build all programs 5 | # 6 | # Copyright 2017-2022 Nicolas Mora 7 | # 8 | # This program is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU Lesser General Public License 10 | # as published by the Free Software Foundation; 11 | # version 2.1 of the License. 12 | # 13 | # This library is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU GENERAL PUBLIC LICENSE for more details. 17 | # 18 | # You should have received a copy of the GNU General Public 19 | # License along with this library. If not, see . 20 | # 21 | 22 | LIBORCANIA_LOCATION=./src 23 | TESTS_LOCATION=./test 24 | BASE64URL_LOCATION=./tools/base64url/ 25 | 26 | all: target 27 | 28 | target: 29 | cd $(LIBORCANIA_LOCATION) && $(MAKE) $* 30 | cd $(BASE64URL_LOCATION) && $(MAKE) $* 31 | 32 | debug: 33 | cd $(LIBORCANIA_LOCATION) && $(MAKE) debug $* 34 | cd $(BASE64URL_LOCATION) && $(MAKE) debug $* 35 | 36 | clean: 37 | cd $(LIBORCANIA_LOCATION) && $(MAKE) clean 38 | cd $(TESTS_LOCATION) && $(MAKE) clean 39 | cd $(BASE64URL_LOCATION) && $(MAKE) clean 40 | rm -rf doc/html/ 41 | 42 | check: 43 | cd $(LIBORCANIA_LOCATION) && $(MAKE) debug $* 44 | cd $(TESTS_LOCATION) && $(MAKE) test $* 45 | cd $(BASE64URL_LOCATION) && $(MAKE) test $* 46 | 47 | install: 48 | cd $(LIBORCANIA_LOCATION) && $(MAKE) install $* 49 | cd $(BASE64URL_LOCATION) && $(MAKE) install $* 50 | 51 | uninstall: 52 | cd $(LIBORCANIA_LOCATION) && $(MAKE) uninstall $* 53 | cd $(BASE64URL_LOCATION) && $(MAKE) uninstall $* 54 | 55 | doxygen: 56 | doxygen doc/doxygen.cfg 57 | 58 | release: target 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Orcania 2 | 3 | Potluck with different functions for different purposes that can be shared among C programs. 4 | 5 | ![.github/workflows/ccpp.yml](https://github.com/babelouest/orcania/workflows/.github/workflows/ccpp.yml/badge.svg) 6 | 7 | ## Documentation 8 | 9 | Library documentation is available in the [online documentation](https://babelouest.github.io/orcania/). 10 | 11 | ## Installation 12 | 13 | ### Distribution packages 14 | 15 | [![Packaging status](https://repology.org/badge/vertical-allrepos/orcania.svg)](https://repology.org/metapackage/orcania) 16 | 17 | Orcania is available in multiple distributions as official package. Check out your distribution documentation to install the package automatically. 18 | 19 | ### Pre-compiled packages 20 | 21 | You can install Orcania with a pre-compiled package available in the [release pages](https://github.com/babelouest/orcania/releases/latest/). 22 | 23 | ### Build from source 24 | 25 | Download Orcania source code from GitHub: 26 | 27 | ```shell 28 | $ git clone https://github.com/babelouest/orcania.git 29 | $ cd orcania 30 | ``` 31 | 32 | #### CMake - Multi architecture 33 | 34 | [CMake](https://cmake.org/download/) minimum 3.5 is required. 35 | 36 | Run the CMake script in a sub-directory, example: 37 | 38 | ```shell 39 | $ git clone https://github.com/babelouest/orcania.git 40 | $ cd orcania/ 41 | $ mkdir build 42 | $ cd build 43 | $ cmake .. 44 | $ make && sudo make install 45 | ``` 46 | 47 | The available options for CMake are: 48 | - `-DBUILD_STATIC=[on|off]` (default `off`): Build the static archive in addition to the shared library 49 | - `-DWITH_STRSTR=[on|off]` (default `off`): Force using inline implementation of strstr 50 | - `-DBUILD_ORCANIA_TESTING=[on|off]` (default `off`): Build unit tests 51 | - `-DINSTALL_HEADER=[on|off]` (default `on`): Install header file `orcania.h` 52 | - `-DBUILD_RPM=[on|off]` (default `off`): Build RPM package when running `make package` 53 | - `-DBUILD_ORCANIA_DOCUMENTATION=[on|off]` (default `off`): Build the documentation, doxygen is required 54 | - `-DCMAKE_BUILD_TYPE=[Debug|Release]` (default `Release`): Compile with debugging symbols or not 55 | 56 | #### Good ol' Makefile - Linux only 57 | 58 | Go to `src/` directory, compile and install: 59 | 60 | ```shell 61 | $ cd src 62 | $ make && sudo make install 63 | ``` 64 | 65 | This will install Orcania's files under `/usr/local/` DESTDIR. 66 | 67 | If you want to force using inline implementation of `strstr`, you can append the build option `STRSTRFLAG=1`. This is useful if your system doesn't have an implementation of the function `strstr` but isn't listed as one in Orcania. Like FreeRTOS. 68 | 69 | ``` 70 | $ cd src 71 | $ make STRSTRFLAG=1 72 | ``` 73 | 74 | To build and install as a static archive, use the make commands `make static*`: 75 | 76 | ```shell 77 | $ cd src 78 | $ make static && sudo make static-install # or make DESTDIR=/tmp static-install if you want to install in `/tmp/lib` 79 | ``` 80 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /cmake-modules/CMakeUninstall.cmake.in: -------------------------------------------------------------------------------- 1 | if (NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") 2 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") 3 | endif (NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") 4 | 5 | file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) 6 | string(REGEX REPLACE "\n" ";" files "${files}") 7 | foreach (file ${files}) 8 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}") 9 | if (IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 10 | exec_program( 11 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 12 | OUTPUT_VARIABLE rm_out 13 | RETURN_VALUE rm_retval 14 | ) 15 | if (NOT "${rm_retval}" STREQUAL 0) 16 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") 17 | endif (NOT "${rm_retval}" STREQUAL 0) 18 | else (IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 19 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.") 20 | endif (IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 21 | endforeach (file) 22 | -------------------------------------------------------------------------------- /cmake-modules/CTestCustom.cmake.in: -------------------------------------------------------------------------------- 1 | string(REPLACE ";" " " TESTS "@TESTS@") 2 | set(CTEST_CUSTOM_PRE_TEST "@CMAKE_MAKE_PROGRAM@ ${TESTS}") -------------------------------------------------------------------------------- /cmake-modules/FindCheck.cmake: -------------------------------------------------------------------------------- 1 | #.rst: 2 | # FindCheck 3 | # ----------- 4 | # 5 | # Find Check 6 | # 7 | # Find Check headers and libraries. 8 | # 9 | # :: 10 | # 11 | # CHECK_FOUND - True if Check found. 12 | # CHECK_INCLUDE_DIRS - Where to find check.h. 13 | # CHECK_LIBRARIES - List of libraries when using Check. 14 | # CHECK_VERSION_STRING - The version of Check found. 15 | 16 | #============================================================================= 17 | # Copyright 2018 Silvio Clecio 18 | # 19 | # This program is free software; you can redistribute it and/or 20 | # modify it under the terms of the GNU Lesser General Public License 21 | # as published by the Free Software Foundation; 22 | # version 2.1 of the License. 23 | # 24 | # This library is distributed in the hope that it will be useful, 25 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | # GNU GENERAL PUBLIC LICENSE for more details. 28 | # 29 | # You should have received a copy of the GNU General Public 30 | # License along with this library. If not, see . 31 | #============================================================================= 32 | 33 | # Sat Jan 20 23:33:47 -03 2018 34 | 35 | find_package(PkgConfig QUIET) 36 | pkg_check_modules(PC_CHECK QUIET check) 37 | 38 | find_path(CHECK_INCLUDE_DIR 39 | NAMES check.h 40 | HINTS ${PC_CHECK_INCLUDEDIR} ${PC_CHECK_INCLUDE_DIRS}) 41 | 42 | find_library(CHECK_LIBRARY 43 | NAMES check libcheck 44 | HINTS ${PC_CHECK_LIBDIR} ${PC_CHECK_LIBRARY_DIRS}) 45 | 46 | if (PC_CHECK_VERSION) 47 | set(CHECK_VERSION_STRING ${PC_CHECK_VERSION}) 48 | elseif (CHECK_INCLUDE_DIR AND EXISTS "${CHECK_INCLUDE_DIR}/check.h") 49 | set(check_version_list MAJOR MINOR MICRO) 50 | foreach (v ${check_version_list}) 51 | set(regex_check_version "^#define CHECK_${v}_VERSION +\\(?([0-9]+)\\)?$") 52 | file(STRINGS "${CHECK_INCLUDE_DIR}/check.h" check_version_${v} REGEX "${regex_check_version}") 53 | string(REGEX REPLACE "${regex_check_version}" "\\1" check_version_${v} "${check_version_${v}}") 54 | unset(regex_check_version) 55 | endforeach () 56 | set(CHECK_VERSION_STRING "${check_version_MAJOR}.${check_version_MINOR}.${check_version_MICRO}") 57 | foreach (v check_version_list) 58 | unset(check_version_${v}) 59 | endforeach () 60 | unset(check_version_list) 61 | endif () 62 | 63 | include(FindPackageHandleStandardArgs) 64 | find_package_handle_standard_args(Check 65 | REQUIRED_VARS CHECK_LIBRARY CHECK_INCLUDE_DIR 66 | VERSION_VAR CHECK_VERSION_STRING) 67 | 68 | if (CHECK_FOUND) 69 | set(CHECK_LIBRARIES ${CHECK_LIBRARY}) 70 | set(CHECK_INCLUDE_DIRS ${CHECK_INCLUDE_DIR}) 71 | if (NOT TARGET Check::Check) 72 | add_library(Check::Check IMPORTED UNKNOWN) 73 | set_target_properties(Check::Check PROPERTIES 74 | IMPORTED_LOCATION "${CHECK_LIBRARY}" 75 | INTERFACE_INCLUDE_DIRECTORIES "${CHECK_INCLUDE_DIR}") 76 | endif () 77 | endif () 78 | 79 | mark_as_advanced(CHECK_INCLUDE_DIR CHECK_LIBRARY) -------------------------------------------------------------------------------- /cmake-modules/FindSubunit.cmake: -------------------------------------------------------------------------------- 1 | #.rst: 2 | # FindSubunit 3 | # ----------- 4 | # 5 | # Find Subunit 6 | # 7 | # Find Subunit headers and libraries. 8 | # 9 | # :: 10 | # 11 | # SUBUNIT_FOUND - True if Subunit found. 12 | # SUBUNIT_INCLUDE_DIRS - Where to find subunit/child.h. 13 | # SUBUNIT_LIBRARIES - List of libraries when using Subunit. 14 | # SUBUNIT_VERSION_STRING - The version of Subunit found. 15 | 16 | #============================================================================= 17 | # Copyright 2018 Silvio Clecio 18 | # 19 | # This program is free software; you can redistribute it and/or 20 | # modify it under the terms of the GNU Lesser General Public License 21 | # as published by the Free Software Foundation; 22 | # version 2.1 of the License. 23 | # 24 | # This library is distributed in the hope that it will be useful, 25 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | # GNU GENERAL PUBLIC LICENSE for more details. 28 | # 29 | # You should have received a copy of the GNU General Public 30 | # License along with this library. If not, see . 31 | #============================================================================= 32 | 33 | # Fri Jan 19 22:27:51 -03 2018 34 | 35 | find_package(PkgConfig QUIET) 36 | pkg_check_modules(PC_SUBUNIT QUIET libsubunit) 37 | 38 | set(SUBUNIT_VERSION_STRING "${PC_SUBUNIT_VERSION}") 39 | 40 | find_path(SUBUNIT_INCLUDE_DIR 41 | NAMES child.h 42 | HINTS ${PC_SUBUNIT_INCLUDEDIR} ${PC_SUBUNIT_INCLUDE_DIRS} 43 | PATH_SUFFIXES subunit) 44 | 45 | find_library(SUBUNIT_LIBRARY 46 | NAMES subunit libsubunit 47 | HINTS ${PC_SUBUNIT_LIBDIR} ${PC_SUBUNIT_LIBRARY_DIRS}) 48 | 49 | include(FindPackageHandleStandardArgs) 50 | find_package_handle_standard_args(Subunit 51 | REQUIRED_VARS SUBUNIT_LIBRARY SUBUNIT_INCLUDE_DIR 52 | VERSION_VAR SUBUNIT_VERSION_STRING) 53 | 54 | if (SUBUNIT_FOUND) 55 | set(SUBUNIT_LIBRARIES ${SUBUNIT_LIBRARY}) 56 | set(SUBUNIT_INCLUDE_DIRS ${SUBUNIT_INCLUDE_DIR}) 57 | if (NOT TARGET Subunit::Subunit) 58 | add_library(Subunit::Subunit IMPORTED UNKNOWN) 59 | set_target_properties(Subunit::Subunit PROPERTIES 60 | IMPORTED_LOCATION "${SUBUNIT_LIBRARY}" 61 | INTERFACE_INCLUDE_DIRECTORIES "${SUBUNIT_INCLUDE_DIR}") 62 | endif () 63 | endif () 64 | 65 | mark_as_advanced(SUBUNIT_INCLUDE_DIR SUBUNIT_LIBRARY) -------------------------------------------------------------------------------- /cmake-modules/OrcaniaConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/OrcaniaTargets.cmake") 4 | 5 | if(TARGET Orcania::Orcania-static) 6 | set(ORCANIA_INCLUDE_DIRS $) 7 | set(ORCANIA_LIBRARIES Orcania::Orcania-static) 8 | endif() 9 | 10 | if(TARGET Orcania::Orcania) 11 | set(ORCANIA_INCLUDE_DIRS $) 12 | set(ORCANIA_LIBRARIES Orcania::Orcania) 13 | endif() 14 | 15 | set(ORCANIA_VERSION_STRING "@PROJECT_VERSION@") 16 | set(Orcania_FOUND TRUE) 17 | -------------------------------------------------------------------------------- /doc/doxygen.cfg: -------------------------------------------------------------------------------- 1 | # Doxyfile 1.9.1 2 | PROJECT_NAME = Orcania 3 | PROJECT_BRIEF = "Potluck with different functions for different purposes that can be shared among C programs" 4 | INPUT = API.md \ 5 | ./src/ \ 6 | ./include/ \ 7 | tools/base64url/README.md 8 | USE_MDFILE_AS_MAINPAGE = API.md 9 | 10 | #--------------------------------------------------------------------------- 11 | # Project related configuration options 12 | #--------------------------------------------------------------------------- 13 | DOXYFILE_ENCODING = UTF-8 14 | OUTPUT_DIRECTORY = doc 15 | CREATE_SUBDIRS = NO 16 | ALLOW_UNICODE_NAMES = NO 17 | OUTPUT_LANGUAGE = English 18 | BRIEF_MEMBER_DESC = YES 19 | REPEAT_BRIEF = YES 20 | ABBREVIATE_BRIEF = "The $name class" \ 21 | "The $name widget" \ 22 | "The $name file" \ 23 | is \ 24 | provides \ 25 | specifies \ 26 | contains \ 27 | represents \ 28 | a \ 29 | an \ 30 | the 31 | TAB_SIZE = 4 32 | OPTIMIZE_OUTPUT_FOR_C = YES 33 | OPTIMIZE_OUTPUT_JAVA = NO 34 | OPTIMIZE_FOR_FORTRAN = NO 35 | OPTIMIZE_OUTPUT_VHDL = NO 36 | OPTIMIZE_OUTPUT_SLICE = NO 37 | #--------------------------------------------------------------------------- 38 | # Build related configuration options 39 | #--------------------------------------------------------------------------- 40 | EXTRACT_ALL = YES 41 | EXTRACT_PRIVATE = NO 42 | #--------------------------------------------------------------------------- 43 | # Configuration options related to the input files 44 | #--------------------------------------------------------------------------- 45 | INPUT_ENCODING = UTF-8 46 | FILE_PATTERNS = *.c \ 47 | *.h \ 48 | *.md 49 | RECURSIVE = YES 50 | #--------------------------------------------------------------------------- 51 | # Configuration options related to the HTML output 52 | #--------------------------------------------------------------------------- 53 | GENERATE_HTML = YES 54 | HTML_OUTPUT = html 55 | HTML_FILE_EXTENSION = .html 56 | HTML_COLORSTYLE_HUE = 220 57 | HTML_COLORSTYLE_SAT = 100 58 | HTML_COLORSTYLE_GAMMA = 80 59 | HTML_DYNAMIC_MENUS = YES 60 | HTML_DYNAMIC_SECTIONS = NO 61 | GENERATE_LATEX = NO 62 | GENERATE_RTF = NO 63 | GENERATE_MAN = NO 64 | GENERATE_XML = NO 65 | GENERATE_DOCBOOK = NO 66 | GENERATE_AUTOGEN_DEF = NO 67 | GENERATE_PERLMOD = NO 68 | ENABLE_PREPROCESSING = YES 69 | MACRO_EXPANSION = NO 70 | EXPAND_ONLY_PREDEF = NO 71 | SEARCH_INCLUDES = YES 72 | HAVE_DOT = NO 73 | -------------------------------------------------------------------------------- /include/orcania-cfg.h.in: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Orcania library 4 | * 5 | * Different functions for different purposes but that can be shared between 6 | * other projects 7 | * 8 | * orcania-cfg.h.in: configuration file 9 | * 10 | * Copyright 2018-2022 Nicolas Mora 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU Lesser General Public License 14 | * as published by the Free Software Foundation; 15 | * version 2.1 of the License. 16 | * 17 | * This library is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU GENERAL PUBLIC LICENSE for more details. 21 | * 22 | * You should have received a copy of the GNU General Public 23 | * License along with this library. If not, see . 24 | * 25 | */ 26 | 27 | #ifndef _ORCANIA_CFG_H_ 28 | #define _ORCANIA_CFG_H_ 29 | 30 | #define ORCANIA_VERSION ${PROJECT_VERSION} 31 | #define ORCANIA_VERSION_STR "${PROJECT_VERSION}" 32 | 33 | #define ORCANIA_VERSION_MAJOR ${PROJECT_VERSION_MAJOR} 34 | #define ORCANIA_VERSION_MINOR ${PROJECT_VERSION_MINOR} 35 | #define ORCANIA_VERSION_PATCH ${PROJECT_VERSION_PATCH} 36 | 37 | #define ORCANIA_VERSION_NUMBER ((ORCANIA_VERSION_MAJOR << 16) | (ORCANIA_VERSION_MINOR << 8) | (ORCANIA_VERSION_PATCH << 0)) 38 | 39 | #cmakedefine O_STRSTR 40 | 41 | #endif /* _ORCANIA_CFG_H_ */ 42 | -------------------------------------------------------------------------------- /include/orcania.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @file orcania.h 4 | * @brief Orcania library 5 | * 6 | * Different functions for different purposes but that can be shared between 7 | * other projects 8 | * 9 | * orcania.h: public header file 10 | * 11 | * Copyright 2015-2022 Nicolas Mora 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Lesser General Public License 15 | * as published by the Free Software Foundation; 16 | * version 2.1 of the License. 17 | * 18 | * This library is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU GENERAL PUBLIC LICENSE for more details. 22 | * 23 | * You should have received a copy of the GNU General Public 24 | * License along with this library. If not, see . 25 | * 26 | */ 27 | 28 | #ifndef __ORCANIA_H__ 29 | #define __ORCANIA_H__ 30 | 31 | #ifdef __cplusplus 32 | extern "C" 33 | { 34 | #endif 35 | 36 | #include "orcania-cfg.h" 37 | 38 | #include 39 | #include 40 | 41 | struct _o_datum { 42 | size_t size; 43 | unsigned char * data; 44 | }; 45 | 46 | /** 47 | * @defgroup str string functions 48 | * These functions are used for string manipulation 49 | * Types of functions available: 50 | * - crash safe version of library 51 | * - build heap allocated strings using printf-like format 52 | * @{ 53 | */ 54 | 55 | /** 56 | * char * str_replace(const char * source, char * old, char * new) 57 | * replace all occurences of old by new in the string source 58 | * return a char * with the new value 59 | * @param source: the source string 60 | * @param str_old string to be replaced in source 61 | * @param str_new new string to replace 62 | * @return a heap-allocated string with the replacements applied 63 | * return NULL on error 64 | * returned value must be free'd after use 65 | */ 66 | char * str_replace(const char * source, const char * str_old, const char * str_new); 67 | 68 | /** 69 | * o_strdup 70 | * a modified strdup function that don't crash when source is NULL, instead return NULL 71 | * @param source the source string to duplicate 72 | * @return a heap-allocated string 73 | * Returned value must be free'd after use 74 | */ 75 | char * o_strdup(const char * source); 76 | 77 | /** 78 | * o_strndup 79 | * a modified strndup function that don't crash when source is NULL, instead return NULL 80 | * @param source the source string to duplicate 81 | * @param len the maximum length of the string source to duplicate 82 | * @return a heap-allocated string 83 | * Returned value must be free'd after use 84 | */ 85 | char * o_strndup(const char * source, size_t len); 86 | 87 | /** 88 | * o_strcmp 89 | * a modified strcmp function that don't crash when p1 is NULL or p2 us NULL 90 | * @param p1 the first string to compare 91 | * @param p2 the second string to compare 92 | * @return 0 if p1 is equal to p2, negative number if p1 is inferior to p2, positive number otherwise 93 | */ 94 | int o_strcmp(const char * p1, const char * p2); 95 | 96 | /** 97 | * o_strncmp 98 | * a modified strncmp function that don't crash when p1 is NULL or p2 us NULL 99 | * @param p1 the first string to compare 100 | * @param p2 the second string to compare 101 | * @param n the maximum number of char to compare 102 | * @return 0 if p1 is equal to p2, negative number if p1 is inferior to p2, positive number otherwise 103 | */ 104 | int o_strncmp(const char * p1, const char * p2, size_t n); 105 | 106 | /** 107 | * o_strcpy 108 | * a modified strcpy function that don't crash when p1 is NULL or p2 us NULL 109 | * @param p1 the string to copy p2 110 | * @param p2 the source string to be copied 111 | * @return p1 112 | */ 113 | char * o_strcpy(char * p1, const char * p2); 114 | 115 | /** 116 | * o_strncpy 117 | * @param p1 the string to copy p2 118 | * @param p2 the source string to be copied 119 | * @param n the maximum characters to copy from p2 to p1 120 | * @return p1 121 | * a modified strncpy function that don't crash when p1 is NULL or p2 us NULL 122 | */ 123 | char * o_strncpy(char * p1, const char * p2, size_t n); 124 | 125 | /** 126 | * o_strcasecmp 127 | * a modified strcasecmp function that don't crash when p1 is NULL or p2 us NULL 128 | * @param p1 the first string to compare 129 | * @param p2 the second string to compare 130 | * @return 0 if p1 is equal to p2, negative number if p1 is inferior to p2, positive number otherwise 131 | */ 132 | int o_strcasecmp(const char * p1, const char * p2); 133 | 134 | /** 135 | * o_strncasecmp 136 | * a modified strncasecmp function that don't crash when p1 is NULL or p2 us NULL 137 | * @param p1 the first string to compare 138 | * @param p2 the second string to compare 139 | * @param n the maximum number of char to compare 140 | * @return 0 if p1 is equal to p2, negative number if p1 is inferior to p2, positive number otherwise 141 | */ 142 | int o_strncasecmp(const char * p1, const char * p2, size_t n); 143 | 144 | /** 145 | * o_strstr 146 | * a modified strstr function that don't crash when haystack is NULL or needle us NULL 147 | * @param haystack the string to be looked for 148 | * @param needle the string to search in haystack 149 | * @return the pointer to the first occurence of needle in haystack or NULL if not found 150 | */ 151 | char * o_strstr(const char * haystack, const char * needle); 152 | 153 | /** 154 | * o_strnstr 155 | * a modified strnstr function that don't crash when haystack is NULL or needle us NULL 156 | * @param haystack the string to be looked for 157 | * @param needle the string to search in haystack 158 | * @param len the maximum length to look for in haystack 159 | * @return the pointer to the first occurence of needle in haystack or NULL if not found 160 | */ 161 | char * o_strnstr(const char * haystack, const char * needle, size_t len); 162 | 163 | /** 164 | * o_strcasestr 165 | * a modified strcasestr function that don't crash when haystack is NULL or needle us NULL 166 | * @param haystack the string to be looked for 167 | * @param needle the string to search in haystack 168 | * @return the pointer to the first occurence of needle in haystack or NULL if not found 169 | */ 170 | char * o_strcasestr(const char * haystack, const char * needle); 171 | 172 | /** 173 | * o_strchr 174 | * a modified strchr function that don't crash when haystack is NULL 175 | * @param haystack the string to be looked for 176 | * @param c the character to look for in haystack 177 | * @return the pointer to the first occurence of c in haystack or NULL if not found 178 | */ 179 | char * o_strchr(const char * haystack, int c); 180 | 181 | /** 182 | * o_strnchr 183 | * a modified strnchr function that don't crash when haystack is NULL 184 | * @param haystack the string to be looked for 185 | * @param len the maxmimum length of characters to look for in haystack 186 | * @param c the character to look for in haystack 187 | * @return the pointer to the first occurence of c in haystack or NULL if not found 188 | */ 189 | const char * o_strnchr(const char * haystack, size_t len, char c); 190 | 191 | /** 192 | * o_strrchr 193 | * a modified strrchr function that don't crash when haystack is NULL 194 | * @param haystack the string to be looked for 195 | * @param c the character to look for in haystack 196 | * @return the pointer to the last occurence of c in haystack or NULL if not found 197 | */ 198 | char * o_strrchr(const char * haystack, int c); 199 | 200 | /** 201 | * o_strrnchr 202 | * a modified strrnchr function that don't crash when haystack is NULL 203 | * @param haystack the string to be looked for 204 | * @param len the maxmimum length of characters to look for in haystack 205 | * @param c the character to look for in haystack 206 | * @return the pointer to the last occurence of c in haystack or NULL if not found 207 | */ 208 | const char * o_strrnchr(const char * haystack, size_t len, char c); 209 | 210 | /** 211 | * o_strnullempty 212 | * return true if s is NULL or empty string, false otherwise 213 | */ 214 | int o_strnullempty(const char * s); 215 | 216 | /** 217 | * o_strlen 218 | * a modified version of strlen that don't crash when s is NULL 219 | * @param s the string to calculate length 220 | * @return the length of s, 0 if s is NULL 221 | */ 222 | size_t o_strlen(const char * s); 223 | 224 | /** 225 | * Remove string of beginning and ending whitespaces 226 | * the string str will be modified 227 | * @param str the string to trim 228 | * @return the trimmed str 229 | */ 230 | const char * trimwhitespace(char * str); 231 | 232 | /** 233 | * Remove string of beginning and ending given character 234 | * the string str will be modified 235 | * @param str the string to trim 236 | * @param to_remove the character to trim 237 | * @return the trimmed str 238 | */ 239 | char * trimcharacter(char * str, char to_remove); 240 | 241 | /** 242 | * char * msprintf(const char * message, ...) 243 | * Implementation of sprintf that return a malloc'd char * with the string construction 244 | * because life is too short to use 3 lines instead of 1 245 | * but don't forget to free the returned value after use! 246 | * Disclaimer: When I made this function, I didn't know 247 | * asprintf existed. If I did I surely wouldn't make msprintf 248 | * although, msprintf has the advantage to work with o_malloc and o_free 249 | * so it can use specific memory allocation functions 250 | * @param message the message format to concat to source, printf format 251 | * @return a heap-allocated char * containing the result string 252 | */ 253 | char * msprintf(const char * message, ...); 254 | 255 | /** 256 | * char * mstrcatf((char * source, const char * message, ...) 257 | * A combination of strcat and msprintf that will concat source and message formatted 258 | * and return the combination as a new allocated char * 259 | * and will o_free source 260 | * but don't forget to free the returned value after use! 261 | * @param source the source string to concat message, source will be free'd during the process 262 | * @param message the message format to concat to source, printf format 263 | * @return a heap-allocated char * containing the result string 264 | */ 265 | char * mstrcatf(char * source, const char * message, ...); 266 | 267 | /** 268 | * @} 269 | */ 270 | 271 | /** 272 | * @defgroup split split string and string array functions 273 | * @{ 274 | */ 275 | 276 | /** 277 | * Split a string into an array of strings using separator string 278 | * return the number of elements to be returned, 0 on error 279 | * @param string the string to split 280 | * @param separator the string separator, will not be included in the result 281 | * @param return_array an reference to a char ** that will be heap-allocated by the function 282 | * The last element in return_array will be NULL 283 | * @return the number of string elements in result_array 284 | * if return_array is not NULL, set the returned array in it 285 | * return_array is an array of char * ending with a NULL value 286 | * return_array must be free'd after use 287 | * you can use free_string_array to free return_array 288 | */ 289 | size_t split_string(const char * string, const char * separator, char *** return_array); 290 | 291 | /** 292 | * Clean an array of strings 293 | * @param array an array of char * to free using o_free for each element 294 | * the last element of array must be a NULL 295 | */ 296 | void free_string_array(char ** array); 297 | 298 | /** 299 | * Count the number of elements in an array of strings 300 | * @param array an array of char * with NULL in the last element 301 | * @return the number of string elements in array 302 | */ 303 | size_t string_array_size(char ** array); 304 | 305 | /** 306 | * Check if an array of string has a specified value, case sensitive 307 | * @param array an array of char * with NULL in the last element 308 | * @param needle the value to look for in array 309 | * @return 1 if needle exists in array, 0 otherwise 310 | */ 311 | int string_array_has_value(const char ** array, const char * needle); 312 | 313 | /** 314 | * Check if an array of string has a specified value, case insensitive 315 | * @param array an array of char * with NULL in the last element 316 | * @param needle the value to look for in array 317 | * @return 1 if needle exists in array, 0 otherwise 318 | */ 319 | int string_array_has_value_case(const char ** array, const char * needle); 320 | 321 | /** 322 | * Check if an array of string has a specified value, case sensitive, limit to len characters 323 | * @param array an array of char * with NULL in the last element 324 | * @param needle the value to look for in array 325 | * @param len the length of needle 326 | * @return 1 if needle exists in array, 0 otherwise 327 | */ 328 | int string_array_has_value_n(const char ** array, const char * needle, size_t len); 329 | 330 | /** 331 | * Check if an array of string has a specified value, case insensitive, limit to len characters 332 | * @param array an array of char * with NULL in the last element 333 | * @param needle the value to look for in array 334 | * @param len the length of needle 335 | * @return 1 if needle exists in array, 0 otherwise 336 | */ 337 | int string_array_has_value_ncase(const char ** array, const char * needle, size_t len); 338 | 339 | /** 340 | * Check if an array of string has a specified trimmed value 341 | * @param array an array of char * with NULL in the last element 342 | * @param needle the value to look for in array 343 | * @return 1 if needle exists in array, 0 otherwise 344 | */ 345 | int string_array_has_trimmed_value(const char ** array, const char * needle); 346 | 347 | /** 348 | * Join a string array into a single string 349 | * @param array an array of char * with NULL in the last element 350 | * @param separator a string to put between the elements 351 | * @return a heap allocated string 352 | */ 353 | char * string_array_join(const char ** array, const char * separator); 354 | 355 | /** 356 | * @} 357 | */ 358 | 359 | /** 360 | * @defgroup plist _pointer_list structure 361 | * @{ 362 | */ 363 | struct _pointer_list { 364 | size_t size; /* size of the list */ 365 | void ** list; /* list of pointers */ 366 | }; 367 | 368 | /** 369 | * pointer_list_init 370 | * Initialize a pointer list structure 371 | * @param pointer_list a pointer list to initialize 372 | */ 373 | void pointer_list_init(struct _pointer_list * pointer_list); 374 | 375 | /** 376 | * pointer_list_clean 377 | * Clean a pointer list structure 378 | * @param pointer_list a pointer list to clean 379 | */ 380 | void pointer_list_clean(struct _pointer_list * pointer_list); 381 | 382 | /** 383 | * pointer_list_clean_free 384 | * Clean a pointer list structure 385 | * Free all elements using the free_function given in parameters 386 | * @param pointer_list a pointer list to clean 387 | * @param free_function a function to use for freeing values 388 | */ 389 | void pointer_list_clean_free(struct _pointer_list * pointer_list, void (* free_function)(void * elt)); 390 | 391 | /** 392 | * pointer_list_size 393 | * @param pointer_list a pointer list 394 | * @return the size of a pointer list 395 | */ 396 | size_t pointer_list_size(struct _pointer_list * pointer_list); 397 | 398 | /** 399 | * pointer_list_append 400 | * Appends an element at the end of a pointer list 401 | * @param pointer_list a pointer list 402 | * @param element an element to append 403 | * @return 1 on success, 0 on error 404 | */ 405 | int pointer_list_append(struct _pointer_list * pointer_list, void * element); 406 | 407 | /** 408 | * pointer_list_get_at 409 | * @param pointer_list a pointer list 410 | * @param index the index of the element in pointer_list 411 | * @return an element of a pointer list at the specified index or NULL if non valid index 412 | */ 413 | void * pointer_list_get_at(struct _pointer_list * pointer_list, size_t index); 414 | 415 | /** 416 | * pointer_list_remove_at 417 | * Removes an element of a pointer list at the specified index 418 | * @param pointer_list a pointer list 419 | * @param index the index of the element in pointer_list 420 | * @return 1 on success, 0 on error or non valid index 421 | */ 422 | int pointer_list_remove_at(struct _pointer_list * pointer_list, size_t index); 423 | 424 | /** 425 | * pointer_list_remove_at_free 426 | * Removes an element of a pointer list at the specified index 427 | * Free the element using the free_function given in parameters 428 | * @param pointer_list a pointer list 429 | * @param index the index of the element in pointer_list 430 | * @param free_function the function to use to free the element 431 | * @return 1 on success, 0 on error or non valid index 432 | */ 433 | int pointer_list_remove_at_free(struct _pointer_list * pointer_list, size_t index, void (* free_function)(void * elt)); 434 | 435 | /** 436 | * pointer_list_insert_at 437 | * Inserts an element at the specified index of a pointer list 438 | * @param pointer_list a pointer list 439 | * @param element the element to set at index 440 | * @param index the index of the element in pointer_list 441 | * @return 1 on success, 0 on error or non valid inde 442 | */ 443 | int pointer_list_insert_at(struct _pointer_list * pointer_list, void * element, size_t index); 444 | 445 | /** 446 | * pointer_list_remove_pointer 447 | * Removes an element of a pointer list corresponding to the specified element 448 | * @param pointer_list a pointer list 449 | * @param element the element to set at index 450 | * @return 1 on success, 0 on error or non valid inde 451 | */ 452 | int pointer_list_remove_pointer(struct _pointer_list * pointer_list, void * element); 453 | 454 | /** 455 | * pointer_list_remove_pointer_free 456 | * Removes an element of a pointer list corresponding to the specified element 457 | * Free the element using the free_function given in parameters 458 | * @param pointer_list a pointer list 459 | * @param element the element to set at index 460 | * @param free_function the function to use to free the element 461 | * @return 1 on success, 0 on error or non valid inde 462 | */ 463 | int pointer_list_remove_pointer_free(struct _pointer_list * pointer_list, void * element, void (* free_function)(void * elt)); 464 | 465 | /** 466 | * @} 467 | */ 468 | 469 | /** 470 | * @defgroup mem Memory functions 471 | * @{ 472 | */ 473 | 474 | /* C89 allows these to be macros */ 475 | #undef malloc 476 | #undef realloc 477 | #undef free 478 | 479 | /** 480 | * typedefs use to replace glib's memory functions 481 | */ 482 | typedef void *(*o_malloc_t)(size_t); 483 | typedef void *(*o_realloc_t)(void *, size_t); 484 | typedef void (*o_free_t)(void *); 485 | 486 | /** 487 | * Allocate a memory block 488 | * @param size the size of the block to allocate in memory 489 | * @return a pointer to the new allocated block 490 | */ 491 | void * o_malloc(size_t size); 492 | 493 | /** 494 | * Reallocate a memory block 495 | * @param ptr the previous memory block that will be free'd 496 | * @param size the size of the block to allocate in memory 497 | * @return a pointer to the new allocated block with a copy of the data previously in ptr 498 | */ 499 | void * o_realloc(void * ptr, size_t size); 500 | 501 | /** 502 | * Free a block allocated by o_malloc 503 | */ 504 | void o_free(void * ptr); 505 | 506 | /** 507 | * Updates the memory functions by user-specific ones 508 | * @param malloc_fn a pointer to a malloc function, if NULL, will use current function 509 | * @param realloc_fn a pointer to a realloc function, if NULL, will use current function 510 | * @param free_fn a pointer to a free function, if NULL, will use current function 511 | */ 512 | void o_set_alloc_funcs(o_malloc_t malloc_fn, o_realloc_t realloc_fn, o_free_t free_fn); 513 | 514 | /** 515 | * Gets the pointer to current memory functions 516 | * @param malloc_fn reference to a pointer to a malloc function 517 | * @param realloc_fn reference to a pointer to a realloc function 518 | * @param free_fn reference to a pointer to a free function 519 | */ 520 | void o_get_alloc_funcs(o_malloc_t * malloc_fn, o_realloc_t * realloc_fn, o_free_t * free_fn); 521 | 522 | /** 523 | * @} 524 | */ 525 | 526 | /** 527 | * @defgroup base64 Base64 encode and decode functions 528 | * @{ 529 | */ 530 | 531 | /** 532 | * o_base64_encode - Base64 encode 533 | * @param src Data to be encoded 534 | * @param len Length of the data to be encoded 535 | * @param out Pointer to output variable, you might add up to 2 bytes to out length than expected for safety 536 | * @param out_len Pointer to output length variable 537 | * @return 1 on success, 0 on failure 538 | * 539 | * The nul terminator is not included in out_len. 540 | */ 541 | int o_base64_encode(const unsigned char * src, size_t len, unsigned char * out, size_t * out_len); 542 | 543 | /** 544 | * o_base64_decode - Base64 decode 545 | * @param src Data to be decoded 546 | * @param len Length of the data to be decoded 547 | * @param out Pointer to output variable, you might add up to 2 bytes to out length than expected for safety 548 | * @param out_len Pointer to output length variable 549 | * @return 1 on success, 0 on failure 550 | * 551 | * The nul terminator is not included in out_len. 552 | */ 553 | int o_base64_decode(const unsigned char *src, size_t len, unsigned char * out, size_t * out_len); 554 | 555 | /** 556 | * o_base64url_encode - Base64url encode (url format) 557 | * @param src Data to be encoded 558 | * @param len Length of the data to be encoded 559 | * @param out Pointer to output variable, you might add up to 2 bytes to out length than expected for safety 560 | * @param out_len Pointer to output length variable 561 | * @return 1 on success, 0 on failure 562 | * 563 | * The nul terminator is not included in out_len. 564 | */ 565 | int o_base64url_encode(const unsigned char * src, size_t len, unsigned char * out, size_t * out_len); 566 | 567 | /** 568 | * o_base64url_decode - Base64 decode (url format) 569 | * @param src Data to be decoded 570 | * @param len Length of the data to be decoded 571 | * @param out Pointer to output variable, you might add up to 2 bytes to out length than expected for safety 572 | * @param out_len Pointer to output length variable 573 | * @return 1 on success, 0 on failure 574 | * 575 | * The nul terminator is not included in out_len. 576 | */ 577 | int o_base64url_decode(const unsigned char *src, size_t len, unsigned char * out, size_t * out_len); 578 | 579 | /** 580 | * o_base64url_2_base64 - Convert a base64 url format to base64 format - Does not check if src is a valid base64 581 | * @param src Data to be decoded 582 | * @param len Length of the data to be decoded 583 | * @param out Pointer to output variable 584 | * @param out_len Pointer to output length variable 585 | * @return 1 on success, 0 on failure 586 | * 587 | * The nul terminator is not included in out_len. 588 | * out must be at least len+2 589 | */ 590 | int o_base64url_2_base64(const unsigned char *src, size_t len, unsigned char * out, size_t * out_len); 591 | 592 | /** 593 | * o_base64_2_base64url - Convert a base64 url format to base64 format - Does not check if src is a valid base64url 594 | * @param src Data to be decoded 595 | * @param len Length of the data to be decoded 596 | * @param out Pointer to output variable 597 | * @param out_len Pointer to output length variable 598 | * @return 1 on success, 0 on failure 599 | * 600 | * The nul terminator is not included in out_len. 601 | * out must be at least len+2 602 | */ 603 | int o_base64_2_base64url(const unsigned char *src, size_t len, unsigned char * out, size_t * out_len); 604 | 605 | /** 606 | * o_base64_encode_alloc - Base64 encode - allocate data result in a struct _o_datum * 607 | * @param src Data to be encoded 608 | * @param len Length of the data to be encoded 609 | * @param dat Pointer to a struct _o_datum * to store result 610 | * @return 1 on success, 0 on failure 611 | * 612 | * dat->data must be o_free'd after use 613 | * The nul terminator is not included in dat->data. 614 | */ 615 | int o_base64_encode_alloc(const unsigned char * src, size_t len, struct _o_datum * dat); 616 | 617 | /** 618 | * o_base64_decode_alloc - Base64 decode - allocate data result in a struct _o_datum * 619 | * @param src Data to be decoded 620 | * @param len Length of the data to be decoded 621 | * @param dat Pointer to a struct _o_datum * to store result 622 | * @return 1 on success, 0 on failure 623 | * 624 | * dat->data must be o_free'd after use 625 | * The nul terminator is not included in dat->data. 626 | */ 627 | int o_base64_decode_alloc(const unsigned char * src, size_t len, struct _o_datum * dat); 628 | 629 | /** 630 | * o_base64url_encode_alloc - Base64url encode (url format) - allocate data result in a struct _o_datum * 631 | * @param src Data to be encoded 632 | * @param len Length of the data to be encoded 633 | * @param dat Pointer to a struct _o_datum * to store result 634 | * @return 1 on success, 0 on failure 635 | * 636 | * dat->data must be o_free'd after use 637 | * The nul terminator is not included in dat->data. 638 | */ 639 | int o_base64url_encode_alloc(const unsigned char * src, size_t len, struct _o_datum * dat); 640 | 641 | /** 642 | * o_base64url_decode_alloc - Base64 decode (url format) - allocate data result in a struct _o_datum * 643 | * @param src Data to be decoded 644 | * @param len Length of the data to be decoded 645 | * @param dat Pointer to a struct _o_datum * to store result 646 | * @return 1 on success, 0 on failure 647 | * 648 | * dat->data must be o_free'd after use 649 | * The nul terminator is not included in dat->data. 650 | */ 651 | int o_base64url_decode_alloc(const unsigned char * src, size_t len, struct _o_datum * dat); 652 | 653 | /** 654 | * o_base64url_2_base64_alloc - Convert a base64 url format to base64 format - allocate data result in a struct _o_datum * 655 | * @param src Data to be decoded 656 | * @param len Length of the data to be decoded 657 | * @param dat Pointer to a struct _o_datum * to store result 658 | * @return 1 on success, 0 on failure 659 | * 660 | * dat->data must be o_free'd after use 661 | * The nul terminator is not included in dat->data. 662 | */ 663 | int o_base64url_2_base64_alloc(const unsigned char * src, size_t len, struct _o_datum * dat); 664 | 665 | /** 666 | * o_base64_2_base64url_alloc - Convert a base64 format to base64 url format - allocate data result in a struct _o_datum * 667 | * @param src Data to be decoded 668 | * @param len Length of the data to be decoded 669 | * @param dat Pointer to a struct _o_datum * to store result 670 | * @return 1 on success, 0 on failure 671 | * 672 | * dat->data must be o_free'd after use 673 | * The nul terminator is not included in dat->data. 674 | */ 675 | int o_base64_2_base64url_alloc(const unsigned char * src, size_t len, struct _o_datum * dat); 676 | 677 | /** 678 | * @} 679 | */ 680 | 681 | #ifdef __cplusplus 682 | } 683 | #endif 684 | 685 | #endif // __ORCANIA_H__ 686 | -------------------------------------------------------------------------------- /liborcania.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=@CMAKE_INSTALL_PREFIX@ 3 | libdir=@PKGCONFIG_TARGET_LIBDIR@ 4 | includedir=@PKGCONFIG_TARGET_INCLUDES@ 5 | 6 | Name: @PROJECT_NAME@ 7 | Description: @PROJECT_DESCRIPTION@ 8 | URL: @PROJECT_BUGREPORT_PATH@ 9 | Version: @LIBRARY_VERSION@ 10 | Requires: @PKGCONF_REQ@ 11 | Requires.private: @PKGCONF_REQ_PRIVATE@ 12 | Libs: -L${libdir} -lorcania @LIB_STATIC@ 13 | Cflags: -I${includedir} 14 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Orcania Library 3 | # 4 | # Makefile used to build the software 5 | # 6 | # Copyright 2014-2022 Nicolas Mora 7 | # 8 | # This program is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU Lesser General Public License 10 | # as published by the Free Software Foundation; 11 | # version 2.1 of the License. 12 | # 13 | # This library is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU GENERAL PUBLIC LICENSE for more details. 17 | # 18 | # You should have received a copy of the GNU General Public 19 | # License along with this library. If not, see . 20 | # 21 | PROJECT_NAME=orcania 22 | PROJECT_DESCRIPTION=Potluck with different functions for different purposes that can be shared among programs 23 | PROJECT_BUGREPORT_PATH=https://github.com/babelouest/orcania/issues 24 | PKGCONF_REQ= 25 | PKGCONF_REQ_PRIVATE= 26 | DESTDIR=/usr/local 27 | ORCANIA_INCLUDE=../include 28 | CONFIG_TEMPLATE=$(ORCANIA_INCLUDE)/orcania-cfg.h.in 29 | CONFIG_FILE=$(ORCANIA_INCLUDE)/orcania-cfg.h 30 | PKGCONFIG_FILE=../liborcania.pc 31 | PKGCONFIG_TEMPLATE=../liborcania.pc.in 32 | CC=gcc 33 | CFLAGS+=-c -fPIC -Wall -Werror -Wextra -Wpedantic -Wconversion -I$(ORCANIA_INCLUDE) -D_REENTRANT $(ADDITIONALFLAGS) $(CPPFLAGS) 34 | OUTPUT=liborcania.so 35 | VERSION_MAJOR=2 36 | VERSION_MINOR=3 37 | VERSION_PATCH=4 38 | OBJECTS=orcania.o memory.o base64.o 39 | LIBSDEP=-lm 40 | LIBS=-lc 41 | 42 | SONAME = -soname 43 | ifeq ($(shell uname -s),Darwin) 44 | SONAME = -install_name 45 | endif 46 | 47 | ifdef STRSTRFLAG 48 | STRSTR=1 49 | else 50 | STRSTR=0 51 | endif 52 | 53 | all: release 54 | 55 | $(CONFIG_FILE): 56 | @cp $(CONFIG_TEMPLATE) $(CONFIG_FILE) 57 | @echo Config file $(CONFIG_FILE) generated 58 | @sed -i -e 's/$${PROJECT_VERSION}/$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)/g' $(CONFIG_FILE) 59 | @sed -i -e 's/$${PROJECT_VERSION_MAJOR}/$(VERSION_MAJOR)/g' $(CONFIG_FILE) 60 | @sed -i -e 's/$${PROJECT_VERSION_MINOR}/$(VERSION_MINOR)/g' $(CONFIG_FILE) 61 | @sed -i -e 's/$${PROJECT_VERSION_PATCH}/$(VERSION_PATCH)/g' $(CONFIG_FILE) 62 | @sed -i -e 's/$${PROJECT_VERSION_NUMBER}/$(shell printf '%02d' $(VERSION_MAJOR))$(shell printf '%02d' $(VERSION_MINOR))$(shell printf '%02d' $(VERSION_PATCH))/g' $(CONFIG_FILE) 63 | @if [ "$(STRSTR)" = "1" ]; then \ 64 | sed -i -e 's/\#cmakedefine O_STRSTR/\#define O_STRSTR/g' $(CONFIG_FILE); \ 65 | echo "FORCE IMPLEMENT STRSTR ENABLED"; \ 66 | else \ 67 | sed -i -e 's/\#cmakedefine O_STRSTR/\/* #undef O_STRSTR *\//g' $(CONFIG_FILE); \ 68 | echo "FORCE IMPLEMENT STRSTR DISABLED"; \ 69 | fi 70 | 71 | $(PKGCONFIG_FILE): 72 | @cp $(PKGCONFIG_TEMPLATE) $(PKGCONFIG_FILE) 73 | @echo Pkgconfig file $(PKGCONFIG_FILE) generated 74 | @sed -i -e 's#@CMAKE_INSTALL_PREFIX@#$(DESTDIR)#g' $(PKGCONFIG_FILE) 75 | @sed -i -e 's#@PKGCONFIG_TARGET_LIBDIR@#$${prefix}/lib#g' $(PKGCONFIG_FILE) 76 | @sed -i -e 's#@PKGCONFIG_TARGET_INCLUDES@#$${prefix}/include#g' $(PKGCONFIG_FILE) 77 | @sed -i -e 's/@PROJECT_NAME@/$(PROJECT_NAME)/g' $(PKGCONFIG_FILE) 78 | @sed -i -e 's/@PROJECT_DESCRIPTION@/$(PROJECT_DESCRIPTION)/g' $(PKGCONFIG_FILE) 79 | @sed -i -e 's|@PROJECT_BUGREPORT_PATH@|$(PROJECT_BUGREPORT_PATH)|g' $(PKGCONFIG_FILE) 80 | @sed -i -e 's/@LIBRARY_VERSION@/$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)/g' $(PKGCONFIG_FILE) 81 | @sed -i -e 's/@PKGCONF_REQ@/$(PKGCONF_REQ)/g' $(PKGCONFIG_FILE) 82 | @sed -i -e 's/@PKGCONF_REQ_PRIVATE@/$(PKGCONF_REQ_PRIVATE)/g' $(PKGCONFIG_FILE) 83 | @sed -i -e 's/@LIB_STATIC@/$(LIB_STATIC)/g' $(PKGCONFIG_FILE) 84 | 85 | liborcania.so: $(OBJECTS) $(PKGCONFIG_FILE) 86 | $(CC) -shared -fPIC -Wl,$(SONAME),$(OUTPUT) -o $(OUTPUT).$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH) $(OBJECTS) $(LIBS) $(LIBSDEP) $(LDFLAGS) 87 | ln -sf $(OUTPUT).$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH) $(OUTPUT) 88 | 89 | liborcania.a: $(OBJECTS) $(PKGCONFIG_FILE) 90 | ar rcs liborcania.a $(OBJECTS) 91 | 92 | %.o: %.c $(CONFIG_FILE) ../include/orcania.h 93 | $(CC) $(CFLAGS) $< 94 | 95 | clean: 96 | rm -f *.o *.so *.a $(OUTPUT) $(OUTPUT).* $(CONFIG_FILE) $(PKGCONFIG_FILE) 97 | 98 | install: all 99 | install $(OUTPUT).$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH) $(DESTDIR)/lib 100 | mkdir -p $(DESTDIR)/lib/pkgconfig/ $(DESTDIR)/include 101 | install -m644 $(PKGCONFIG_FILE) $(DESTDIR)/lib/pkgconfig/ 102 | install -m644 ../include/orcania.h $(DESTDIR)/include 103 | install -m644 $(CONFIG_FILE) $(DESTDIR)/include 104 | -ldconfig $(DESTDIR)/lib 105 | 106 | static-install: static 107 | install liborcania.a $(DESTDIR)/lib 108 | mkdir -p $(DESTDIR)/lib/pkgconfig/ $(DESTDIR)/include 109 | install -m644 $(PKGCONFIG_FILE) $(DESTDIR)/lib/pkgconfig 110 | install -m644 ../include/orcania.h $(DESTDIR)/include 111 | install -m644 $(CONFIG_FILE) $(DESTDIR)/include 112 | 113 | uninstall: 114 | rm -f $(DESTDIR)/lib/$(OUTPUT) $(DESTDIR)/lib/liborcania.a 115 | rm -f $(DESTDIR)/lib/$(OUTPUT).* 116 | rm -f $(DESTDIR)/include/orcania.h 117 | rm -f $(DESTDIR)/include/$(CONFIG_FILE) 118 | rm -f $(DESTDIR)/lib/pkgconfig/$(PKGCONFIG_FILE) 119 | 120 | debug: ADDITIONALFLAGS=-DDEBUG -g -O0 121 | 122 | debug: liborcania.so 123 | 124 | release: ADDITIONALFLAGS=-O3 125 | 126 | release: liborcania.so 127 | 128 | static-debug: ADDITIONALFLAGS=-DDEBUG -g -O0 129 | 130 | static-debug: liborcania.a 131 | 132 | static-debug: LIB_STATIC=$(LIBSDEP) 133 | 134 | static: ADDITIONALFLAGS=-O3 135 | 136 | static: liborcania.a 137 | 138 | static: LIB_STATIC=$(LIBSDEP) 139 | -------------------------------------------------------------------------------- /src/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Base64 encoding/decoding (RFC1341) 3 | * Copyright (c) 2005-2011, Jouni Malinen 4 | * Copyright (c) 2017-2022, Nicolas Mora 5 | * 6 | * This software may be distributed under the terms of the BSD license. 7 | */ 8 | 9 | #include 10 | #include "orcania.h" 11 | 12 | static const unsigned char base64_table[65] = 13 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 14 | 15 | static const unsigned char base64_url_table[65] = 16 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; 17 | 18 | static size_t table_size = 65; 19 | 20 | static int _o_base64_encode_agnostic(const unsigned char * src, size_t len, unsigned char * out, size_t * out_len, const unsigned char * table, int right_pad) { 21 | unsigned char * pos; 22 | const unsigned char * end, * in; 23 | size_t olen; 24 | int line_len; 25 | 26 | olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ 27 | olen += olen / 72; /* line feeds */ 28 | olen++; /* nul termination */ 29 | if (olen < len || src == NULL || out_len == NULL || !len) { 30 | return 0; 31 | } 32 | 33 | end = src + len; 34 | in = src; 35 | pos = out; 36 | line_len = 0; 37 | *out_len = 0; 38 | while (end - in >= 3) { 39 | if (pos != NULL) { 40 | *pos++ = (unsigned char)(table[in[0] >> 2]); 41 | *pos++ = (unsigned char)(table[((in[0] & 0x03) << 4) | (in[1] >> 4)]); 42 | *pos++ = (unsigned char)(table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]); 43 | *pos++ = (unsigned char)(table[in[2] & 0x3f]); 44 | } 45 | (*out_len) += 4; 46 | in += 3; 47 | line_len += 4; 48 | if (line_len >= 72) { 49 | line_len = 0; 50 | } 51 | } 52 | 53 | if (end - in) { 54 | if (pos != NULL) { 55 | *pos++ = (unsigned char)(table[in[0] >> 2]); 56 | } 57 | (*out_len)++; 58 | if (end - in == 1) { 59 | if (pos != NULL) { 60 | *pos++ = (unsigned char)(table[(in[0] & 0x03) << 4]); 61 | if (right_pad) { 62 | *pos++ = '='; 63 | } 64 | } 65 | if (right_pad) { 66 | (*out_len) += 2; 67 | } else { 68 | (*out_len)++; 69 | } 70 | } else { 71 | if (pos != NULL) { 72 | *pos++ = (unsigned char)(table[((in[0] & 0x03) << 4) | (in[1] >> 4)]); 73 | *pos++ = (unsigned char)(table[(in[1] & 0x0f) << 2]); 74 | } 75 | (*out_len) += 2; 76 | } 77 | if (pos != NULL && right_pad) { 78 | *pos++ = '='; 79 | } 80 | if (right_pad) { 81 | (*out_len)++; 82 | } 83 | } 84 | 85 | return 1; 86 | } 87 | 88 | static int o_base64_decode_agnostic(const unsigned char *src, size_t len, unsigned char * out, size_t * out_len, const unsigned char * table, int right_pad) { 89 | unsigned char dtable[256], *pos = out, block[4] = {0}, tmp; 90 | size_t i, count, unpad = 0; 91 | int pad = 0; 92 | 93 | if (src == NULL || !len || out_len == NULL) { 94 | return 0; 95 | } 96 | 97 | if (len % 4 == 2) { 98 | unpad = 2; 99 | } else if (len % 4 == 3) { 100 | unpad = 1; 101 | } 102 | 103 | memset(dtable, 0x80, 256); 104 | for (i = 0; i < table_size - 1; i++) { 105 | dtable[table[i]] = (unsigned char) i; 106 | } 107 | dtable['='] = 0; 108 | 109 | count = 0; 110 | for (i = 0; i < len; i++) { 111 | if (dtable[src[i]] != 0x80) { 112 | count++; 113 | } 114 | } 115 | 116 | if (right_pad && (count == 0 || count % 4)) { 117 | return 0; 118 | } else if (!right_pad && (len % 4) == 1) { 119 | return 0; 120 | } 121 | 122 | count = 0; 123 | *out_len = 0; 124 | for (i = 0; i < len; i++) { 125 | if (!o_strnchr((const char *)table, table_size, (char)src[i]) && ((src[i] != '=')||(!right_pad && src[i] == '='))) { 126 | // character invalid 127 | return 0; 128 | } 129 | tmp = dtable[src[i]]; 130 | if (tmp == 0x80) { 131 | continue; 132 | } 133 | 134 | if (src[i] == '=') { 135 | pad++; 136 | } 137 | block[count] = tmp; 138 | count++; 139 | if (i == len-1) { 140 | count = 4; 141 | (*out_len) -= unpad; 142 | } 143 | if (count == 4) { 144 | if (pos != NULL) { 145 | *pos++ = (unsigned char)((block[0] << 2)) | (unsigned char)((block[1] >> 4)); 146 | *pos++ = (unsigned char)((block[1] << 4)) | (unsigned char)((block[2] >> 2)); 147 | *pos++ = (unsigned char)((block[2] << 6)) | (unsigned char)(block[3]); 148 | } 149 | (*out_len)+=3; 150 | count = 0; 151 | if (pad) { 152 | if (pad == 1) { 153 | if (pos != NULL) { 154 | pos--; 155 | } 156 | (*out_len)--; 157 | } else if (pad == 2) { 158 | if (pos != NULL) { 159 | pos -= 2; 160 | } 161 | (*out_len) -= 2; 162 | } else { 163 | /* Invalid padding */ 164 | return 0; 165 | } 166 | break; 167 | } 168 | memset(block, 0, 4); 169 | } 170 | } 171 | 172 | return *out_len?1:0; 173 | } 174 | 175 | int o_base64_encode(const unsigned char * src, size_t len, unsigned char * out, size_t * out_len) { 176 | return _o_base64_encode_agnostic(src, len, out, out_len, base64_table, 1); 177 | } 178 | 179 | int o_base64_decode(const unsigned char *src, size_t len, unsigned char * out, size_t * out_len) { 180 | return o_base64_decode_agnostic(src, len, out, out_len, base64_table, 1); 181 | } 182 | 183 | int o_base64url_encode(const unsigned char * src, size_t len, unsigned char * out, size_t * out_len) { 184 | return _o_base64_encode_agnostic(src, len, out, out_len, base64_url_table, 0); 185 | } 186 | 187 | int o_base64url_decode(const unsigned char *src, size_t len, unsigned char * out, size_t * out_len) { 188 | return o_base64_decode_agnostic(src, len, out, out_len, base64_url_table, 0); 189 | } 190 | 191 | int o_base64url_2_base64(const unsigned char *src, size_t len, unsigned char * out, size_t * out_len) { 192 | int res = 0; 193 | size_t index; 194 | 195 | if (src != NULL && len && out != NULL && out_len != NULL) { 196 | memcpy(out, src, len); 197 | *out_len = len; 198 | for (index = 0; index < len; index++) { 199 | if (out[index] == '-') { 200 | out[index] = '+'; 201 | } else if (out[index] == '_') { 202 | out[index] = '/'; 203 | } 204 | } 205 | if (len % 4 == 2) { 206 | out[len] = '='; 207 | out[len+1] = '='; 208 | (*out_len) += 2; 209 | } else if (len % 4 == 3) { 210 | out[len] = '='; 211 | (*out_len)++; 212 | } 213 | res = 1; 214 | } 215 | return res; 216 | } 217 | 218 | int o_base64_2_base64url(const unsigned char *src, size_t len, unsigned char * out, size_t * out_len) { 219 | int res = 0; 220 | size_t index; 221 | 222 | if (src) { 223 | memcpy(out, src, len); 224 | *out_len = len; 225 | for (index = 0; index < len; index++) { 226 | if (out[index] == '+') { 227 | out[index] = '-'; 228 | } else if (out[index] == '/') { 229 | out[index] = '_'; 230 | } 231 | } 232 | while (out[(*out_len)-1] == '=') { 233 | (*out_len)--; 234 | } 235 | res = 1; 236 | } 237 | 238 | return res; 239 | } 240 | 241 | int o_base64_encode_alloc(const unsigned char * src, size_t len, struct _o_datum * dat) { 242 | int ret = 0; 243 | 244 | if (dat != NULL) { 245 | dat->size = 0; 246 | if ((ret = o_base64_encode(src, len, NULL, &dat->size)) && dat->size) { 247 | if ((dat->data = o_malloc(dat->size+2)) != NULL) { 248 | memset(dat->data, 0, dat->size+2); 249 | ret = o_base64_encode(src, len, dat->data, &dat->size); 250 | } else { 251 | ret = 0; 252 | } 253 | } 254 | } 255 | return ret; 256 | } 257 | 258 | int o_base64_decode_alloc(const unsigned char * src, size_t len, struct _o_datum * dat) { 259 | int ret = 0; 260 | 261 | if (dat != NULL) { 262 | dat->size = 0; 263 | if ((ret = o_base64_decode(src, len, NULL, &dat->size)) && dat->size) { 264 | if ((dat->data = o_malloc(dat->size+2)) != NULL) { 265 | memset(dat->data, 0, dat->size+2); 266 | ret = o_base64_decode(src, len, dat->data, &dat->size); 267 | } else { 268 | ret = 0; 269 | } 270 | } 271 | } 272 | return ret; 273 | } 274 | 275 | int o_base64url_encode_alloc(const unsigned char * src, size_t len, struct _o_datum * dat) { 276 | int ret = 0; 277 | 278 | if (dat != NULL) { 279 | dat->size = 0; 280 | if ((ret = o_base64url_encode(src, len, NULL, &dat->size)) && dat->size) { 281 | if ((dat->data = o_malloc(dat->size+2)) != NULL) { 282 | memset(dat->data, 0, dat->size+2); 283 | ret = o_base64url_encode(src, len, dat->data, &dat->size); 284 | } else { 285 | ret = 0; 286 | } 287 | } 288 | } 289 | return ret; 290 | } 291 | 292 | int o_base64url_decode_alloc(const unsigned char * src, size_t len, struct _o_datum * dat) { 293 | int ret = 0; 294 | 295 | if (dat != NULL) { 296 | dat->size = 0; 297 | if ((ret = o_base64url_decode(src, len, NULL, &dat->size)) && dat->size) { 298 | if ((dat->data = o_malloc(dat->size+2)) != NULL) { 299 | memset(dat->data, 0, dat->size+2); 300 | ret = o_base64url_decode(src, len, dat->data, &dat->size); 301 | } else { 302 | ret = 0; 303 | } 304 | } 305 | } 306 | return ret; 307 | } 308 | 309 | int o_base64url_2_base64_alloc(const unsigned char * src, size_t len, struct _o_datum * dat) { 310 | int ret = 0; 311 | unsigned char * out = NULL; 312 | 313 | if (dat != NULL) { 314 | dat->size = 0; 315 | if ((out = o_malloc(len+4)) != NULL) { 316 | if ((ret = o_base64url_2_base64(src, len, out, &dat->size)) && dat->size) { 317 | if ((dat->data = o_malloc(dat->size)) != NULL) { 318 | memcpy(dat->data, out, dat->size); 319 | } 320 | } 321 | } 322 | } 323 | o_free(out); 324 | return ret; 325 | } 326 | 327 | int o_base64_2_base64url_alloc(const unsigned char * src, size_t len, struct _o_datum * dat) { 328 | int ret = 0; 329 | unsigned char * out = NULL; 330 | 331 | if (dat != NULL) { 332 | dat->size = 0; 333 | if ((out = o_malloc(len)) != NULL) { 334 | if ((ret = o_base64_2_base64url(src, len, out, &dat->size)) && dat->size) { 335 | if ((dat->data = o_malloc(dat->size)) != NULL) { 336 | memcpy(dat->data, out, dat->size); 337 | } 338 | } 339 | } 340 | } 341 | o_free(out); 342 | return ret; 343 | } 344 | -------------------------------------------------------------------------------- /src/memory.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-2022 Nicolas Mora 3 | * Copyright (c) 2009-2014 Petri Lehtinen 4 | * Copyright (c) 2011-2012 Basile Starynkevitch 5 | * 6 | * Inspired by jansson memory.c 7 | * Jansson is free software; you can redistribute it and/or modify it 8 | * under the terms of the MIT license. See LICENSE for details. 9 | */ 10 | 11 | #include 12 | #include "orcania.h" 13 | 14 | /* memory function pointers */ 15 | static o_malloc_t do_malloc = malloc; 16 | static o_realloc_t do_realloc = realloc; 17 | static o_free_t do_free = free; 18 | 19 | void * o_malloc(size_t size) { 20 | if (!size) { 21 | return NULL; 22 | } else { 23 | return (*do_malloc)(size); 24 | } 25 | } 26 | 27 | void * o_realloc(void * ptr, size_t size) { 28 | if (!size) { 29 | return NULL; 30 | } else { 31 | return (*do_realloc)(ptr, size); 32 | } 33 | } 34 | 35 | void o_free(void * ptr) { 36 | if (ptr == NULL) { 37 | return; 38 | } else { 39 | (*do_free)(ptr); 40 | } 41 | } 42 | 43 | void o_set_alloc_funcs(o_malloc_t malloc_fn, o_realloc_t realloc_fn, o_free_t free_fn) { 44 | do_malloc = malloc_fn; 45 | do_realloc = realloc_fn; 46 | do_free = free_fn; 47 | } 48 | 49 | void o_get_alloc_funcs(o_malloc_t * malloc_fn, o_realloc_t * realloc_fn, o_free_t * free_fn) { 50 | if (malloc_fn) { 51 | *malloc_fn = do_malloc; 52 | } 53 | if (realloc_fn) { 54 | *realloc_fn = do_realloc; 55 | } 56 | if (free_fn) { 57 | *free_fn = do_free; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/orcania.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Orcania library 4 | * 5 | * Different functions for different purposes but that can be shared between 6 | * other projects 7 | * 8 | * orcania.c: main functions definitions 9 | * 10 | * Copyright 2015-2022 Nicolas Mora 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU Lesser General Public License 14 | * as published by the Free Software Foundation; 15 | * version 2.1 of the License. 16 | * 17 | * This library is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU GENERAL PUBLIC LICENSE for more details. 21 | * 22 | * You should have received a copy of the GNU General Public 23 | * License along with this library. If not, see . 24 | * 25 | */ 26 | 27 | #ifndef _GNU_SOURCE 28 | #define _GNU_SOURCE 29 | #endif 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "orcania.h" 36 | 37 | #ifdef _MSC_VER 38 | #define strncasecmp _strnicmp 39 | #define strcasecmp _stricmp 40 | #endif 41 | 42 | #ifdef _MSC_VER 43 | #include 44 | typedef SSIZE_T ssize_t; 45 | #endif 46 | 47 | /** 48 | * 49 | * Orcania library 50 | * 51 | * Different functions for different purposes but that can be shared between 52 | * other projects 53 | * 54 | */ 55 | 56 | char * str_replace(const char * source, const char * str_old, const char * str_new) { 57 | char * to_return, * ptr, * pre, * next; 58 | size_t len, pre_len; 59 | 60 | if (source == NULL || str_old == NULL || str_new == NULL) { 61 | return NULL; 62 | } 63 | 64 | ptr = strstr(source, str_old); 65 | if (ptr == NULL) { 66 | return o_strdup(source); 67 | } else { 68 | if ((size_t)(ptr-source) > SIZE_MAX) { 69 | return NULL; 70 | } 71 | pre_len = (size_t)(ptr-source); 72 | pre = o_malloc((pre_len+1)); 73 | if (pre == NULL) { 74 | return NULL; 75 | } 76 | memcpy(pre, source, pre_len); 77 | pre[pre_len] = '\0'; 78 | 79 | next = str_replace(source+o_strlen(pre)+o_strlen(str_old), str_old, str_new); 80 | if (next == NULL) { 81 | o_free(pre); 82 | return NULL; 83 | } 84 | if (((size_t)(ptr-source))+o_strlen(str_new)+o_strlen(next) > SIZE_MAX) { 85 | o_free(pre); 86 | return NULL; 87 | } 88 | len = (((size_t)(ptr-source))+o_strlen(str_new)+o_strlen(next)); 89 | to_return = o_malloc((len+1)); 90 | if (to_return == NULL) { 91 | o_free(pre); 92 | o_free(next); 93 | return NULL; 94 | } 95 | if (snprintf(to_return, (len+1), "%s%s%s", pre, str_new, next) < 0) { 96 | o_free(pre); 97 | o_free(next); 98 | o_free(to_return); 99 | return NULL; 100 | } 101 | o_free(pre); 102 | o_free(next); 103 | return to_return; 104 | } 105 | } 106 | 107 | char * msprintf(const char * message, ...) { 108 | va_list argp, argp_cpy; 109 | size_t out_len = 0; 110 | char * out = NULL; 111 | int v_out = 0; 112 | if (message != NULL) { 113 | va_start(argp, message); 114 | va_copy(argp_cpy, argp); // We make a copy because in some architectures, vsnprintf can modify argp 115 | if ((v_out = vsnprintf(NULL, 0, message, argp)) >= 0) { 116 | out_len = (size_t)v_out; 117 | out = o_malloc(out_len+1); 118 | if (out == NULL) { 119 | va_end(argp); 120 | va_end(argp_cpy); 121 | return NULL; 122 | } 123 | vsnprintf(out, (out_len+1), message, argp_cpy); 124 | } 125 | va_end(argp); 126 | va_end(argp_cpy); 127 | } 128 | return out; 129 | } 130 | 131 | char * mstrcatf(char * source, const char * message, ...) { 132 | va_list argp, argp_cpy; 133 | char * out = NULL, * message_formatted = NULL; 134 | size_t message_formatted_len = 0, out_len = 0; 135 | int v_out = 0; 136 | if (message != NULL) { 137 | va_start(argp, message); 138 | va_copy(argp_cpy, argp); // We make a copy because in some architectures, vsnprintf can modify argp 139 | if (source != NULL) { 140 | if ((v_out = vsnprintf(NULL, 0, message, argp)) >= 0) { 141 | message_formatted_len = (size_t)v_out; 142 | message_formatted = o_malloc(message_formatted_len+1); 143 | if (message_formatted != NULL) { 144 | memset(message_formatted, 0, message_formatted_len+1); 145 | vsnprintf(message_formatted, (message_formatted_len+1), message, argp_cpy); 146 | out = msprintf("%s%s", source, message_formatted); 147 | o_free(message_formatted); 148 | o_free(source); 149 | } 150 | } 151 | } else { 152 | if ((v_out = vsnprintf(NULL, 0, message, argp)) >= 0) { 153 | out_len = (size_t)v_out; 154 | out = o_malloc(out_len+1); 155 | if (out != NULL) { 156 | vsnprintf(out, (out_len+1), message, argp_cpy); 157 | } 158 | } 159 | } 160 | va_end(argp); 161 | va_end(argp_cpy); 162 | } 163 | return out; 164 | } 165 | 166 | char * o_strdup(const char * source) { 167 | return (source==NULL?NULL:o_strndup(source, strlen(source))); 168 | } 169 | 170 | char * o_strndup(const char * source, size_t len) { 171 | char *new_str; 172 | 173 | if (source == NULL) { 174 | return NULL; 175 | } else { 176 | new_str = o_malloc(len + 1); 177 | if(!new_str) { 178 | return NULL; 179 | } 180 | 181 | memcpy(new_str, source, len); 182 | new_str[len] = '\0'; 183 | return new_str; 184 | } 185 | } 186 | 187 | int o_strcmp(const char * p1, const char * p2) { 188 | if (p1 == NULL && p2 == NULL) { 189 | return 0; 190 | } else if (p1 != NULL && p2 == NULL) { 191 | return -1; 192 | } else if (p1 == NULL) { 193 | return 1; 194 | } else { 195 | return strcmp(p1, p2); 196 | } 197 | } 198 | 199 | int o_strncmp(const char * p1, const char * p2, size_t n) { 200 | if ((p1 == NULL && p2 == NULL) || n <= 0) { 201 | return 0; 202 | } else if (p1 != NULL && p2 == NULL) { 203 | return -1; 204 | } else if (p1 == NULL) { 205 | return 1; 206 | } else { 207 | return strncmp(p1, p2, n); 208 | } 209 | } 210 | 211 | char * o_strcpy(char * p1, const char * p2) { 212 | if (p1 == NULL || p2 == NULL) { 213 | return NULL; 214 | } else { 215 | return strcpy(p1, p2); 216 | } 217 | } 218 | 219 | char * o_strncpy(char * p1, const char * p2, size_t n) { 220 | if (p1 == NULL || p2 == NULL) { 221 | return NULL; 222 | } else { 223 | return strncpy(p1, p2, n); 224 | } 225 | } 226 | 227 | int o_strcasecmp(const char * p1, const char * p2) { 228 | if (p1 == NULL && p2 == NULL) { 229 | return 0; 230 | } else if (p1 != NULL && p2 == NULL) { 231 | return -1; 232 | } else if (p1 == NULL && p2 != NULL) { 233 | return 1; 234 | } else { 235 | return strcasecmp(p1, p2); 236 | } 237 | } 238 | 239 | int o_strncasecmp(const char * p1, const char * p2, size_t n) { 240 | if ((p1 == NULL && p2 == NULL) || n <= 0) { 241 | return 0; 242 | } else if (p1 != NULL && p2 == NULL) { 243 | return -1; 244 | } else if (p1 == NULL && p2 != NULL) { 245 | return 1; 246 | } else { 247 | return strncasecmp(p1, p2, n); 248 | } 249 | } 250 | 251 | char * o_strstr(const char * haystack, const char * needle) { 252 | if (haystack == NULL || needle == NULL) { 253 | return NULL; 254 | } else { 255 | return strstr(haystack, needle); 256 | } 257 | } 258 | 259 | char * o_strchr(const char * haystack, int c) { 260 | if (haystack == NULL) { 261 | return NULL; 262 | } else { 263 | return strchr(haystack, c); 264 | } 265 | } 266 | 267 | const char * o_strnchr(const char * haystack, size_t len, char c) { 268 | size_t offset; 269 | if (haystack != NULL && len > 0) { 270 | for (offset = 0; offset < len && offset < o_strlen(haystack); offset++) { 271 | if (haystack[offset] == c) { 272 | return (haystack+offset); 273 | } 274 | } 275 | } 276 | return NULL; 277 | } 278 | 279 | /** 280 | * o_strrchr 281 | * a modified strrchr function that don't crash when haystack is NULL 282 | */ 283 | char * o_strrchr(const char * haystack, int c) { 284 | if (haystack == NULL) { 285 | return NULL; 286 | } else { 287 | return strrchr(haystack, c); 288 | } 289 | } 290 | 291 | const char * o_strrnchr(const char * haystack, size_t len, char c) { 292 | ssize_t offset; 293 | if (haystack != NULL && len > 0) { 294 | for (offset = ((ssize_t)o_strlen(haystack))-1; offset>=0 && (o_strlen(haystack) - 1 - (size_t)offset < len); offset--) { 295 | if (haystack[offset] == c) { 296 | return (haystack+offset); 297 | } 298 | } 299 | } 300 | return NULL; 301 | } 302 | 303 | #if defined(__linux__) || defined(__GLIBC__) || defined(_WIN32) || defined(O_STRSTR) 304 | static char *strnstr(const char *haystack, const char *needle, size_t len) { 305 | int i; 306 | size_t needle_len; 307 | 308 | /* segfault here if needle is not NULL terminated */ 309 | if (0 == (needle_len = o_strlen(needle))) 310 | return (char *)haystack; 311 | 312 | for (i=0; i<=(int)(len - needle_len); i++) { 313 | if ((haystack[0] == needle[0]) && (0 == strncmp(haystack, needle, needle_len))) 314 | return (char *)haystack; 315 | 316 | haystack++; 317 | } 318 | return NULL; 319 | } 320 | #endif 321 | 322 | #ifdef _WIN32 323 | static char *strcasestr(const char *haystack, const char *needle) { 324 | size_t n; 325 | if (haystack == NULL || needle == NULL) { 326 | return NULL; 327 | } 328 | n = o_strlen(needle); 329 | while (*haystack) { 330 | if (!strnicmp(haystack++, needle, n)) { 331 | return (char *)(haystack-1); 332 | } 333 | } 334 | return NULL; 335 | } 336 | #endif 337 | 338 | char * o_strnstr(const char * haystack, const char * needle, size_t len) { 339 | if (haystack == NULL || needle == NULL) { 340 | return NULL; 341 | } else { 342 | return strnstr(haystack, needle, len); 343 | } 344 | } 345 | 346 | char * o_strcasestr(const char * haystack, const char * needle) { 347 | if (haystack == NULL || needle == NULL) { 348 | return NULL; 349 | } else { 350 | return strcasestr(haystack, needle); 351 | } 352 | } 353 | 354 | size_t o_strlen(const char * s) { 355 | if (s == NULL) { 356 | return 0; 357 | } else { 358 | return strlen(s); 359 | } 360 | } 361 | 362 | int o_strnullempty(const char * s) { 363 | return (s == NULL || s[0] == '\0'); 364 | } 365 | 366 | size_t split_string(const char * string, const char * separator, char *** return_array) { 367 | size_t result = 0; 368 | char * token; 369 | const char * begin = string; 370 | 371 | if (string != NULL && separator != NULL) { 372 | if (return_array != NULL) { 373 | *return_array = NULL; 374 | } 375 | result = 1; 376 | token = strstr(begin, separator); 377 | while (token != NULL) { 378 | if (return_array != NULL) { 379 | (*return_array) = o_realloc((*return_array), (result + 1)*sizeof(char*)); 380 | if ((*return_array) != NULL) { 381 | (*return_array)[result-1] = o_strndup(begin, (size_t)(token-begin)); 382 | (*return_array)[result] = NULL; 383 | } 384 | } 385 | result++; 386 | begin = token+o_strlen(separator); 387 | token = strstr(begin, separator); 388 | } 389 | if (return_array != NULL) { 390 | (*return_array) = o_realloc((*return_array), (result + 1)*sizeof(char*)); 391 | if ((*return_array) != NULL) { 392 | (*return_array)[result-1] = o_strdup(begin); 393 | (*return_array)[result] = NULL; 394 | } 395 | } 396 | } 397 | return result; 398 | } 399 | 400 | void free_string_array(char ** array) { 401 | int i; 402 | if (array != NULL) { 403 | for (i=0; array[i] != NULL; i++) { 404 | o_free(array[i]); 405 | array[i] = NULL; 406 | } 407 | o_free(array); 408 | } 409 | } 410 | 411 | size_t string_array_size(char ** array) { 412 | size_t ret = 0; 413 | if (array != NULL) { 414 | for (;array[ret] != NULL; ret++); 415 | } 416 | return ret; 417 | } 418 | 419 | char * string_array_join(const char ** array, const char * separator) { 420 | char * to_return = NULL, * tmp; 421 | int i; 422 | 423 | if (array != NULL && separator != NULL) { 424 | for (i=0; array[i] != NULL; i++) { 425 | if (to_return == NULL) { 426 | to_return = o_strdup(array[i]); 427 | } else { 428 | tmp = msprintf("%s%s%s", to_return, separator, array[i]); 429 | o_free(to_return); 430 | to_return = tmp; 431 | } 432 | } 433 | } 434 | return to_return; 435 | } 436 | 437 | const char * trimwhitespace(char * str) { 438 | char * end; 439 | 440 | if (str == NULL) { 441 | return NULL; 442 | } else if(*str == 0) { 443 | return str; 444 | } 445 | 446 | while(isspace((unsigned char)*str)) str++; 447 | 448 | end = str + o_strlen(str) - 1; 449 | while(end > str && isspace((unsigned char)*end)) { 450 | end--; 451 | } 452 | 453 | *(end+1) = 0; 454 | 455 | return str; 456 | } 457 | 458 | char * trimcharacter(char * str, char to_remove) { 459 | char * end; 460 | 461 | if (str == NULL) { 462 | return NULL; 463 | } else if(*str == 0) { 464 | return str; 465 | } 466 | 467 | while(*str == to_remove) str++; 468 | 469 | end = str + o_strlen(str) - 1; 470 | while(end > str && (*end == to_remove)) { 471 | end--; 472 | } 473 | 474 | *(end+1) = 0; 475 | 476 | return str; 477 | } 478 | 479 | int string_array_has_value(const char ** array, const char * needle) { 480 | int i; 481 | if (array != NULL && needle != NULL) { 482 | for (i=0; array[i] != NULL; i++) { 483 | if (o_strcmp(array[i], needle) == 0) { 484 | return 1; 485 | } 486 | } 487 | return 0; 488 | } else { 489 | return 0; 490 | } 491 | } 492 | 493 | int string_array_has_value_case(const char ** array, const char * needle) { 494 | int i; 495 | if (array != NULL && needle != NULL) { 496 | for (i=0; array[i] != NULL; i++) { 497 | if (o_strcasecmp(array[i], needle) == 0) { 498 | return 1; 499 | } 500 | } 501 | return 0; 502 | } else { 503 | return 0; 504 | } 505 | } 506 | 507 | int string_array_has_value_n(const char ** array, const char * needle, size_t len) { 508 | int i; 509 | if (array != NULL && needle != NULL) { 510 | for (i=0; array[i] != NULL; i++) { 511 | if (o_strncmp(array[i], needle, len) == 0) { 512 | return 1; 513 | } 514 | } 515 | return 0; 516 | } else { 517 | return 0; 518 | } 519 | } 520 | 521 | int string_array_has_value_ncase(const char ** array, const char * needle, size_t len) { 522 | int i; 523 | if (array != NULL && needle != NULL) { 524 | for (i=0; array[i] != NULL; i++) { 525 | if (o_strncasecmp(array[i], needle, len) == 0) { 526 | return 1; 527 | } 528 | } 529 | return 0; 530 | } else { 531 | return 0; 532 | } 533 | } 534 | 535 | int string_array_has_trimmed_value(const char ** array, const char * needle) { 536 | int i, to_return = 0; 537 | char * duplicate_needle, * duplicate_value; 538 | const char * trimmed_needle, * trimmed_value; 539 | if (array != NULL && needle != NULL) { 540 | duplicate_needle = o_strdup(needle); 541 | if (duplicate_needle != NULL) { 542 | trimmed_needle = trimwhitespace(duplicate_needle); 543 | for (i=0; array[i] != NULL && !to_return; i++) { 544 | duplicate_value = o_strdup(array[i]); 545 | if (duplicate_value == NULL) { 546 | break; 547 | } else { 548 | trimmed_value = trimwhitespace(duplicate_value); 549 | if (o_strcmp(trimmed_value, trimmed_needle) == 0) { 550 | to_return = 1; 551 | } 552 | } 553 | o_free(duplicate_value); 554 | } 555 | } 556 | o_free(duplicate_needle); 557 | } 558 | return to_return; 559 | } 560 | 561 | void pointer_list_init(struct _pointer_list * pointer_list) { 562 | if (pointer_list != NULL) { 563 | pointer_list->size = 0; 564 | pointer_list->list = NULL; 565 | } 566 | } 567 | 568 | void pointer_list_clean(struct _pointer_list * pointer_list) { 569 | size_t i; 570 | if (pointer_list != NULL) { 571 | for (i=pointer_list_size(pointer_list); i; i--) { 572 | pointer_list_remove_at(pointer_list, (i-1)); 573 | } 574 | } 575 | } 576 | 577 | void pointer_list_clean_free(struct _pointer_list * pointer_list, void (* free_function)(void * elt)) { 578 | size_t i; 579 | if (pointer_list != NULL) { 580 | for (i=pointer_list_size(pointer_list); i; i--) { 581 | free_function(pointer_list_get_at(pointer_list, i-1)); 582 | pointer_list_remove_at(pointer_list, (i-1)); 583 | } 584 | } 585 | } 586 | 587 | size_t pointer_list_size(struct _pointer_list * pointer_list) { 588 | if (pointer_list != NULL) { 589 | return pointer_list->size; 590 | } else { 591 | return 0; 592 | } 593 | } 594 | 595 | int pointer_list_append(struct _pointer_list * pointer_list, void * element) { 596 | if (pointer_list) { 597 | pointer_list->list = o_realloc(pointer_list->list, (pointer_list->size+1)*sizeof(void *)); 598 | if (pointer_list->list != NULL) { 599 | pointer_list->list[pointer_list->size] = element; 600 | pointer_list->size++; 601 | return 1; 602 | } else { 603 | o_free(pointer_list->list); 604 | pointer_list->list = NULL; 605 | return 0; 606 | } 607 | } else { 608 | return 0; 609 | } 610 | } 611 | 612 | void * pointer_list_get_at(struct _pointer_list * pointer_list, size_t index) { 613 | if (pointer_list != NULL && index < pointer_list->size) { 614 | return pointer_list->list[index]; 615 | } else { 616 | return NULL; 617 | } 618 | } 619 | 620 | int pointer_list_remove_at(struct _pointer_list * pointer_list, size_t index) { 621 | size_t i; 622 | if (pointer_list != NULL && index < pointer_list->size) { 623 | for (i=index; isize-1; i++) { 624 | pointer_list->list[i] = pointer_list->list[i+1]; 625 | } 626 | if (pointer_list->size > 1) { 627 | pointer_list->list = o_realloc(pointer_list->list, (pointer_list->size-1)*sizeof(void *)); 628 | } else { 629 | o_free(pointer_list->list); 630 | pointer_list->list = NULL; 631 | } 632 | pointer_list->size--; 633 | return 1; 634 | } else { 635 | return 0; 636 | } 637 | } 638 | 639 | int pointer_list_remove_at_free(struct _pointer_list * pointer_list, size_t index, void (* free_function)(void * elt)) { 640 | if (pointer_list != NULL && index < pointer_list->size) { 641 | free_function(pointer_list_get_at(pointer_list, index)); 642 | return pointer_list_remove_at(pointer_list, index); 643 | } else { 644 | return 0; 645 | } 646 | } 647 | 648 | int pointer_list_insert_at(struct _pointer_list * pointer_list, void * element, size_t index) { 649 | size_t i; 650 | if (pointer_list != NULL && index <= pointer_list->size) { 651 | pointer_list->list = o_realloc(pointer_list->list, (pointer_list->size + 1)*sizeof(void *)); 652 | if (pointer_list->list != NULL) { 653 | for (i=pointer_list->size; i>index; i--) { 654 | pointer_list->list[i] = pointer_list->list[i-1]; 655 | } 656 | pointer_list->list[index] = element; 657 | pointer_list->size++; 658 | return 1; 659 | } else { 660 | return 0; 661 | } 662 | } else { 663 | return 0; 664 | } 665 | } 666 | 667 | int pointer_list_remove_pointer(struct _pointer_list * pointer_list, void * element) { 668 | size_t index; 669 | if (pointer_list != NULL) { 670 | for (index=0; indexsize; index++) { 671 | if (pointer_list->list[index] == element) { 672 | return pointer_list_remove_at(pointer_list, index); 673 | } 674 | } 675 | return 0; 676 | } else { 677 | return 0; 678 | } 679 | } 680 | 681 | int pointer_list_remove_pointer_free(struct _pointer_list * pointer_list, void * element, void (* free_function)(void * elt)) { 682 | size_t index; 683 | if (pointer_list != NULL) { 684 | for (index=0; indexsize; index++) { 685 | if (pointer_list->list[index] == element) { 686 | free_function(element); 687 | return pointer_list_remove_at(pointer_list, index); 688 | } 689 | } 690 | return 0; 691 | } else { 692 | return 0; 693 | } 694 | } 695 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | valgrind*.txt 2 | str_test 3 | split_test 4 | memory_test 5 | pointer_list_test 6 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Public domain, no copyright. Use at your own risk. 3 | # 4 | 5 | CC=gcc 6 | CFLAGS+=-Wall -Werror -Wextra -D_REENTRANT -DDEBUG -g -O0 -I$(INCLUDE_LOCATION) $(CPPFLAGS) 7 | ORCANIA_LOCATION=../src 8 | INCLUDE_LOCATION=../include 9 | ORCANIA_LIBRARY=$(ORCANIA_LOCATION)/liborcania.so 10 | LDFLAGS=-lc -lorcania $(shell pkg-config --libs check) -L$(ORCANIA_LOCATION) 11 | VALGRIND_COMMAND=valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all 12 | TARGET=str_test split_test memory_test pointer_list_test 13 | VERBOSE=0 14 | MEMCHECK=0 15 | 16 | all: test 17 | 18 | clean: 19 | rm -f *.o $(TARGET) *.log valgrind-*.txt 20 | 21 | $(ORCANIA_LIBRARY): $(ORCANIA_LOCATION)/orcania.c $(ORCANIA_LOCATION)/memory.c $(ORCANIA_LOCATION)/base64.c 22 | cd $(ORCANIA_LOCATION) && $(MAKE) debug $* 23 | 24 | %: %.c 25 | $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) 26 | 27 | test: $(ORCANIA_LIBRARY) $(TARGET) test_str_test test_split_test test_memory_test test_pointer_list_test 28 | 29 | check: test 30 | 31 | test_%: % $(ORCANIA_LIBRARY) 32 | @if [ "$(VERBOSE)" = "0" ] && [ "$(MEMCHECK)" = "0" ]; then \ 33 | LD_LIBRARY_PATH=$(ORCANIA_LOCATION):${LD_LIBRARY_PATH} ./run_test.sh ./$^; \ 34 | elif [ "$(MEMCHECK)" = "0" ]; then \ 35 | LD_LIBRARY_PATH=$(ORCANIA_LOCATION):${LD_LIBRARY_PATH} ./$^ ; \ 36 | else \ 37 | CK_FORK=no LD_LIBRARY_PATH=$(ORCANIA_LOCATION):${LD_LIBRARY_PATH} $(VALGRIND_COMMAND) ./$^ 2>valgrind-$@.txt; \ 38 | fi 39 | -------------------------------------------------------------------------------- /test/memory_test.c: -------------------------------------------------------------------------------- 1 | /* Public domain, no copyright. Use at your own risk. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "orcania.h" 11 | 12 | START_TEST(test_o_malloc) 13 | { 14 | void * var; 15 | var = o_malloc(8); 16 | ck_assert_ptr_ne(var, NULL); 17 | o_free(var); 18 | } 19 | END_TEST 20 | 21 | START_TEST(test_o_realloc) 22 | { 23 | void * var; 24 | var = o_malloc(8); 25 | ck_assert_ptr_ne(var, NULL); 26 | var = o_realloc(var, 16); 27 | ck_assert_ptr_ne(var, NULL); 28 | if (var != NULL) { 29 | o_free(var); 30 | } 31 | } 32 | END_TEST 33 | 34 | static Suite *orcania_suite(void) 35 | { 36 | Suite *s; 37 | TCase *tc_core; 38 | 39 | s = suite_create("Orcania tests memory functions"); 40 | tc_core = tcase_create("test_orcania_memory"); 41 | tcase_add_test(tc_core, test_o_malloc); 42 | tcase_add_test(tc_core, test_o_realloc); 43 | tcase_set_timeout(tc_core, 30); 44 | suite_add_tcase(s, tc_core); 45 | 46 | return s; 47 | } 48 | 49 | int main(void) 50 | { 51 | int number_failed; 52 | Suite *s; 53 | SRunner *sr; 54 | 55 | s = orcania_suite(); 56 | sr = srunner_create(s); 57 | 58 | srunner_run_all(sr, CK_VERBOSE); 59 | number_failed = srunner_ntests_failed(sr); 60 | srunner_free(sr); 61 | 62 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 63 | } 64 | -------------------------------------------------------------------------------- /test/pointer_list_test.c: -------------------------------------------------------------------------------- 1 | /* Public domain, no copyright. Use at your own risk. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "orcania.h" 11 | 12 | int counter = 0; 13 | 14 | void free_with_test(void * ptr) { 15 | counter++; 16 | o_free(ptr); 17 | } 18 | 19 | START_TEST(test_pointer_list_init) 20 | { 21 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 22 | 23 | pointer_list_init(pointer_list); 24 | ck_assert_int_eq(pointer_list->size, 0); 25 | ck_assert_ptr_eq(pointer_list->list, NULL); 26 | pointer_list_clean(pointer_list); 27 | o_free(pointer_list); 28 | } 29 | END_TEST 30 | 31 | START_TEST(test_pointer_list_append) 32 | { 33 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 34 | 35 | pointer_list_init(pointer_list); 36 | ck_assert_int_eq(pointer_list->size, 0); 37 | ck_assert_ptr_eq(pointer_list->list, NULL); 38 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x42), 1); 39 | ck_assert_int_eq(pointer_list_append(NULL, (void *)0x42), 0); 40 | ck_assert_int_eq(pointer_list->size, 1); 41 | ck_assert_int_eq(pointer_list_append(NULL, (void *)0x43), 0); 42 | ck_assert_int_eq(pointer_list_append(pointer_list, NULL), 1); 43 | ck_assert_int_eq(pointer_list->size, 2); 44 | pointer_list_clean(pointer_list); 45 | o_free(pointer_list); 46 | } 47 | END_TEST 48 | 49 | START_TEST(test_pointer_list_size) 50 | { 51 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 52 | 53 | pointer_list_init(pointer_list); 54 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x42), 1); 55 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x43), 1); 56 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x44), 1); 57 | ck_assert_int_eq(pointer_list_size(pointer_list), 3); 58 | ck_assert_int_eq(pointer_list_size(pointer_list), pointer_list->size); 59 | pointer_list_clean(pointer_list); 60 | o_free(pointer_list); 61 | } 62 | END_TEST 63 | 64 | START_TEST(test_pointer_list_get_at) 65 | { 66 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 67 | 68 | pointer_list_init(pointer_list); 69 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x42), 1); 70 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x43), 1); 71 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x44), 1); 72 | ck_assert_int_eq(pointer_list->size, 3); 73 | ck_assert_ptr_ne(pointer_list_get_at(pointer_list, 0), NULL); 74 | ck_assert_ptr_eq(pointer_list_get_at(pointer_list, 0), (void *)0x42); 75 | ck_assert_ptr_ne(pointer_list_get_at(pointer_list, 1), NULL); 76 | ck_assert_ptr_eq(pointer_list_get_at(pointer_list, 1), (void *)0x43); 77 | ck_assert_ptr_ne(pointer_list_get_at(pointer_list, 2), NULL); 78 | ck_assert_ptr_eq(pointer_list_get_at(pointer_list, 2), (void *)0x44); 79 | ck_assert_ptr_eq(pointer_list_get_at(pointer_list, 3), NULL); 80 | pointer_list_clean(pointer_list); 81 | o_free(pointer_list); 82 | } 83 | END_TEST 84 | 85 | START_TEST(test_pointer_list_remove_at) 86 | { 87 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 88 | 89 | pointer_list_init(pointer_list); 90 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x42), 1); 91 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x43), 1); 92 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x44), 1); 93 | ck_assert_int_eq(pointer_list->size, 3); 94 | ck_assert_int_eq(pointer_list_remove_at(pointer_list, 0), 1); 95 | ck_assert_int_eq(pointer_list_remove_at(pointer_list, 4), 0); 96 | ck_assert_int_eq(pointer_list->size, 2); 97 | pointer_list_clean(pointer_list); 98 | o_free(pointer_list); 99 | } 100 | END_TEST 101 | 102 | START_TEST(test_pointer_list_remove_at_free) 103 | { 104 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 105 | 106 | pointer_list_init(pointer_list); 107 | ck_assert_int_eq(pointer_list_append(pointer_list, o_strdup("test1")), 1); 108 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x43), 1); 109 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x44), 1); 110 | ck_assert_int_eq(pointer_list->size, 3); 111 | counter = 0; 112 | ck_assert_int_eq(pointer_list_remove_at_free(pointer_list, 0, &free_with_test), 1); 113 | ck_assert_int_eq(counter, 1); 114 | ck_assert_int_eq(pointer_list_remove_at_free(pointer_list, 4, &free_with_test), 0); 115 | ck_assert_int_eq(counter, 1); 116 | ck_assert_int_eq(pointer_list->size, 2); 117 | pointer_list_clean(pointer_list); 118 | o_free(pointer_list); 119 | } 120 | END_TEST 121 | 122 | START_TEST(test_pointer_list_insert_at) 123 | { 124 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 125 | 126 | pointer_list_init(pointer_list); 127 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x42), 1); 128 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x43), 1); 129 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x44), 1); 130 | ck_assert_int_eq(pointer_list->size, 3); 131 | ck_assert_int_eq(pointer_list_insert_at(pointer_list, (void *)0x45, 0), 1); 132 | ck_assert_int_eq(pointer_list->size, 4); 133 | ck_assert_ptr_eq(pointer_list_get_at(pointer_list, 0), (void *)0x45); 134 | ck_assert_ptr_eq(pointer_list_get_at(pointer_list, 1), (void *)0x42); 135 | ck_assert_int_eq(pointer_list_insert_at(pointer_list, (void *)0x46, 3), 1); 136 | ck_assert_int_eq(pointer_list->size, 5); 137 | ck_assert_ptr_eq(pointer_list_get_at(pointer_list, 0), (void *)0x45); 138 | ck_assert_ptr_eq(pointer_list_get_at(pointer_list, 1), (void *)0x42); 139 | ck_assert_ptr_eq(pointer_list_get_at(pointer_list, 3), (void *)0x46); 140 | ck_assert_int_eq(pointer_list_insert_at(pointer_list, (void *)0x47, 10), 0); 141 | pointer_list_clean(pointer_list); 142 | o_free(pointer_list); 143 | } 144 | END_TEST 145 | 146 | START_TEST(test_pointer_list_remove_pointer) 147 | { 148 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 149 | 150 | pointer_list_init(pointer_list); 151 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x42), 1); 152 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x43), 1); 153 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x44), 1); 154 | ck_assert_int_eq(pointer_list->size, 3); 155 | ck_assert_int_eq(pointer_list_remove_pointer(pointer_list, (void *)0x42), 1); 156 | ck_assert_int_eq(pointer_list->size, 2); 157 | ck_assert_int_eq(pointer_list_remove_pointer(pointer_list, (void *)0x42), 0); 158 | ck_assert_int_eq(pointer_list->size, 2); 159 | ck_assert_int_eq(pointer_list_remove_pointer(pointer_list, (void *)0x44), 1); 160 | ck_assert_int_eq(pointer_list->size, 1); 161 | pointer_list_clean(pointer_list); 162 | o_free(pointer_list); 163 | } 164 | END_TEST 165 | 166 | START_TEST(test_pointer_list_remove_pointer_free) 167 | { 168 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 169 | 170 | char * test1 = o_strdup("test1"), * test3 = o_strdup("test3"); 171 | pointer_list_init(pointer_list); 172 | ck_assert_int_eq(pointer_list_append(pointer_list, test1), 1); 173 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x43), 1); 174 | ck_assert_int_eq(pointer_list_append(pointer_list, test3), 1); 175 | ck_assert_int_eq(pointer_list->size, 3); 176 | counter = 0; 177 | ck_assert_int_eq(pointer_list_remove_pointer_free(pointer_list, test1, &free_with_test), 1); 178 | ck_assert_int_eq(counter, 1); 179 | ck_assert_int_eq(pointer_list->size, 2); 180 | ck_assert_int_eq(pointer_list_remove_pointer(pointer_list, (void *)0x42), 0); 181 | ck_assert_int_eq(pointer_list->size, 2); 182 | ck_assert_int_eq(pointer_list_remove_pointer_free(pointer_list, test3, &free_with_test), 1); 183 | ck_assert_int_eq(counter, 2); 184 | ck_assert_int_eq(pointer_list->size, 1); 185 | pointer_list_clean(pointer_list); 186 | o_free(pointer_list); 187 | } 188 | END_TEST 189 | 190 | START_TEST(test_pointer_list_clean) 191 | { 192 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 193 | 194 | pointer_list_init(pointer_list); 195 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x42), 1); 196 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x43), 1); 197 | ck_assert_int_eq(pointer_list_append(pointer_list, (void *)0x44), 1); 198 | ck_assert_int_eq(pointer_list->size, 3); 199 | pointer_list_clean(pointer_list); 200 | ck_assert_int_eq(pointer_list->size, 0); 201 | o_free(pointer_list); 202 | } 203 | END_TEST 204 | 205 | START_TEST(test_pointer_list_clean_free) 206 | { 207 | struct _pointer_list * pointer_list = o_malloc(sizeof(struct _pointer_list)); 208 | 209 | pointer_list_init(pointer_list); 210 | ck_assert_int_eq(pointer_list_append(pointer_list, o_strdup("test1")), 1); 211 | ck_assert_int_eq(pointer_list_append(pointer_list, o_strdup("test2")), 1); 212 | ck_assert_int_eq(pointer_list_append(pointer_list, o_strdup("test3")), 1); 213 | ck_assert_int_eq(pointer_list->size, 3); 214 | counter = 0; 215 | pointer_list_clean_free(pointer_list, &free_with_test); 216 | ck_assert_int_eq(pointer_list->size, 0); 217 | ck_assert_int_eq(counter, 3); 218 | o_free(pointer_list); 219 | } 220 | END_TEST 221 | 222 | static Suite *orcania_suite(void) 223 | { 224 | Suite *s; 225 | TCase *tc_core; 226 | 227 | s = suite_create("Orcania tests pointer list structure functions"); 228 | tc_core = tcase_create("test_pointer_list"); 229 | tcase_add_test(tc_core, test_pointer_list_init); 230 | tcase_add_test(tc_core, test_pointer_list_append); 231 | tcase_add_test(tc_core, test_pointer_list_size); 232 | tcase_add_test(tc_core, test_pointer_list_get_at); 233 | tcase_add_test(tc_core, test_pointer_list_remove_at); 234 | tcase_add_test(tc_core, test_pointer_list_remove_at_free); 235 | tcase_add_test(tc_core, test_pointer_list_insert_at); 236 | tcase_add_test(tc_core, test_pointer_list_remove_pointer); 237 | tcase_add_test(tc_core, test_pointer_list_remove_pointer_free); 238 | tcase_add_test(tc_core, test_pointer_list_clean); 239 | tcase_add_test(tc_core, test_pointer_list_clean_free); 240 | tcase_set_timeout(tc_core, 30); 241 | suite_add_tcase(s, tc_core); 242 | 243 | return s; 244 | } 245 | 246 | int main(void) 247 | { 248 | int number_failed; 249 | Suite *s; 250 | SRunner *sr; 251 | 252 | s = orcania_suite(); 253 | sr = srunner_create(s); 254 | 255 | srunner_run_all(sr, CK_VERBOSE); 256 | number_failed = srunner_ntests_failed(sr); 257 | srunner_free(sr); 258 | 259 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 260 | } 261 | -------------------------------------------------------------------------------- /test/run_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | printf_new() { 4 | str=$1 5 | num=$2 6 | v=$(printf "%-${num}s" "$str") 7 | printf "${v// / }" 8 | } 9 | 10 | RED='\033[0;31m' 11 | GREEN='\033[0;32m' 12 | NC='\033[0m' # No Color 13 | COMMAND=$1 14 | CHRLEN=${#COMMAND} 15 | NBSP=$((32-$CHRLEN)) 16 | 17 | printf "Run $1" 18 | printf_new " " $NBSP 19 | 20 | $1 $2 $3 $4 $5 $6 $7 $8 $9 1>$1.log 2>&1 21 | 22 | if [ $? -ne 0 ] 23 | then 24 | printf "${RED}FAIL${NC}\n" 25 | else 26 | printf "${GREEN}SUCCESS${NC}\n" 27 | fi 28 | -------------------------------------------------------------------------------- /test/split_test.c: -------------------------------------------------------------------------------- 1 | /* Public domain, no copyright. Use at your own risk. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "orcania.h" 11 | 12 | START_TEST(test_split_string) 13 | { 14 | char * str = "ab,cd,ef,gghhii,jkl", * str_2 = "ab, cd,ef,gghhii, jkl", * separator = ",", * long_separator = ", ", ** splitted; 15 | int nb_elt; 16 | nb_elt = split_string(str, separator, &splitted); 17 | ck_assert_ptr_ne(splitted, NULL); 18 | ck_assert_int_eq(nb_elt, 5); 19 | ck_assert_int_eq(split_string(str, "nope", NULL), 1); 20 | ck_assert_str_eq(splitted[0], "ab"); 21 | free_string_array(splitted); 22 | 23 | nb_elt = split_string(str_2, long_separator, &splitted); 24 | ck_assert_ptr_ne(splitted, NULL); 25 | ck_assert_int_eq(nb_elt, 3); 26 | free_string_array(splitted); 27 | 28 | nb_elt = split_string(str_2, "yolo", &splitted); 29 | ck_assert_ptr_ne(splitted, NULL); 30 | ck_assert_int_eq(nb_elt, 1); 31 | free_string_array(splitted); 32 | 33 | nb_elt = split_string("john", "and-yolo", &splitted); 34 | ck_assert_ptr_ne(splitted, NULL); 35 | ck_assert_int_eq(nb_elt, 1); 36 | free_string_array(splitted); 37 | } 38 | END_TEST 39 | 40 | START_TEST(test_string_array_has_value) 41 | { 42 | char * str = "ab,cd,ef,gghhii,jkl", * separator = ",", ** splitted; 43 | ck_assert_int_eq(split_string(str, separator, &splitted), 5); 44 | ck_assert_int_eq(string_array_has_value((const char **)splitted, "ab"), 1); 45 | ck_assert_int_eq(string_array_has_value((const char **)splitted, "nope"), 0); 46 | ck_assert_int_eq(string_array_has_value((const char **)splitted, NULL), 0); 47 | ck_assert_int_eq(string_array_has_value(NULL, "ab"), 0); 48 | free_string_array(splitted); 49 | } 50 | END_TEST 51 | 52 | START_TEST(test_string_array_join) 53 | { 54 | char * str = "ab,cd,ef,gghhii,jkl", * separator = ",", * join, ** splitted; 55 | ck_assert_int_eq(split_string(str, separator, &splitted), 5); 56 | join = string_array_join((const char **)splitted, " "); 57 | ck_assert_str_eq(join, "ab cd ef gghhii jkl"); 58 | ck_assert_ptr_eq(string_array_join(NULL, " "), NULL); 59 | ck_assert_ptr_eq(string_array_join((const char **)splitted, NULL), NULL); 60 | ck_assert_ptr_eq(string_array_join(NULL, NULL), NULL); 61 | free_string_array(splitted); 62 | o_free(join); 63 | } 64 | END_TEST 65 | 66 | START_TEST(test_string_array_size) 67 | { 68 | char * str = "ab,cd,ef,gghhii,jkl", * separator = ",", ** splitted, ** empty_array = {NULL}; 69 | ck_assert_int_eq(split_string(str, separator, &splitted), 5); 70 | ck_assert_int_eq(string_array_size(splitted), 5); 71 | ck_assert_int_eq(string_array_size(NULL), 0); 72 | ck_assert_int_eq(string_array_size(empty_array), 0); 73 | free_string_array(splitted); 74 | } 75 | END_TEST 76 | 77 | static Suite *orcania_suite(void) 78 | { 79 | Suite *s; 80 | TCase *tc_core; 81 | 82 | s = suite_create("Orcania tests split string functions"); 83 | tc_core = tcase_create("test_orcania_split"); 84 | tcase_add_test(tc_core, test_split_string); 85 | tcase_add_test(tc_core, test_string_array_has_value); 86 | tcase_add_test(tc_core, test_string_array_join); 87 | tcase_add_test(tc_core, test_string_array_size); 88 | tcase_set_timeout(tc_core, 30); 89 | suite_add_tcase(s, tc_core); 90 | 91 | return s; 92 | } 93 | 94 | int main(void) 95 | { 96 | int number_failed; 97 | Suite *s; 98 | SRunner *sr; 99 | 100 | s = orcania_suite(); 101 | sr = srunner_create(s); 102 | 103 | srunner_run_all(sr, CK_VERBOSE); 104 | number_failed = srunner_ntests_failed(sr); 105 | srunner_free(sr); 106 | 107 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 108 | } 109 | -------------------------------------------------------------------------------- /test/str_test.c: -------------------------------------------------------------------------------- 1 | /* Public domain, no copyright. Use at your own risk. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "orcania.h" 11 | 12 | static void run_test_base64(const unsigned char * src, size_t src_len, const unsigned char * b64_expected, size_t b64_expected_len, const unsigned char * b64url_expected, size_t b64url_expected_len) { 13 | unsigned char out[256] = {0}, * out_m; 14 | size_t out_len = 0; 15 | 16 | memset(out, 0, 256); 17 | out_len = 0; 18 | ck_assert_int_eq(o_base64_encode(src, src_len, out, &out_len), 1); 19 | ck_assert_int_eq(out_len, b64_expected_len); 20 | ck_assert_str_eq((const char *)out, (const char *)b64_expected); 21 | 22 | out_len = 0; 23 | ck_assert_int_eq(o_base64_encode(src, src_len, NULL, &out_len), 1); 24 | ck_assert_int_eq(out_len, b64_expected_len); 25 | out_m = o_malloc(out_len); 26 | out_len = 0; 27 | ck_assert_int_eq(o_base64_encode(src, src_len, out_m, &out_len), 1); 28 | o_free(out_m); 29 | 30 | memset(out, 0, 256); 31 | out_len = 0; 32 | ck_assert_int_eq(o_base64_decode(b64_expected, b64_expected_len, out, &out_len), 1); 33 | ck_assert_int_eq(out_len, src_len); 34 | ck_assert_int_eq(0, memcmp(src, out, out_len)); 35 | 36 | out_len = 0; 37 | ck_assert_int_eq(o_base64_decode(b64_expected, b64_expected_len, NULL, &out_len), 1); 38 | ck_assert_int_eq(out_len, src_len); 39 | out_m = o_malloc(out_len+2); 40 | out_len = 0; 41 | ck_assert_int_eq(o_base64_decode(b64_expected, b64_expected_len, out_m, &out_len), 1); 42 | o_free(out_m); 43 | 44 | memset(out, 0, 256); 45 | out_len = 0; 46 | ck_assert_int_eq(o_base64url_encode(src, src_len, out, &out_len), 1); 47 | ck_assert_int_eq(out_len, b64url_expected_len); 48 | ck_assert_str_eq((const char *)out, (const char *)b64url_expected); 49 | 50 | out_len = 0; 51 | ck_assert_int_eq(o_base64url_encode(src, src_len, NULL, &out_len), 1); 52 | ck_assert_int_eq(out_len, b64url_expected_len); 53 | out_m = o_malloc(out_len); 54 | out_len = 0; 55 | ck_assert_int_eq(o_base64url_encode(src, src_len, out_m, &out_len), 1); 56 | o_free(out_m); 57 | 58 | memset(out, 0, 256); 59 | out_len = 0; 60 | ck_assert_int_eq(o_base64url_decode(b64url_expected, b64url_expected_len, out, &out_len), 1); 61 | ck_assert_int_eq(out_len, src_len); 62 | ck_assert_int_eq(0, memcmp(src, out, out_len)); 63 | 64 | out_len = 0; 65 | ck_assert_int_eq(o_base64url_decode(b64url_expected, b64url_expected_len, NULL, &out_len), 1); 66 | ck_assert_int_eq(out_len, src_len); 67 | out_m = o_malloc(out_len+2); 68 | out_len = 0; 69 | ck_assert_int_eq(o_base64url_decode(b64url_expected, b64url_expected_len, out_m, &out_len), 1); 70 | o_free(out_m); 71 | 72 | memset(out, 0, 256); 73 | out_len = 0; 74 | ck_assert_int_eq(o_base64_2_base64url(b64_expected, b64_expected_len, out, &out_len), 1); 75 | ck_assert_int_eq(out_len, b64url_expected_len); 76 | ck_assert_int_eq(0, memcmp(b64url_expected, out, out_len)); 77 | 78 | memset(out, 0, 256); 79 | out_len = 0; 80 | ck_assert_int_eq(o_base64url_2_base64(b64url_expected, b64url_expected_len, out, &out_len), 1); 81 | ck_assert_int_eq(out_len, b64_expected_len); 82 | ck_assert_int_eq(0, memcmp(b64_expected, out, out_len)); 83 | } 84 | 85 | static void run_test_base64_alloc(const unsigned char * src, size_t src_len, const unsigned char * b64_expected, size_t b64_expected_len, const unsigned char * b64url_expected, size_t b64url_expected_len) { 86 | struct _o_datum dat = {0, NULL}; 87 | 88 | ck_assert_int_eq(o_base64_encode_alloc(src, src_len, &dat), 1); 89 | ck_assert_int_eq(b64_expected_len, dat.size); 90 | ck_assert_str_eq((const char *)dat.data, (const char *)b64_expected); 91 | o_free(dat.data); 92 | dat.data = NULL; 93 | dat.size = 0; 94 | 95 | ck_assert_int_eq(o_base64_decode_alloc(b64_expected, b64_expected_len, &dat), 1); 96 | ck_assert_int_eq(dat.size, src_len); 97 | ck_assert_int_eq(0, memcmp(src, dat.data, dat.size)); 98 | o_free(dat.data); 99 | dat.data = NULL; 100 | dat.size = 0; 101 | 102 | ck_assert_int_eq(o_base64url_encode_alloc(src, src_len, &dat), 1); 103 | ck_assert_int_eq(dat.size, b64url_expected_len); 104 | ck_assert_str_eq((const char *)dat.data, (const char *)b64url_expected); 105 | o_free(dat.data); 106 | dat.data = NULL; 107 | dat.size = 0; 108 | 109 | ck_assert_int_eq(o_base64url_decode_alloc(b64url_expected, b64url_expected_len, &dat), 1); 110 | ck_assert_int_eq(dat.size, src_len); 111 | ck_assert_int_eq(0, memcmp(src, dat.data, dat.size)); 112 | o_free(dat.data); 113 | dat.data = NULL; 114 | dat.size = 0; 115 | 116 | ck_assert_int_eq(o_base64_2_base64url_alloc(b64_expected, b64_expected_len, &dat), 1); 117 | ck_assert_int_eq(dat.size, b64url_expected_len); 118 | ck_assert_int_eq(0, memcmp(b64url_expected, dat.data, dat.size)); 119 | o_free(dat.data); 120 | dat.data = NULL; 121 | dat.size = 0; 122 | 123 | ck_assert_int_eq(o_base64url_2_base64_alloc(b64url_expected, b64url_expected_len, &dat), 1); 124 | ck_assert_int_eq(dat.size, b64_expected_len); 125 | ck_assert_int_eq(0, memcmp(b64_expected, dat.data, dat.size)); 126 | o_free(dat.data); 127 | dat.data = NULL; 128 | dat.size = 0; 129 | } 130 | 131 | START_TEST(test_str_replace) 132 | { 133 | char * str = "abcdeffedcba", * old_1 = "cd", * new_1 = "gh", * old_2 = "f", * target; 134 | target = str_replace(str, old_1, new_1); 135 | ck_assert_str_eq(target, "abgheffedcba"); 136 | ck_assert_ptr_eq(str_replace(NULL, old_1, new_1), NULL); 137 | ck_assert_ptr_eq(str_replace(str, NULL, new_1), NULL); 138 | ck_assert_ptr_eq(str_replace(str, old_1, NULL), NULL); 139 | o_free(target); 140 | target = str_replace(str, old_2, new_1); 141 | ck_assert_str_eq(target, "abcdeghghedcba"); 142 | o_free(target); 143 | target = str_replace(str, str, ""); 144 | ck_assert_str_eq(target, ""); 145 | o_free(target); 146 | } 147 | END_TEST 148 | 149 | START_TEST(test_o_strdup) 150 | { 151 | char * str = "abcdeffedcba", * target; 152 | target = o_strdup(str); 153 | ck_assert_str_eq(target, str); 154 | o_free(target); 155 | ck_assert_ptr_eq(o_strdup(NULL), NULL); 156 | } 157 | END_TEST 158 | 159 | START_TEST(test_o_strndup) 160 | { 161 | char * str = "abcdeffedcba", * target; 162 | target = o_strndup(str, o_strlen(str)); 163 | ck_assert_str_eq(target, str); 164 | o_free(target); 165 | target = o_strndup(str, o_strlen(str)-2); 166 | ck_assert_str_eq(target, "abcdeffedc"); 167 | o_free(target); 168 | ck_assert_ptr_eq(o_strndup(NULL, 12), NULL); 169 | target = o_strndup("abcdeffedc", 0); 170 | ck_assert_ptr_ne(target, NULL); 171 | o_free(target); 172 | } 173 | END_TEST 174 | 175 | START_TEST(test_o_strcmp) 176 | { 177 | char * str_1 = "abcdeffedcba", * str_2 = "bob", * str_3 = "abcdeffedcba"; 178 | ck_assert_int_eq(o_strcmp(str_1, str_3), 0); 179 | ck_assert_int_ne(o_strcmp(str_1, str_2), 0); 180 | ck_assert_int_ne(o_strcmp(str_1, NULL), 0); 181 | ck_assert_int_ne(o_strcmp(NULL, str_1), 0); 182 | ck_assert_int_eq(o_strcmp(NULL, NULL), 0); 183 | } 184 | END_TEST 185 | 186 | START_TEST(test_o_strncmp) 187 | { 188 | char * str_1 = "abcdeffedcba", * str_2 = "abc", * str_3 = "abcdeffedcba"; 189 | ck_assert_int_eq(o_strncmp(str_1, str_3, o_strlen(str_3)), 0); 190 | ck_assert_int_eq(o_strncmp(str_1, str_2, o_strlen(str_2)), 0); 191 | ck_assert_int_ne(o_strncmp(str_1, str_2, o_strlen(str_1)), 0); 192 | ck_assert_int_ne(o_strncmp(str_1, NULL, o_strlen(str_1)), 0); 193 | ck_assert_int_ne(o_strncmp(NULL, str_1, o_strlen(str_1)), 0); 194 | ck_assert_int_eq(o_strncmp(NULL, NULL, 0), 0); 195 | ck_assert_int_eq(o_strncmp(NULL, NULL, 1), 0); 196 | } 197 | END_TEST 198 | 199 | START_TEST(test_o_strcasecmp) 200 | { 201 | char * str_1 = "abcdeffedcba", * str_2 = "bob", * str_3 = "AbcdeFfedcba"; 202 | ck_assert_int_eq(o_strcasecmp(str_1, str_3), 0); 203 | ck_assert_int_ne(o_strcasecmp(str_1, str_2), 0); 204 | ck_assert_int_ne(o_strcasecmp(str_1, NULL), 0); 205 | ck_assert_int_ne(o_strcasecmp(NULL, str_1), 0); 206 | ck_assert_int_eq(o_strcasecmp(NULL, NULL), 0); 207 | } 208 | END_TEST 209 | 210 | START_TEST(test_o_strncasecmp) 211 | { 212 | char * str_1 = "abcdeFfedcba", * str_2 = "abC", * str_3 = "abCdeffedCba"; 213 | ck_assert_int_eq(o_strncasecmp(str_1, str_3, o_strlen(str_3)), 0); 214 | ck_assert_int_eq(o_strncasecmp(str_1, str_2, o_strlen(str_2)), 0); 215 | ck_assert_int_ne(o_strncasecmp(str_1, str_2, o_strlen(str_1)), 0); 216 | ck_assert_int_ne(o_strncasecmp(str_1, NULL, o_strlen(str_1)), 0); 217 | ck_assert_int_ne(o_strncasecmp(NULL, str_1, o_strlen(str_1)), 0); 218 | ck_assert_int_eq(o_strncasecmp(NULL, NULL, 0), 0); 219 | ck_assert_int_eq(o_strncasecmp(NULL, NULL, 1), 0); 220 | } 221 | END_TEST 222 | 223 | START_TEST(test_o_strcpy) 224 | { 225 | char * src = "abcd", target[5]; 226 | ck_assert_ptr_ne(o_strcpy(target, src), NULL); 227 | ck_assert_str_eq(target, src); 228 | ck_assert_ptr_eq(o_strcpy(target, NULL), NULL); 229 | ck_assert_ptr_eq(o_strcpy(NULL, src), NULL); 230 | ck_assert_ptr_eq(o_strcpy(NULL, NULL), NULL); 231 | } 232 | END_TEST 233 | 234 | START_TEST(test_o_strncpy) 235 | { 236 | char * src = "abcd", target[5] = {0}; 237 | ck_assert_ptr_ne(o_strncpy(target, src, 3), NULL); 238 | ck_assert_str_eq(target, "abc"); 239 | ck_assert_ptr_eq(o_strncpy(target, NULL, 4), NULL); 240 | ck_assert_ptr_eq(o_strncpy(NULL, src, 4), NULL); 241 | ck_assert_ptr_eq(o_strncpy(NULL, NULL, 4), NULL); 242 | } 243 | END_TEST 244 | 245 | START_TEST(test_o_strstr) 246 | { 247 | char * str_1 = "abcdeffedcba", * str_2 = "def", * str_3 = "bob"; 248 | ck_assert_ptr_ne(o_strstr(str_1, str_2), NULL); 249 | ck_assert_ptr_eq(o_strstr(str_1, str_3), NULL); 250 | ck_assert_ptr_eq(o_strstr(NULL, str_3), NULL); 251 | ck_assert_ptr_eq(o_strstr(str_1, NULL), NULL); 252 | ck_assert_ptr_eq(o_strstr(NULL, NULL), NULL); 253 | } 254 | END_TEST 255 | 256 | START_TEST(test_o_strnstr) 257 | { 258 | char * str_1 = "abcdeffedcba", * str_2 = "def", * str_3 = "bob"; 259 | ck_assert_ptr_ne(o_strnstr(str_1, str_2, o_strlen(str_1)), NULL); 260 | ck_assert_ptr_eq(o_strnstr(str_1, str_3, o_strlen(str_1)), NULL); 261 | ck_assert_ptr_eq(o_strnstr(str_1, str_3, 0), NULL); 262 | ck_assert_ptr_eq(o_strnstr(NULL, str_3, o_strlen(str_3)), NULL); 263 | ck_assert_ptr_eq(o_strnstr(str_1, NULL, o_strlen(str_1)), NULL); 264 | ck_assert_ptr_eq(o_strnstr(NULL, NULL, o_strlen(str_3)), NULL); 265 | } 266 | END_TEST 267 | 268 | START_TEST(test_o_strchr) 269 | { 270 | char * str_1 = "abcdef", str_2 = 'd', str_3 = 'g'; 271 | ck_assert_ptr_ne(o_strchr(str_1, str_2), NULL); 272 | ck_assert_ptr_eq(o_strchr(str_1, str_3), NULL); 273 | ck_assert_ptr_eq(o_strchr(NULL, str_3), NULL); 274 | } 275 | END_TEST 276 | 277 | START_TEST(test_o_strnchr) 278 | { 279 | char * str_1 = "abcdef", str_2 = 'd'; 280 | ck_assert_ptr_ne(o_strnchr(str_1, 5, str_2), NULL); 281 | ck_assert_ptr_eq(o_strnchr(str_1, 2, str_2), NULL); 282 | ck_assert_ptr_eq(o_strnchr(str_1, 0, str_2), NULL); 283 | ck_assert_ptr_ne(o_strnchr(str_1, 8, str_2), NULL); 284 | ck_assert_ptr_eq(o_strnchr(NULL, 4, str_2), NULL); 285 | } 286 | END_TEST 287 | 288 | START_TEST(test_o_strrchr) 289 | { 290 | char * str_1 = "abcdef", str_2 = 'd', str_3 = 'g'; 291 | ck_assert_ptr_ne(o_strrchr(str_1, str_2), NULL); 292 | ck_assert_ptr_eq(o_strrchr(str_1, str_3), NULL); 293 | ck_assert_ptr_ne(o_strrchr(str_1, str_2), NULL); 294 | ck_assert_ptr_eq(o_strrchr(NULL, str_3), NULL); 295 | } 296 | END_TEST 297 | 298 | START_TEST(test_o_strrnchr) 299 | { 300 | char * str_1 = "abcdef", str_2 = 'd'; 301 | ck_assert_ptr_ne(o_strrnchr(str_1, 5, str_2), NULL); 302 | ck_assert_ptr_eq(o_strrnchr(str_1, 2, str_2), NULL); 303 | ck_assert_ptr_eq(o_strrnchr(str_1, 0, str_2), NULL); 304 | ck_assert_ptr_ne(o_strrnchr(str_1, 8, str_2), NULL); 305 | ck_assert_ptr_eq(o_strrnchr(NULL, 4, str_2), NULL); 306 | } 307 | END_TEST 308 | 309 | START_TEST(test_o_strlen) 310 | { 311 | ck_assert_int_eq(o_strlen("abcdef"), 6); 312 | ck_assert_int_eq(o_strlen(NULL), 0); 313 | ck_assert_int_eq(o_strlen(""), 0); 314 | } 315 | END_TEST 316 | 317 | START_TEST(test_msprintf) 318 | { 319 | char * target; 320 | char tmp[100]; 321 | target = msprintf("target1 %s %d %s %p", "str1", 42, "pl\342\230\272op", NULL); 322 | sprintf(tmp, "target1 %s %d %s %p", "str1", 42, "pl\342\230\272op", NULL); 323 | ck_assert_str_eq(target, tmp); 324 | o_free(target); 325 | ck_assert_ptr_eq(msprintf(NULL, "str1", 42, "pl\342\230\272op", NULL), NULL); 326 | target = msprintf(""); 327 | ck_assert_ptr_ne(NULL, target); 328 | o_free(target); 329 | } 330 | END_TEST 331 | 332 | START_TEST(test_mstrcatf) 333 | { 334 | char * target; 335 | char tmp[200]; 336 | target = msprintf("target1 %s %d %s %p", "str1", 42, "pl\342\230\272op", NULL); 337 | target = mstrcatf(target, "target2 %s %d %p", "str2", 42, NULL); 338 | sprintf(tmp, "target1 str1 42 %s %ptarget2 %s 42 %p", "pl\342\230\272op", NULL, "str2", NULL); 339 | ck_assert_str_eq(target, tmp); 340 | o_free(target); 341 | ck_assert_ptr_eq(msprintf(NULL, NULL, "str1", 42, NULL), NULL); 342 | target = NULL; 343 | target = mstrcatf(target, "target2 %s %d %s %p", "str2", 42, "pl\342\230\272op", NULL); 344 | sprintf(tmp, "target2 %s 42 %s %p", "str2", "pl\342\230\272op", NULL); 345 | ck_assert_str_eq(target, tmp); 346 | o_free(target); 347 | target = msprintf("target1 %s %d %s %p", "str1", 42, "pl\342\230\272op", NULL); 348 | target = mstrcatf(target, ""); 349 | sprintf(tmp, "target1 str1 42 %s %p", "pl\342\230\272op", NULL); 350 | ck_assert_str_eq(target, tmp); 351 | o_free(target); 352 | target = mstrcatf(NULL, "%s", "plop"); 353 | ck_assert_ptr_ne(NULL, target); 354 | ck_assert_str_eq("plop", target); 355 | o_free(target); 356 | } 357 | END_TEST 358 | 359 | START_TEST(test_trimwhitespace) 360 | { 361 | char * test1 = o_strdup(" bob trimmed "), * test2 = o_strdup(" \t \t"), * test3 = o_strdup(""); 362 | ck_assert_str_eq(trimwhitespace(test1), "bob trimmed"); 363 | ck_assert_str_eq(trimwhitespace(test2), ""); 364 | ck_assert_str_eq(trimwhitespace(test3), ""); 365 | ck_assert_ptr_eq(trimwhitespace(NULL), NULL); 366 | o_free(test1); 367 | o_free(test2); 368 | o_free(test3); 369 | } 370 | END_TEST 371 | 372 | START_TEST(test_trimcharacter) 373 | { 374 | char test1[] = "3bob trimmed33", test2[] = "333", test3[] = ""; 375 | ck_assert_str_eq(trimcharacter(test1, '3'), "bob trimmed"); 376 | ck_assert_str_eq(trimcharacter(test2, '3'), ""); 377 | ck_assert_str_eq(trimcharacter(test3, '3'), ""); 378 | ck_assert_ptr_eq(trimcharacter(NULL, '3'), NULL); 379 | } 380 | END_TEST 381 | 382 | START_TEST(test_split_string) 383 | { 384 | char ** array; 385 | 386 | ck_assert_int_eq(split_string("Alice,Bob,Carol,Dave,Eve,Isaac", ",", &array), 6); 387 | free_string_array(array); 388 | array = NULL; 389 | 390 | ck_assert_int_eq(split_string("Alice,Bob,Carol,Dave,Eve,Isaac", " ", &array), 1); 391 | free_string_array(array); 392 | array = NULL; 393 | 394 | ck_assert_int_eq(split_string("Alice,Bob,Carol,Dave,Eve,Isaac", ",D", &array), 2); 395 | free_string_array(array); 396 | array = NULL; 397 | 398 | ck_assert_int_eq(split_string("Alice,Bob,Carol,Dave,Eve,Isaac", ",g", &array), 1); 399 | free_string_array(array); 400 | array = NULL; 401 | 402 | ck_assert_int_eq(split_string("", ",", &array), 1); 403 | free_string_array(array); 404 | array = NULL; 405 | 406 | ck_assert_int_eq(split_string(NULL, ",", &array), 0); 407 | } 408 | END_TEST 409 | 410 | START_TEST(test_string_array) 411 | { 412 | char ** array, * str_orig = "Alice,Bob,Carol,Dave,Eve,Isaac"; 413 | int size = split_string(str_orig, ",", &array); 414 | 415 | ck_assert_int_eq(size, 6); 416 | ck_assert_int_eq(string_array_has_value((const char **)array, "Alice"), 1); 417 | ck_assert_int_eq(string_array_has_value((const char **)array, "Ali"), 0); 418 | ck_assert_int_eq(string_array_has_value((const char **)array, "Mallory"), 0); 419 | ck_assert_int_eq(string_array_has_value_case((const char **)array, "alice"), 1); 420 | ck_assert_int_eq(string_array_has_value_case((const char **)array, "ali"), 0); 421 | ck_assert_int_eq(string_array_has_value_case((const char **)array, "mallory"), 0); 422 | ck_assert_int_eq(string_array_has_value_n((const char **)array, "Ali", 3), 1); 423 | ck_assert_int_eq(string_array_has_value_n((const char **)array, "Aliceeee", 5), 1); 424 | ck_assert_int_eq(string_array_has_value_n((const char **)array, "Malloryyyy", 7), 0); 425 | ck_assert_int_eq(string_array_has_value_ncase((const char **)array, "aliceeee", 5), 1); 426 | ck_assert_int_eq(string_array_has_value_ncase((const char **)array, "malloryyyy", 7), 0); 427 | 428 | free_string_array(array); 429 | } 430 | END_TEST 431 | 432 | START_TEST(test_string_array_has_trimmed_value) 433 | { 434 | char ** array, * str_orig = "Alice,Bob,Carol,Dave,Eve,Isaac", * str_match_ok = "Carol", * str_match_not_found = "Sam"; 435 | int size = split_string(str_orig, ",", &array); 436 | 437 | ck_assert_int_eq(size, 6); 438 | ck_assert_int_eq(string_array_has_trimmed_value((const char **)array, str_match_ok), 1); 439 | ck_assert_int_eq(string_array_has_trimmed_value((const char **)array, str_match_not_found), 0); 440 | ck_assert_int_eq(string_array_has_trimmed_value((const char **)array, NULL), 0); 441 | ck_assert_int_eq(string_array_has_trimmed_value(NULL, str_match_ok), 0); 442 | ck_assert_int_eq(string_array_has_trimmed_value(NULL, NULL), 0); 443 | 444 | free_string_array(array); 445 | } 446 | END_TEST 447 | 448 | START_TEST(test_base64) 449 | { 450 | char * src = "source string", encoded[128] = {0}, decoded[128] = {0}, b64_error[] = ";error;", b64_error_2[] = "c291cmNlIHN0cmluZw=="; 451 | size_t encoded_size, decoded_size, b64_error_2_len = 20; 452 | ck_assert_int_eq(o_base64_encode((unsigned char *)src, o_strlen(src), (unsigned char *)encoded, &encoded_size), 1); 453 | ck_assert_str_eq(encoded, "c291cmNlIHN0cmluZw=="); 454 | ck_assert_int_eq(20, encoded_size); 455 | ck_assert_int_eq(o_base64_decode((unsigned char *)encoded, encoded_size-1, (unsigned char *)decoded, &decoded_size), 0); 456 | ck_assert_int_eq(o_base64_decode((unsigned char *)encoded, encoded_size-2, (unsigned char *)decoded, &decoded_size), 0); 457 | ck_assert_int_eq(o_base64_decode((unsigned char *)encoded, encoded_size-3, (unsigned char *)decoded, &decoded_size), 0); 458 | ck_assert_int_eq(o_base64_decode((unsigned char *)encoded, encoded_size-4, (unsigned char *)decoded, &decoded_size), 1); 459 | ck_assert_int_eq(o_base64_decode((unsigned char *)(encoded+1), encoded_size-1, (unsigned char *)decoded, &decoded_size), 0); 460 | ck_assert_int_eq(o_base64_decode((unsigned char *)(encoded+2), encoded_size-2, (unsigned char *)decoded, &decoded_size), 0); 461 | ck_assert_int_eq(o_base64_decode((unsigned char *)(encoded+3), encoded_size-3, (unsigned char *)decoded, &decoded_size), 0); 462 | ck_assert_int_eq(o_base64_decode((unsigned char *)"", 0, (unsigned char *)decoded, &decoded_size), 0); 463 | ck_assert_int_eq(o_base64_decode((unsigned char *)"Zw==", 4, (unsigned char *)decoded, &decoded_size), 1); 464 | ck_assert_int_eq(o_base64_decode((unsigned char *)"Z===", 4, (unsigned char *)decoded, &decoded_size), 0); 465 | ck_assert_int_eq(o_base64_decode((unsigned char *)"==", 2, (unsigned char *)decoded, &decoded_size), 0); 466 | ck_assert_int_eq(o_base64_decode((unsigned char *)"===", 3, (unsigned char *)decoded, &decoded_size), 0); 467 | ck_assert_int_eq(o_base64_decode((unsigned char *)"====", 4, (unsigned char *)decoded, &decoded_size), 0); 468 | ck_assert_int_eq(o_base64_decode((unsigned char *)"cmluZw==", 8, (unsigned char *)decoded, &decoded_size), 1); 469 | ck_assert_int_eq(o_base64_decode((unsigned char *)"cmluZwe=", 8, (unsigned char *)decoded, &decoded_size), 1); 470 | ck_assert_int_eq(o_base64_decode((unsigned char *)"cmluZweS", 8, (unsigned char *)decoded, &decoded_size), 1); 471 | ck_assert_int_eq(o_base64_decode((unsigned char *)"cmluZ ==", 8, (unsigned char *)decoded, &decoded_size), 0); 472 | ck_assert_int_eq(o_base64_decode((unsigned char *)"cmluZ===", 8, (unsigned char *)decoded, &decoded_size), 0); 473 | ck_assert_int_eq(o_base64_decode((unsigned char *)"cmlu= =", 8, (unsigned char *)decoded, &decoded_size), 0); 474 | ck_assert_int_eq(o_base64_decode((unsigned char *)"cmlu====", 8, (unsigned char *)decoded, &decoded_size), 0); 475 | ck_assert_int_eq(o_base64_decode((unsigned char *)" cmlu===", 8, (unsigned char *)decoded, &decoded_size), 0); 476 | ck_assert_int_eq(o_base64_decode((unsigned char *)"cmlu==E=", 8, (unsigned char *)decoded, &decoded_size), 0); 477 | ck_assert_int_eq(o_base64_decode((unsigned char *)"cmluZ=eS", 8, (unsigned char *)decoded, &decoded_size), 1); 478 | ck_assert_int_eq(o_base64_decode((unsigned char *)encoded, encoded_size, (unsigned char *)decoded, &decoded_size), 1); 479 | ck_assert_str_eq(decoded, src); 480 | ck_assert_int_eq(decoded_size, o_strlen(src)); 481 | ck_assert_int_eq(o_base64_decode((unsigned char *)b64_error, o_strlen(b64_error), NULL, &decoded_size), 0); 482 | ck_assert_int_eq(o_base64_decode((unsigned char *)b64_error, o_strlen(b64_error), (unsigned char *)decoded, &decoded_size), 0); 483 | 484 | memset(encoded, 0, 128); 485 | memset(decoded, 0, 128); 486 | ck_assert_int_eq(o_base64_encode((unsigned char *)src, 1, (unsigned char *)encoded, &encoded_size), 1); 487 | ck_assert_int_eq(4, encoded_size); 488 | ck_assert_int_eq(o_base64_decode((unsigned char *)encoded, encoded_size, (unsigned char *)decoded, &decoded_size), 1); 489 | ck_assert_int_eq(decoded_size, 1); 490 | ck_assert_int_eq(o_base64_decode((unsigned char *)encoded, 3, (unsigned char *)decoded, &decoded_size), 0); 491 | ck_assert_int_eq(o_base64_decode((unsigned char *)encoded, 2, (unsigned char *)decoded, &decoded_size), 0); 492 | ck_assert_int_eq(o_base64_decode((unsigned char *)encoded, 1, (unsigned char *)decoded, &decoded_size), 0); 493 | 494 | ck_assert_int_eq(o_base64_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 1); 495 | // Insert invalid characters 496 | b64_error_2[4] = 0; 497 | ck_assert_int_eq(o_base64_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 498 | b64_error_2[4] = 2; 499 | ck_assert_int_eq(o_base64_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 500 | b64_error_2[4] = 11; 501 | ck_assert_int_eq(o_base64_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 502 | b64_error_2[4] = 128; 503 | ck_assert_int_eq(o_base64_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 504 | b64_error_2[4] = '='; 505 | ck_assert_int_eq(o_base64_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 1); 506 | ck_assert_int_gt(o_strlen(src), decoded_size); 507 | b64_error_2[4] = '-'; 508 | ck_assert_int_eq(o_base64_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 509 | b64_error_2[4] = '_'; 510 | ck_assert_int_eq(o_base64_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 511 | } 512 | END_TEST 513 | 514 | START_TEST(test_base64_more_test_cases) 515 | { 516 | const unsigned char message1[] = "C combines the power and performance of assembly language with the flexibility and ease-of-use of assembly language.", 517 | message2[] = "Bryan is in\nthe kitchen", 518 | message3[] = {0}, 519 | message4[] = {0, 0}, 520 | message5[] = {0, 0, 0}, 521 | message6[] = {0x32, 0x0, 0x0}, 522 | message7[] = "아쿠아 포니", 523 | message8[] = {0x76, 0x65, 0x72, 0x79, 0x00, 0x20, 0x75, 0x6e, 0x75, 0x73, 0x75, 0x61, 0x6c, 0x9b, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67}, 524 | message9[] = "\377", 525 | message10[] = "\377\377", 526 | message11[] = "\377\377\377", 527 | message12[] = "\xff\xef"; 528 | const unsigned char message1_b64[] = "QyBjb21iaW5lcyB0aGUgcG93ZXIgYW5kIHBlcmZvcm1hbmNlIG9mIGFzc2VtYmx5IGxhbmd1YWdlIHdpdGggdGhlIGZsZXhpYmlsaXR5IGFuZCBlYXNlLW9mLXVzZSBvZiBhc3NlbWJseSBsYW5ndWFnZS4=", 529 | message2_b64[] = "QnJ5YW4gaXMgaW4KdGhlIGtpdGNoZW4=", 530 | message3_b64[] = "AA==", 531 | message4_b64[] = "AAA=", 532 | message5_b64[] = "AAAA", 533 | message6_b64[] = "MgAA", 534 | message7_b64[] = "7JWE7L+g7JWEIO2PrOuLiAA=", 535 | message8_b64[] = "dmVyeQAgdW51c3VhbJsgc3RyaW5n", 536 | message9_b64[] = "/w==", 537 | message10_b64[] = "//8=", 538 | message11_b64[] = "////", 539 | message12_b64[] = "/+8="; 540 | const unsigned char message1_b64url[] = "QyBjb21iaW5lcyB0aGUgcG93ZXIgYW5kIHBlcmZvcm1hbmNlIG9mIGFzc2VtYmx5IGxhbmd1YWdlIHdpdGggdGhlIGZsZXhpYmlsaXR5IGFuZCBlYXNlLW9mLXVzZSBvZiBhc3NlbWJseSBsYW5ndWFnZS4", 541 | message2_b64url[] = "QnJ5YW4gaXMgaW4KdGhlIGtpdGNoZW4", 542 | message3_b64url[] = "AA", 543 | message4_b64url[] = "AAA", 544 | message5_b64url[] = "AAAA", 545 | message6_b64url[] = "MgAA", 546 | message7_b64url[] = "7JWE7L-g7JWEIO2PrOuLiAA", 547 | message8_b64url[] = "dmVyeQAgdW51c3VhbJsgc3RyaW5n", 548 | message9_b64url[] = "_w", 549 | message10_b64url[] = "__8", 550 | message11_b64url[] = "____", 551 | message12_b64url[] = "_-8"; 552 | 553 | run_test_base64(message1, o_strlen((const char *)message1), message1_b64, o_strlen((const char *)message1_b64), message1_b64url, o_strlen((const char *)message1_b64url)); 554 | run_test_base64(message2, o_strlen((const char *)message2), message2_b64, o_strlen((const char *)message2_b64), message2_b64url, o_strlen((const char *)message2_b64url)); 555 | run_test_base64(message3, sizeof(message3), message3_b64, o_strlen((const char *)message3_b64), message3_b64url, o_strlen((const char *)message3_b64url)); 556 | run_test_base64(message4, sizeof(message4), message4_b64, o_strlen((const char *)message4_b64), message4_b64url, o_strlen((const char *)message4_b64url)); 557 | run_test_base64(message5, sizeof(message5), message5_b64, o_strlen((const char *)message5_b64), message5_b64url, o_strlen((const char *)message5_b64url)); 558 | run_test_base64(message6, sizeof(message6), message6_b64, o_strlen((const char *)message6_b64), message6_b64url, o_strlen((const char *)message6_b64url)); 559 | run_test_base64(message7, sizeof(message7), message7_b64, o_strlen((const char *)message7_b64), message7_b64url, o_strlen((const char *)message7_b64url)); 560 | run_test_base64(message8, sizeof(message8), message8_b64, o_strlen((const char *)message8_b64), message8_b64url, o_strlen((const char *)message8_b64url)); 561 | run_test_base64(message9, o_strlen((const char *)message9), message9_b64, o_strlen((const char *)message9_b64), message9_b64url, o_strlen((const char *)message9_b64url)); 562 | run_test_base64(message10, o_strlen((const char *)message10), message10_b64, o_strlen((const char *)message10_b64), message10_b64url, o_strlen((const char *)message10_b64url)); 563 | run_test_base64(message11, o_strlen((const char *)message11), message11_b64, o_strlen((const char *)message11_b64), message11_b64url, o_strlen((const char *)message11_b64url)); 564 | run_test_base64(message12, o_strlen((const char *)message12), message12_b64, o_strlen((const char *)message12_b64), message12_b64url, o_strlen((const char *)message12_b64url)); 565 | } 566 | END_TEST 567 | 568 | START_TEST(test_base64url) 569 | { 570 | char * src = "source string", encoded[128] = {0}, decoded[128] = {0}, b64_error[] = ";error;", b64_error_2[] = "c291cmNlIHN0cmluZw"; 571 | size_t encoded_size, decoded_size, b64_error_2_len = 18; 572 | ck_assert_int_eq(o_base64url_encode((unsigned char *)src, o_strlen(src), (unsigned char *)encoded, &encoded_size), 1); 573 | ck_assert_str_eq(encoded, "c291cmNlIHN0cmluZw"); 574 | ck_assert_int_eq(18, encoded_size); 575 | ck_assert_int_eq(o_base64url_decode((unsigned char *)encoded, encoded_size-1, (unsigned char *)decoded, &decoded_size), 0); 576 | ck_assert_int_eq(o_base64url_decode((unsigned char *)encoded, encoded_size-2, (unsigned char *)decoded, &decoded_size), 1); 577 | ck_assert_int_eq(o_base64url_decode((unsigned char *)encoded, encoded_size-3, (unsigned char *)decoded, &decoded_size), 1); 578 | ck_assert_int_eq(o_base64url_decode((unsigned char *)encoded, encoded_size-4, (unsigned char *)decoded, &decoded_size), 1); 579 | ck_assert_int_eq(o_base64url_decode((unsigned char *)(encoded+1), encoded_size-1, (unsigned char *)decoded, &decoded_size), 0); 580 | ck_assert_int_eq(o_base64url_decode((unsigned char *)"", 0, (unsigned char *)decoded, &decoded_size), 0); 581 | ck_assert_int_eq(o_base64url_decode((unsigned char *)"Zw", 2, (unsigned char *)decoded, &decoded_size), 1); 582 | ck_assert_int_eq(o_base64url_decode((unsigned char *)"Zw ", 4, (unsigned char *)decoded, &decoded_size), 0); 583 | ck_assert_int_eq(o_base64url_decode((unsigned char *)"Z ", 4, (unsigned char *)decoded, &decoded_size), 0); 584 | ck_assert_int_eq(o_base64url_decode((unsigned char *)" ", 4, (unsigned char *)decoded, &decoded_size), 0); 585 | ck_assert_int_eq(o_base64url_decode((unsigned char *)"cmluZw ", 8, (unsigned char *)decoded, &decoded_size), 0); 586 | ck_assert_int_eq(o_base64url_decode((unsigned char *)"cmluZwe ", 8, (unsigned char *)decoded, &decoded_size), 0); 587 | ck_assert_int_eq(o_base64url_decode((unsigned char *)"cmluZweS", 8, (unsigned char *)decoded, &decoded_size), 1); 588 | ck_assert_int_eq(o_base64url_decode((unsigned char *)"cmluZ ", 8, (unsigned char *)decoded, &decoded_size), 0); 589 | ck_assert_int_eq(o_base64url_decode((unsigned char *)" cmluZ ", 8, (unsigned char *)decoded, &decoded_size), 0); 590 | ck_assert_int_eq(o_base64url_decode((unsigned char *)"cmlu ", 8, (unsigned char *)decoded, &decoded_size), 0); 591 | ck_assert_int_eq(o_base64url_decode((unsigned char *)" cmlu ", 8, (unsigned char *)decoded, &decoded_size), 0); 592 | ck_assert_int_eq(o_base64url_decode((unsigned char *)"cmlu E ", 8, (unsigned char *)decoded, &decoded_size), 0); 593 | ck_assert_int_eq(o_base64url_decode((unsigned char *)encoded, encoded_size, (unsigned char *)decoded, &decoded_size), 1); 594 | ck_assert_str_eq(decoded, src); 595 | ck_assert_int_eq(decoded_size, o_strlen(src)); 596 | ck_assert_int_eq(o_base64url_decode((unsigned char *)b64_error, o_strlen(b64_error), NULL, &decoded_size), 0); 597 | ck_assert_int_eq(o_base64url_decode((unsigned char *)b64_error, o_strlen(b64_error), (unsigned char *)decoded, &decoded_size), 0); 598 | 599 | memset(encoded, 0, 128); 600 | memset(decoded, 0, 128); 601 | ck_assert_int_eq(o_base64url_encode((unsigned char *)src, 1, (unsigned char *)encoded, &encoded_size), 1); 602 | ck_assert_int_eq(2, encoded_size); 603 | ck_assert_int_eq(o_base64url_decode((unsigned char *)encoded, encoded_size, (unsigned char *)decoded, &decoded_size), 1); 604 | ck_assert_int_eq(decoded_size, 1); 605 | ck_assert_int_eq(o_base64url_decode((unsigned char *)encoded, 1, (unsigned char *)decoded, &decoded_size), 0); 606 | 607 | ck_assert_int_eq(o_base64url_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 1); 608 | // Insert invalid characters 609 | b64_error_2[4] = 0; 610 | ck_assert_int_eq(o_base64url_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 611 | b64_error_2[4] = 2; 612 | ck_assert_int_eq(o_base64url_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 613 | b64_error_2[4] = 11; 614 | ck_assert_int_eq(o_base64url_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 615 | b64_error_2[4] = 128; 616 | ck_assert_int_eq(o_base64url_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 617 | b64_error_2[4] = '='; 618 | ck_assert_int_eq(o_base64url_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 619 | b64_error_2[4] = '+'; 620 | ck_assert_int_eq(o_base64url_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 621 | b64_error_2[4] = '/'; 622 | ck_assert_int_eq(o_base64url_decode((unsigned char *)b64_error_2, b64_error_2_len, (unsigned char *)decoded, &decoded_size), 0); 623 | } 624 | END_TEST 625 | 626 | START_TEST(test_base64url_2_base64) 627 | { 628 | unsigned char src[10] = {0x6f, 0x5b, 0x70, 0x29, 0x27, 0x2d, 0x3d, 0x40, 0x7e, 0x0}, encoded[21] = {0}, encoded_url[21] = {0}, encoded_new[19] = {0}; 629 | size_t encoded_size = 0, encoded_new_size = 0; 630 | ck_assert_int_eq(o_base64_encode(src, 10, encoded, &encoded_size), 1); 631 | ck_assert_int_gt(encoded_size, 0); 632 | encoded[encoded_size] = '\0'; // should be "b1twKSctPUB+AA==" 633 | ck_assert_int_eq(o_base64url_encode(src, 10, encoded_url, &encoded_size), 1); 634 | ck_assert_int_gt(encoded_size, 0); 635 | encoded_url[encoded_size] = '\0'; // should be "b1twKSctPUB-AA" 636 | ck_assert_str_ne((const char *)encoded_url, (const char *)encoded); 637 | ck_assert_int_eq(o_base64url_2_base64(encoded_url, encoded_size, encoded_new, &encoded_new_size), 1); 638 | encoded_new[encoded_new_size] = '\0'; 639 | ck_assert_str_eq((const char *)encoded_new, (const char *)encoded); 640 | } 641 | END_TEST 642 | 643 | START_TEST(test_base64_2_base64url) 644 | { 645 | unsigned char src[10] = {0x6f, 0x5b, 0x70, 0x29, 0x27, 0x2d, 0x3d, 0x40, 0x7e, 0x0}, encoded[21] = {0}, encoded_url[21] = {0}, encoded_new[19] = {0}; 646 | size_t encoded_size = 0, encoded_new_size = 0; 647 | ck_assert_int_eq(o_base64url_encode(src, 10, encoded, &encoded_size), 1); 648 | ck_assert_int_gt(encoded_size, 0); 649 | encoded[encoded_size] = '\0'; // should be "b1twKSctPUB-AA" 650 | ck_assert_int_eq(o_base64_encode(src, 10, encoded_url, &encoded_size), 1); 651 | ck_assert_int_gt(encoded_size, 0); 652 | encoded_url[encoded_size] = '\0'; // should be "b1twKSctPUB+AA==" 653 | ck_assert_str_ne((const char *)encoded_url, (const char *)encoded); 654 | ck_assert_int_eq(o_base64_2_base64url(encoded_url, encoded_size, encoded_new, &encoded_new_size), 1); 655 | encoded_new[encoded_new_size] = '\0'; 656 | ck_assert_str_eq((const char *)encoded_new, (const char *)encoded); 657 | } 658 | END_TEST 659 | 660 | START_TEST(test_base64_len) 661 | { 662 | char * src1 = "a", * src2 = "aa", * src3 = "aaa", * src4 = "aaaa", * src5 = "aaaaa", * src = "source string", encoded[128] = {0}; 663 | char * src1_enc = "YQ==", * src2_enc = "YWE=", * src3_enc = "YWFh", *src4_enc = "YWFhYQ==", *src5_enc = "YWFhYWE="; 664 | size_t encoded_size, decoded_size; 665 | 666 | ck_assert_int_eq(o_base64_encode((unsigned char *)src, o_strlen(src), NULL, &encoded_size), 1); 667 | ck_assert_int_eq(encoded_size, 20); 668 | ck_assert_int_eq(o_base64_encode((unsigned char *)src, o_strlen(src), (unsigned char *)encoded, &encoded_size), 1); 669 | ck_assert_int_eq(o_base64_decode((unsigned char *)encoded, encoded_size, NULL, &decoded_size), 1); 670 | ck_assert_int_eq(decoded_size, 13); 671 | 672 | ck_assert_int_eq(o_base64url_encode((unsigned char *)src, o_strlen(src), NULL, &encoded_size), 1); 673 | ck_assert_int_eq(encoded_size, 18); 674 | ck_assert_int_eq(o_base64url_encode((unsigned char *)src, o_strlen(src), (unsigned char *)encoded, &encoded_size), 1); 675 | ck_assert_int_eq(o_base64url_decode((unsigned char *)encoded, encoded_size, NULL, &decoded_size), 1); 676 | ck_assert_int_eq(decoded_size, 13); 677 | 678 | ck_assert_int_eq(o_base64_encode((unsigned char *)src1, o_strlen(src1), NULL, &encoded_size), 1); 679 | ck_assert_int_eq(encoded_size, 4); 680 | ck_assert_int_eq(o_base64_encode((unsigned char *)src2, o_strlen(src2), NULL, &encoded_size), 1); 681 | ck_assert_int_eq(encoded_size, 4); 682 | ck_assert_int_eq(o_base64_encode((unsigned char *)src3, o_strlen(src3), NULL, &encoded_size), 1); 683 | ck_assert_int_eq(encoded_size, 4); 684 | ck_assert_int_eq(o_base64_encode((unsigned char *)src4, o_strlen(src4), NULL, &encoded_size), 1); 685 | ck_assert_int_eq(encoded_size, 8); 686 | ck_assert_int_eq(o_base64_encode((unsigned char *)src5, o_strlen(src5), NULL, &encoded_size), 1); 687 | ck_assert_int_eq(encoded_size, 8); 688 | 689 | ck_assert_int_eq(o_base64url_encode((unsigned char *)src1, o_strlen(src1), NULL, &encoded_size), 1); 690 | ck_assert_int_eq(encoded_size, 2); 691 | ck_assert_int_eq(o_base64url_encode((unsigned char *)src2, o_strlen(src2), NULL, &encoded_size), 1); 692 | ck_assert_int_eq(encoded_size, 3); 693 | ck_assert_int_eq(o_base64url_encode((unsigned char *)src3, o_strlen(src3), NULL, &encoded_size), 1); 694 | ck_assert_int_eq(encoded_size, 4); 695 | ck_assert_int_eq(o_base64url_encode((unsigned char *)src4, o_strlen(src4), NULL, &encoded_size), 1); 696 | ck_assert_int_eq(encoded_size, 6); 697 | ck_assert_int_eq(o_base64url_encode((unsigned char *)src5, o_strlen(src5), NULL, &encoded_size), 1); 698 | ck_assert_int_eq(encoded_size, 7); 699 | 700 | ck_assert_int_eq(o_base64_decode((unsigned char *)src1_enc, o_strlen(src1_enc), NULL, &encoded_size), 1); 701 | ck_assert_int_eq(encoded_size, 1); 702 | ck_assert_int_eq(o_base64_decode((unsigned char *)src2_enc, o_strlen(src2_enc), NULL, &encoded_size), 1); 703 | ck_assert_int_eq(encoded_size, 2); 704 | ck_assert_int_eq(o_base64_decode((unsigned char *)src3_enc, o_strlen(src3_enc), NULL, &encoded_size), 1); 705 | ck_assert_int_eq(encoded_size, 3); 706 | ck_assert_int_eq(o_base64_decode((unsigned char *)src4_enc, o_strlen(src4_enc), NULL, &encoded_size), 1); 707 | ck_assert_int_eq(encoded_size, 4); 708 | ck_assert_int_eq(o_base64_decode((unsigned char *)src5_enc, o_strlen(src5_enc), NULL, &encoded_size), 1); 709 | ck_assert_int_eq(encoded_size, 5); 710 | 711 | ck_assert_int_eq(o_base64url_decode((unsigned char *)src1_enc, o_strlen(src1_enc)-2, NULL, &encoded_size), 1); 712 | ck_assert_int_eq(encoded_size, 1); 713 | ck_assert_int_eq(o_base64url_decode((unsigned char *)src2_enc, o_strlen(src2_enc)-1, NULL, &encoded_size), 1); 714 | ck_assert_int_eq(encoded_size, 2); 715 | ck_assert_int_eq(o_base64url_decode((unsigned char *)src3_enc, o_strlen(src3_enc), NULL, &encoded_size), 1); 716 | ck_assert_int_eq(encoded_size, 3); 717 | ck_assert_int_eq(o_base64url_decode((unsigned char *)src4_enc, o_strlen(src4_enc)-2, NULL, &encoded_size), 1); 718 | ck_assert_int_eq(encoded_size, 4); 719 | ck_assert_int_eq(o_base64url_decode((unsigned char *)src5_enc, o_strlen(src5_enc)-1, NULL, &encoded_size), 1); 720 | ck_assert_int_eq(encoded_size, 5); 721 | } 722 | END_TEST 723 | 724 | START_TEST(test_base64_alloc) 725 | { 726 | char * src = "source string", b64_error[] = ";error;"; 727 | struct _o_datum dat = {0, NULL}, dat_dec = {0, NULL}; 728 | ck_assert_int_eq(o_base64_encode_alloc((unsigned char *)src, o_strlen(src), &dat), 1); 729 | ck_assert_int_eq(20, dat.size); 730 | ck_assert_int_eq(0, o_strncmp((const char *)dat.data, "c291cmNlIHN0cmluZw==", dat.size)); 731 | ck_assert_int_eq(o_base64_decode_alloc(dat.data, dat.size, &dat_dec), 1); 732 | ck_assert_int_eq(dat_dec.size, o_strlen(src)); 733 | ck_assert_int_eq(0, o_strncmp((const char *)dat_dec.data, src, dat_dec.size)); 734 | ck_assert_int_eq(o_base64_decode_alloc((unsigned char *)b64_error, o_strlen(b64_error), &dat_dec), 0); 735 | o_free(dat.data); 736 | o_free(dat_dec.data); 737 | } 738 | END_TEST 739 | 740 | START_TEST(test_base64url_alloc) 741 | { 742 | char * src = "source string", b64_error[] = ";error;"; 743 | struct _o_datum dat = {0, NULL}, dat_dec = {0, NULL}; 744 | ck_assert_int_eq(o_base64url_encode_alloc((unsigned char *)src, o_strlen(src), &dat), 1); 745 | ck_assert_int_eq(18, dat.size); 746 | ck_assert_int_eq(0, o_strncmp((const char *)dat.data, "c291cmNlIHN0cmluZw", dat.size)); 747 | ck_assert_int_eq(o_base64url_decode_alloc(dat.data, dat.size, &dat_dec), 1); 748 | ck_assert_int_eq(dat_dec.size, o_strlen(src)); 749 | ck_assert_int_eq(0, o_strncmp((const char *)dat_dec.data, src, dat_dec.size)); 750 | ck_assert_int_eq(o_base64url_decode_alloc((unsigned char *)b64_error, o_strlen(b64_error), &dat_dec), 0); 751 | o_free(dat.data); 752 | o_free(dat_dec.data); 753 | } 754 | END_TEST 755 | 756 | START_TEST(test_base64_more_test_cases_alloc) 757 | { 758 | const unsigned char message1[] = "C combines the power and performance of assembly language with the flexibility and ease-of-use of assembly language.", 759 | message2[] = "Bryan is in\nthe kitchen", 760 | message3[] = {0}, 761 | message4[] = {0, 0}, 762 | message5[] = {0, 0, 0}, 763 | message6[] = {0x32, 0x0, 0x0}, 764 | message7[] = "아쿠아 포니", 765 | message8[] = {0x76, 0x65, 0x72, 0x79, 0x00, 0x20, 0x75, 0x6e, 0x75, 0x73, 0x75, 0x61, 0x6c, 0x9b, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67}, 766 | message9[] = "\377", 767 | message10[] = "\377\377", 768 | message11[] = "\377\377\377", 769 | message12[] = "\xff\xef"; 770 | const unsigned char message1_b64[] = "QyBjb21iaW5lcyB0aGUgcG93ZXIgYW5kIHBlcmZvcm1hbmNlIG9mIGFzc2VtYmx5IGxhbmd1YWdlIHdpdGggdGhlIGZsZXhpYmlsaXR5IGFuZCBlYXNlLW9mLXVzZSBvZiBhc3NlbWJseSBsYW5ndWFnZS4=", 771 | message2_b64[] = "QnJ5YW4gaXMgaW4KdGhlIGtpdGNoZW4=", 772 | message3_b64[] = "AA==", 773 | message4_b64[] = "AAA=", 774 | message5_b64[] = "AAAA", 775 | message6_b64[] = "MgAA", 776 | message7_b64[] = "7JWE7L+g7JWEIO2PrOuLiAA=", 777 | message8_b64[] = "dmVyeQAgdW51c3VhbJsgc3RyaW5n", 778 | message9_b64[] = "/w==", 779 | message10_b64[] = "//8=", 780 | message11_b64[] = "////", 781 | message12_b64[] = "/+8="; 782 | const unsigned char message1_b64url[] = "QyBjb21iaW5lcyB0aGUgcG93ZXIgYW5kIHBlcmZvcm1hbmNlIG9mIGFzc2VtYmx5IGxhbmd1YWdlIHdpdGggdGhlIGZsZXhpYmlsaXR5IGFuZCBlYXNlLW9mLXVzZSBvZiBhc3NlbWJseSBsYW5ndWFnZS4", 783 | message2_b64url[] = "QnJ5YW4gaXMgaW4KdGhlIGtpdGNoZW4", 784 | message3_b64url[] = "AA", 785 | message4_b64url[] = "AAA", 786 | message5_b64url[] = "AAAA", 787 | message6_b64url[] = "MgAA", 788 | message7_b64url[] = "7JWE7L-g7JWEIO2PrOuLiAA", 789 | message8_b64url[] = "dmVyeQAgdW51c3VhbJsgc3RyaW5n", 790 | message9_b64url[] = "_w", 791 | message10_b64url[] = "__8", 792 | message11_b64url[] = "____", 793 | message12_b64url[] = "_-8"; 794 | 795 | run_test_base64_alloc(message1, o_strlen((const char *)message1), message1_b64, o_strlen((const char *)message1_b64), message1_b64url, o_strlen((const char *)message1_b64url)); 796 | run_test_base64_alloc(message2, o_strlen((const char *)message2), message2_b64, o_strlen((const char *)message2_b64), message2_b64url, o_strlen((const char *)message2_b64url)); 797 | run_test_base64_alloc(message3, sizeof(message3), message3_b64, o_strlen((const char *)message3_b64), message3_b64url, o_strlen((const char *)message3_b64url)); 798 | run_test_base64_alloc(message4, sizeof(message4), message4_b64, o_strlen((const char *)message4_b64), message4_b64url, o_strlen((const char *)message4_b64url)); 799 | run_test_base64_alloc(message5, sizeof(message5), message5_b64, o_strlen((const char *)message5_b64), message5_b64url, o_strlen((const char *)message5_b64url)); 800 | run_test_base64_alloc(message6, sizeof(message6), message6_b64, o_strlen((const char *)message6_b64), message6_b64url, o_strlen((const char *)message6_b64url)); 801 | run_test_base64_alloc(message7, sizeof(message7), message7_b64, o_strlen((const char *)message7_b64), message7_b64url, o_strlen((const char *)message7_b64url)); 802 | run_test_base64_alloc(message8, sizeof(message8), message8_b64, o_strlen((const char *)message8_b64), message8_b64url, o_strlen((const char *)message8_b64url)); 803 | run_test_base64_alloc(message9, o_strlen((const char *)message9), message9_b64, o_strlen((const char *)message9_b64), message9_b64url, o_strlen((const char *)message9_b64url)); 804 | run_test_base64_alloc(message10, o_strlen((const char *)message10), message10_b64, o_strlen((const char *)message10_b64), message10_b64url, o_strlen((const char *)message10_b64url)); 805 | run_test_base64_alloc(message11, o_strlen((const char *)message11), message11_b64, o_strlen((const char *)message11_b64), message11_b64url, o_strlen((const char *)message11_b64url)); 806 | run_test_base64_alloc(message12, o_strlen((const char *)message12), message12_b64, o_strlen((const char *)message12_b64), message12_b64url, o_strlen((const char *)message12_b64url)); 807 | } 808 | END_TEST 809 | 810 | START_TEST(test_base64url_2_base64_alloc) 811 | { 812 | unsigned char src[10] = {0x6f, 0x5b, 0x70, 0x29, 0x27, 0x2d, 0x3d, 0x40, 0x7e, 0x0}; 813 | struct _o_datum dat = {0, NULL}, dat_url = {0, NULL}, dat_conv = {0, NULL}; 814 | ck_assert_int_eq(o_base64_encode_alloc(src, 10, &dat), 1); 815 | ck_assert_int_gt(dat.size, 0); 816 | ck_assert_int_eq(o_base64url_encode_alloc(src, 10, &dat_url), 1); 817 | ck_assert_int_gt(dat_url.size, 0); 818 | ck_assert_int_ne(0, memcmp((const char *)dat.data, (const char *)dat_url.data, dat.size)); 819 | ck_assert_int_eq(o_base64url_2_base64_alloc(dat_url.data, dat_url.size, &dat_conv), 1); 820 | ck_assert_int_eq(dat.size, dat_conv.size); 821 | ck_assert_int_eq(0, memcmp(dat_conv.data, dat.data, dat_conv.size)); 822 | o_free(dat.data); 823 | o_free(dat_url.data); 824 | o_free(dat_conv.data); 825 | } 826 | END_TEST 827 | 828 | START_TEST(test_base64_2_base64url_alloc) 829 | { 830 | unsigned char src[10] = {0x6f, 0x5b, 0x70, 0x29, 0x27, 0x2d, 0x3d, 0x40, 0x7e, 0x0}; 831 | struct _o_datum dat = {0, NULL}, dat_url = {0, NULL}, dat_conv = {0, NULL}; 832 | ck_assert_int_eq(o_base64_encode_alloc(src, 10, &dat), 1); 833 | ck_assert_int_gt(dat.size, 0); 834 | ck_assert_int_eq(o_base64url_encode_alloc(src, 10, &dat_url), 1); 835 | ck_assert_int_gt(dat_url.size, 0); 836 | ck_assert_int_ne(0, memcmp((const char *)dat.data, (const char *)dat_url.data, dat.size)); 837 | ck_assert_int_eq(o_base64_2_base64url_alloc(dat.data, dat.size, &dat_conv), 1); 838 | ck_assert_int_eq(dat_url.size, dat_conv.size); 839 | ck_assert_int_eq(0, memcmp(dat_conv.data, dat_url.data, dat_conv.size)); 840 | o_free(dat.data); 841 | o_free(dat_url.data); 842 | o_free(dat_conv.data); 843 | } 844 | END_TEST 845 | 846 | START_TEST(test_str_null_or_empty) 847 | { 848 | char a[1] = {0}, * b = NULL, c[] = "test"; 849 | 850 | ck_assert_int_eq(1, o_strnullempty(a)); 851 | ck_assert_int_eq(1, o_strnullempty(b)); 852 | ck_assert_int_eq(0, o_strnullempty(c)); 853 | c[2] = '\0'; 854 | ck_assert_int_eq(0, o_strnullempty(c)); 855 | c[0] = '\0'; 856 | ck_assert_int_eq(1, o_strnullempty(c)); 857 | } 858 | END_TEST 859 | 860 | static Suite *orcania_suite(void) 861 | { 862 | Suite *s; 863 | TCase *tc_core; 864 | 865 | s = suite_create("Orcania tests string functions"); 866 | tc_core = tcase_create("test_orcania_str"); 867 | tcase_add_test(tc_core, test_str_replace); 868 | tcase_add_test(tc_core, test_o_strdup); 869 | tcase_add_test(tc_core, test_o_strndup); 870 | tcase_add_test(tc_core, test_o_strcmp); 871 | tcase_add_test(tc_core, test_o_strncmp); 872 | tcase_add_test(tc_core, test_o_strcasecmp); 873 | tcase_add_test(tc_core, test_o_strncasecmp); 874 | tcase_add_test(tc_core, test_o_strcpy); 875 | tcase_add_test(tc_core, test_o_strncpy); 876 | tcase_add_test(tc_core, test_o_strstr); 877 | tcase_add_test(tc_core, test_o_strnstr); 878 | tcase_add_test(tc_core, test_o_strchr); 879 | tcase_add_test(tc_core, test_o_strnchr); 880 | tcase_add_test(tc_core, test_o_strrchr); 881 | tcase_add_test(tc_core, test_o_strrnchr); 882 | tcase_add_test(tc_core, test_o_strlen); 883 | tcase_add_test(tc_core, test_msprintf); 884 | tcase_add_test(tc_core, test_mstrcatf); 885 | tcase_add_test(tc_core, test_trimwhitespace); 886 | tcase_add_test(tc_core, test_trimcharacter); 887 | tcase_add_test(tc_core, test_base64); 888 | tcase_add_test(tc_core, test_base64_more_test_cases); 889 | tcase_add_test(tc_core, test_base64url); 890 | tcase_add_test(tc_core, test_base64url_2_base64); 891 | tcase_add_test(tc_core, test_base64_2_base64url); 892 | tcase_add_test(tc_core, test_base64_len); 893 | tcase_add_test(tc_core, test_base64_alloc); 894 | tcase_add_test(tc_core, test_base64url_alloc); 895 | tcase_add_test(tc_core, test_base64_more_test_cases_alloc); 896 | tcase_add_test(tc_core, test_base64url_2_base64_alloc); 897 | tcase_add_test(tc_core, test_base64_2_base64url_alloc); 898 | tcase_add_test(tc_core, test_split_string); 899 | tcase_add_test(tc_core, test_string_array); 900 | tcase_add_test(tc_core, test_string_array_has_trimmed_value); 901 | tcase_add_test(tc_core, test_str_null_or_empty); 902 | tcase_set_timeout(tc_core, 30); 903 | suite_add_tcase(s, tc_core); 904 | 905 | return s; 906 | } 907 | 908 | int main(void) 909 | { 910 | int number_failed; 911 | Suite *s; 912 | SRunner *sr; 913 | 914 | s = orcania_suite(); 915 | sr = srunner_create(s); 916 | 917 | srunner_run_all(sr, CK_VERBOSE); 918 | number_failed = srunner_ntests_failed(sr); 919 | srunner_free(sr); 920 | 921 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 922 | } 923 | -------------------------------------------------------------------------------- /tools/base64url/.gitignore: -------------------------------------------------------------------------------- 1 | base64url 2 | valgrind*.txt 3 | -------------------------------------------------------------------------------- /tools/base64url/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # base64url: Base64Url encode or decode FILE, or standard input, to standard output. 3 | # 4 | # Makefile used to build the software 5 | # 6 | # Copyright 2021-2022 Nicolas Mora 7 | # 8 | # This program is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU GENERAL PUBLIC LICENSE 10 | # License as published by the Free Software Foundation; 11 | # version 3 of the License. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU GENERAL PUBLIC LICENSE for more details. 17 | # 18 | # You should have received a copy of the GNU General Public 19 | # License along with this program. If not, see . 20 | # 21 | CC=gcc 22 | ORCANIA_INCLUDE=../../include 23 | ORCANIA_LOCATION=../../src 24 | DESTDIR=/usr/local 25 | 26 | CFLAGS+=-Wall -Werror -Wextra -Wpedantic -Wconversion -I$(ORCANIA_INCLUDE) $(ADDITIONALFLAGS) $(CPPFLAGS) 27 | LIBS=-lc -lorcania -L$(ORCANIA_LOCATION) 28 | ORCANIA_LIBRARY=../../src/liborcania.so 29 | VALGRIND_COMMAND=valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --track-origins=yes 30 | 31 | all: base64url 32 | 33 | all: ADDITIONALFLAGS= -O3 34 | 35 | clean: 36 | rm -f *.o base64url *.b64 37 | 38 | debug: base64url 39 | 40 | debug: ADDITIONALFLAGS=-DDEBUG -g -O0 41 | 42 | $(ORCANIA_LIBRARY): 43 | cd $(ORCANIA_LOCATION) && $(MAKE) debug 44 | 45 | base64url: $(ORCANIA_LIBRARY) base64url.c 46 | $(CC) -o base64url $(CFLAGS) base64url.c $(LIBS) 47 | 48 | install: base64url 49 | mkdir -p $(DESTDIR)/bin $(DESTDIR)/man/man1/ 50 | install -m755 base64url $(DESTDIR)/bin 51 | install -m644 base64url.1 $(DESTDIR)/man/man1/ 52 | 53 | uninstall: 54 | rm -f $(DESTDIR)/bin/base64url 55 | 56 | manpage: base64url 57 | help2man ./base64url -s 1 -n "Base64Url encode or decode FILE, or standard input, to standard output." > base64url.1 58 | 59 | test: base64url 60 | echo plop | LD_LIBRARY_PATH=$(ORCANIA_LOCATION) $(VALGRIND_COMMAND) ./base64url 61 | LD_LIBRARY_PATH=$(ORCANIA_LOCATION) $(VALGRIND_COMMAND) ./base64url -f README.md 62 | LD_LIBRARY_PATH=$(ORCANIA_LOCATION) $(VALGRIND_COMMAND) ./base64url -f error || true 63 | echo ";error;" | LD_LIBRARY_PATH=$(ORCANIA_LOCATION) $(VALGRIND_COMMAND) ./base64url -d || true 64 | echo Z3J1dAo | LD_LIBRARY_PATH=$(ORCANIA_LOCATION) $(VALGRIND_COMMAND) ./base64url -d 65 | echo ZuJ1dAo | LD_LIBRARY_PATH=$(ORCANIA_LOCATION) $(VALGRIND_COMMAND) ./base64url -d -i 66 | echo plop | LD_LIBRARY_PATH=$(ORCANIA_LOCATION) $(VALGRIND_COMMAND) ./base64url -w 2 67 | -------------------------------------------------------------------------------- /tools/base64url/README.md: -------------------------------------------------------------------------------- 1 | # base64url: Base64Url encode or decode FILE, or standard input, to standard output. 2 | 3 | Copyright 2021-2022 Nicolas Mora 4 | 5 | This program is free software; you can redistribute it and/or modify it under the terms of the GPL3 License. 6 | 7 | ## Options 8 | 9 | Options available: 10 | 11 | ```shell 12 | -d, --decode 13 | Decode data 14 | -i, --ignore-garbage 15 | when decoding, ignore non-alphabet characters 16 | -w, --wrap 17 | wrap encoded lines after COLS character (default 76). Use 0 to disable line wrapping 18 | -f, --file 19 | Encode or decode FILE_NAME content - if this option is missing, red from stdin 20 | -h, --help 21 | display this help and exit 22 | -v, --version 23 | output version information and exit 24 | ``` 25 | -------------------------------------------------------------------------------- /tools/base64url/base64url.1: -------------------------------------------------------------------------------- 1 | .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1. 2 | .TH BASE64URL "1" "March 2022" "base64url 0.9" "User Commands" 3 | .SH NAME 4 | base64url \- Base64Url encode or decode FILE, or standard input, to standard output. 5 | .SH SYNOPSIS 6 | .B base64url 7 | [\fI\,OPTIONS\/\fR] 8 | .SH DESCRIPTION 9 | base64url \- Base64Url encode or decode FILE, or standard input, to standard output. 10 | .PP 11 | Version 0.9 12 | .SH COPYRIGHT 13 | Copyright 2021\-2022 Nicolas Mora 14 | .PP 15 | This program is free software; you can redistribute it and/or 16 | modify it under the terms of the GPL 3 17 | .PP 18 | Command\-line options: 19 | .PP 20 | \fB\-d\fR, \fB\-\-decode\fR 21 | .IP 22 | Decode data 23 | .PP 24 | \fB\-i\fR, \fB\-\-ignore\-garbage\fR 25 | .IP 26 | when decoding, ignore non\-alphabet characters 27 | .PP 28 | \fB\-w\fR, \fB\-\-wrap\fR 29 | .TP 30 | wrap encoded lines after COLS character (default 76). 31 | Use 0 to disable line wrapping 32 | .PP 33 | \fB\-f\fR, \fB\-\-file\fR 34 | .IP 35 | Encode or decode FILE_NAME content \- if this option is missing, red from stdin 36 | .PP 37 | \fB\-h\fR, \fB\-\-help\fR 38 | .IP 39 | display this help and exit 40 | .PP 41 | \fB\-v\fR, \fB\-\-version\fR 42 | .IP 43 | output version information and exit 44 | .PP 45 | .br 46 | Copyright 2021\-2022 Nicolas Mora 47 | This program is free software; you can redistribute it and/or 48 | modify it under the terms of the GPL 3 49 | .SH "SEE ALSO" 50 | The full documentation for 51 | .B base64url 52 | is maintained as a Texinfo manual. If the 53 | .B info 54 | and 55 | .B base64url 56 | programs are properly installed at your site, the command 57 | .IP 58 | .B info base64url 59 | .PP 60 | should give you access to the complete manual. 61 | -------------------------------------------------------------------------------- /tools/base64url/base64url.c: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * base64url: Base64Url encode or decode FILE, or standard input, to standard output. 4 | * 5 | * Copyright 2021-2022 Nicolas Mora 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU GENERAL PUBLIC LICENSE 9 | * License as published by the Free Software Foundation; 10 | * version 3 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU GENERAL PUBLIC LICENSE for more details. 16 | * 17 | * You should have received a copy of the GNU General Public 18 | * License along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #ifdef _MSC_VER 30 | #include 31 | #include 32 | typedef SSIZE_T ssize_t; 33 | #else 34 | #include 35 | #endif 36 | 37 | #define _BASE64URL_VERSION "0.9" 38 | 39 | #define ACTION_ENCODE 0 40 | #define ACTION_DECODE 1 41 | 42 | #define DEFAULT_WRAP 76 43 | 44 | #define SIZE 100 45 | 46 | static void print_output(const unsigned char * output, size_t output_len, size_t wrap, short int ignore) { 47 | size_t i; 48 | for (i=0; i\n"); 65 | fprintf(output, "\n"); 66 | fprintf(output, "This program is free software; you can redistribute it and/or\n"); 67 | fprintf(output, "modify it under the terms of the GPL 3\n"); 68 | fprintf(output, "\n"); 69 | fprintf(output, "Command-line options:\n"); 70 | fprintf(output, "\n"); 71 | fprintf(output, "-d, --decode\n"); 72 | fprintf(output, "\tDecode data\n"); 73 | fprintf(output, "-i, --ignore-garbage\n"); 74 | fprintf(output, "\twhen decoding, ignore non-alphabet characters\n"); 75 | fprintf(output, "-w, --wrap \n"); 76 | fprintf(output, "\twrap encoded lines after COLS character (default 76). Use 0 to disable line wrapping\n"); 77 | fprintf(output, "-f, --file \n"); 78 | fprintf(output, "\tEncode or decode FILE_NAME content - if this option is missing, red from stdin\n"); 79 | fprintf(output, "-h, --help\n"); 80 | fprintf(output, "\tdisplay this help and exit\n"); 81 | fprintf(output, "-v, --version\n"); 82 | fprintf(output, "\toutput version information and exit\n"); 83 | } 84 | 85 | static unsigned char * get_file_content(const char * file_path, size_t * length) { 86 | unsigned char * buffer = NULL; 87 | size_t res; 88 | FILE * f; 89 | 90 | f = fopen (file_path, "rb"); 91 | if (f) { 92 | fseek (f, 0, SEEK_END); 93 | *length = (size_t)ftell (f); 94 | fseek (f, 0, SEEK_SET); 95 | buffer = o_malloc(((*length)+1)*sizeof(char)); 96 | if (buffer) { 97 | res = fread (buffer, 1, *length, f); 98 | if (res != *length) { 99 | *length = 0; 100 | fprintf(stderr, "fread warning, reading %zu while expecting %zu", res, *length); 101 | } 102 | } 103 | fclose (f); 104 | } else { 105 | fprintf(stderr, "error opening file %s\n", file_path); 106 | } 107 | 108 | return buffer; 109 | } 110 | 111 | static unsigned char * get_stdin_content(size_t * length) { 112 | unsigned char * out = NULL, buffer[SIZE]; 113 | ssize_t read_length; 114 | 115 | *length = 0; 116 | while ((read_length = read(0, buffer, SIZE)) > 0) { 117 | out = o_realloc(out, (*length)+(size_t)read_length+1); 118 | memcpy(out+(*length), buffer, (size_t)read_length); 119 | (*length) += (size_t)read_length; 120 | out[(*length)] = '\0'; 121 | } 122 | if ((*length) && (out[(*length)-1] == '\n' || out[(*length)-1] == '\r')) { 123 | out[(*length)-1] = '\0'; 124 | (*length)--; 125 | } 126 | return out; 127 | } 128 | 129 | int main(int argc, char ** argv) { 130 | short int action = ACTION_ENCODE, ignore = 0; 131 | unsigned long int wrap = DEFAULT_WRAP; 132 | size_t s_wrap = DEFAULT_WRAP; 133 | const char * short_options = "d::i::w:f:v::h"; 134 | int next_option, ret = 0, exit_loop = 0; 135 | char * file = NULL, * endptr = NULL, * tmp = NULL; 136 | unsigned char * input = NULL, * output = NULL; 137 | size_t input_len = 0, output_len = 0; 138 | static const struct option long_options[]= { 139 | {"decode", no_argument, NULL, 'd'}, 140 | {"ignore-garbage", no_argument, NULL, 'i'}, 141 | {"wrap", required_argument, NULL, 'w'}, 142 | {"file", required_argument, NULL, 'f'}, 143 | {"version", no_argument, NULL, 'v'}, 144 | {"help", no_argument, NULL, 'h'}, 145 | {NULL, 0, NULL, 0} 146 | }; 147 | 148 | do { 149 | next_option = getopt_long(argc, argv, short_options, long_options, NULL); 150 | 151 | switch (next_option) { 152 | case 'd': 153 | action = ACTION_DECODE; 154 | break; 155 | case 'i': 156 | ignore = 1; 157 | break; 158 | case 'w': 159 | wrap = strtoul(optarg, &endptr, 10); 160 | if (*endptr == '\0' && wrap <= SIZE_MAX) { 161 | s_wrap = (size_t)wrap; 162 | } else { 163 | print_help(stderr, argv[0]); 164 | exit_loop = 1; 165 | ret = 1; 166 | } 167 | break; 168 | case 'f': 169 | o_free(file); 170 | file = o_strdup(optarg); 171 | break; 172 | case 'v': 173 | fprintf(stdout, "%s %s\n", argv[0], _BASE64URL_VERSION); 174 | fprintf(stdout, "Copyright 2021-2022 Nicolas Mora \n"); 175 | fprintf(stdout, "This program is free software; you can redistribute it and/or\n"); 176 | fprintf(stdout, "modify it under the terms of the GPL 3\n"); 177 | exit_loop = 1; 178 | break; 179 | case 'h': 180 | print_help(stdout, argv[0]); 181 | exit_loop = 1; 182 | break; 183 | default: 184 | break; 185 | } 186 | } while (next_option != -1 && !exit_loop); 187 | 188 | if (!exit_loop) { 189 | if (file != NULL) { 190 | input = get_file_content(file, &input_len); 191 | } else { 192 | input = get_stdin_content(&input_len); 193 | } 194 | 195 | if (input != NULL && input_len) { 196 | if (action == ACTION_ENCODE) { 197 | if (o_base64url_encode(input, input_len, NULL, &output_len)) { 198 | if (output_len) { 199 | if ((output = o_malloc(output_len+4)) != NULL) { 200 | if (o_base64url_encode(input, input_len, output, &output_len)) { 201 | print_output(output, output_len, s_wrap, ignore); 202 | } else { 203 | fprintf(stderr, "%s: Error encoding\n", argv[0]); 204 | } 205 | } else { 206 | fprintf(stderr, "%s: Error encoding\n", argv[0]); 207 | } 208 | } else { 209 | fprintf(stderr, "%s: Error encoding\n", argv[0]); 210 | } 211 | } else { 212 | fprintf(stderr, "%s: Error encoding\n", argv[0]); 213 | } 214 | } else { 215 | tmp = str_replace((const char *)input, " ", ""); 216 | o_free(input); 217 | input = (unsigned char *)tmp; 218 | tmp = str_replace((const char *)input, "\n", ""); 219 | o_free(input); 220 | input = (unsigned char *)tmp; 221 | tmp = str_replace((const char *)input, "\t", ""); 222 | o_free(input); 223 | input = (unsigned char *)tmp; 224 | tmp = str_replace((const char *)input, "\v", ""); 225 | o_free(input); 226 | input = (unsigned char *)tmp; 227 | tmp = str_replace((const char *)input, "\f", ""); 228 | o_free(input); 229 | input = (unsigned char *)tmp; 230 | tmp = str_replace((const char *)input, "\r", ""); 231 | o_free(input); 232 | input = (unsigned char *)tmp; 233 | input_len = o_strlen((const char *)input); 234 | if (o_base64url_decode(input, input_len, NULL, &output_len)) { 235 | if (output_len) { 236 | if ((output = o_malloc(output_len+4)) != NULL) { 237 | if (o_base64url_decode(input, input_len, output, &output_len)) { 238 | print_output(output, output_len, 0, ignore); 239 | } else { 240 | fprintf(stderr, "%s: invalid input\n", argv[0]); 241 | ret = 1; 242 | } 243 | } else { 244 | fprintf(stderr, "%s: Error decoding\n", argv[0]); 245 | ret = 1; 246 | } 247 | } else { 248 | fprintf(stderr, "%s: invalid input\n", argv[0]); 249 | ret = 1; 250 | } 251 | } else { 252 | fprintf(stderr, "%s: invalid input\n", argv[0]); 253 | ret = 1; 254 | } 255 | } 256 | } else { 257 | fprintf(stderr, "-- Error no input --\n"); 258 | print_help(stderr, argv[0]); 259 | ret = 1; 260 | } 261 | o_free(input); 262 | o_free(output); 263 | } 264 | o_free(file); 265 | return ret; 266 | } 267 | --------------------------------------------------------------------------------