diff options
-rw-r--r-- | .github/dependabot.yml | 15 | ||||
-rw-r--r-- | .github/workflows/build-and-test.yml | 116 | ||||
-rw-r--r-- | .travis.yml | 86 | ||||
-rw-r--r-- | CMakeLists.txt | 146 | ||||
-rw-r--r-- | ChangeLog | 41 | ||||
-rw-r--r-- | README.md | 11 | ||||
-rw-r--r-- | THANKS | 6 | ||||
-rw-r--r-- | appveyor.yml | 1 | ||||
-rw-r--r-- | doc/Mainpage.txt | 41 | ||||
-rw-r--r-- | include/uriparser/Uri.h | 2 | ||||
-rw-r--r-- | include/uriparser/UriBase.h | 2 | ||||
-rw-r--r-- | include/uriparser/UriDefsConfig.h | 8 | ||||
-rw-r--r-- | include/uriparser/UriDefsUnicode.h | 2 | ||||
-rw-r--r-- | liburiparser.pc.in | 6 | ||||
-rw-r--r-- | src/UriCommon.c | 96 | ||||
-rw-r--r-- | src/UriCommon.h | 2 | ||||
-rw-r--r-- | test/MemoryManagerSuite.cpp | 4 | ||||
-rw-r--r-- | test/test.cpp | 57 |
18 files changed, 430 insertions, 212 deletions
diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..b149019 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +# Copyright (C) 2021 Sebastian Pipping <sebastian@pipping.org> +# Licensed under the MIT license + +version: 2 +updates: + + - package-ecosystem: "github-actions" + commit-message: + include: "scope" + prefix: "Actions" + directory: "/" + labels: + - "enhancement" + schedule: + interval: "weekly" diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..ba5cb84 --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,116 @@ +# Copyright (C) 2021 Sebastian Pipping <sebastian@pipping.org> +# Licensed under the MIT license + +name: Build and test + +on: + pull_request: + push: + schedule: + - cron: '0 4 * * 5' # Every Friday at 4am + +jobs: + build_and_test: + name: Build and test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2.3.4 + + - name: Add Clang/LLVM repositories + run: |- + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main' + + - name: Install build dependencies + run: |- + sudo apt-get install --yes --no-install-recommends -V \ + clang-11 \ + cmake \ + doxygen \ + graphviz \ + llvm-11 \ + lzip \ + qhelpgenerator-qt5 \ + qtchooser + + - name: Build, test and install + run: |- + sed 's,:,\n,g' <<<"${PATH}" + clang --version + + GTEST_VERSION=1.8.1 + GTEST_PREFIX=~/.local/ + + wget https://github.com/google/googletest/archive/release-${GTEST_VERSION}.tar.gz + tar xf release-${GTEST_VERSION}.tar.gz + ( + cd googletest-release-${GTEST_VERSION}/ + cmake \ + -DBUILD_SHARED_LIBS=ON \ + -DCVF_VERSION=${GTEST_VERSION} \ + -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} \ + . + make + make install + ) + + mkdir build + pushd build + compile_flags=( + -pipe + + -O1 + -g + -fsanitize=address,undefined,leak + -fno-sanitize-recover=all + -fno-omit-frame-pointer + + -Wall + -Wextra + -pedantic + ) + CFLAGS="${compile_flags[*]} -std=c89" + CXXFLAGS="${compile_flags[*]} -std=c++98" + LDFLAGS='-g -fsanitize=address' + cmake_args=( + -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} + + -Wdev + -Werror=dev + -Wdeprecated + -Werror=deprecated + + -DCMAKE_C_COMPILER=clang-11 + -DCMAKE_CXX_COMPILER=clang++-11 + -DCMAKE_C_FLAGS="${CFLAGS}" + -DCMAKE_CXX_FLAGS="${CXXFLAGS}" + -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" + -DCMAKE_MODULE_LINKER_FLAGS="${LDFLAGS}" + -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}" + + -DURIPARSER_WARNINGS_AS_ERRORS=ON + ) + cmake "${cmake_args[@]}" -DCMAKE_INSTALL_INCLUDEDIR=include123 .. + + make VERBOSE=1 all + + make VERBOSE=1 test ARGS=--verbose + cat Testing/Temporary/LastTest.log + + make install + make DESTDIR="${PWD}"/ROOT/ install + find ROOT | sort + + ./doc/release.sh + popd + pushd cmake/test_find_package + cmake "${cmake_args[@]}" . + make VERBOSE=1 + ./hello + popd + + git fetch --tags --unshallow origin # for "git describe" in make-distcheck.sh + + ./make-distcheck.sh -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} # without AddressSanitizer + + ! git status | fgrep -A100 'Untracked files:' # works best at the very end diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0096384..0000000 --- a/.travis.yml +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (C) 2018 Sebastian Pipping <sebastian@pipping.org> -# Licensed under the MIT license - -language: cpp -dist: xenial - -addons: - apt: - sources: - # Clang 8: - - llvm-toolchain-xenial-8 - - ubuntu-toolchain-r-test - packages: - - clang-8 - - cmake - - lzip - # Documentation: - - doxygen - - graphviz - - qt4-dev-tools - - qtchooser - -script: - - set -e - - GTEST_VERSION=1.8.1 - ; GTEST_PREFIX=~/.local/ - ; wget https://github.com/google/googletest/archive/release-${GTEST_VERSION}.tar.gz - && tar xf release-${GTEST_VERSION}.tar.gz - && ( cd googletest-release-${GTEST_VERSION}/ - && cmake - -DBUILD_SHARED_LIBS=ON - -DCVF_VERSION=${GTEST_VERSION} - -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} - . - && make - && make install ) - - mkdir build - - pushd build - - compile_flags=( - -pipe - - -O1 - -g - -fsanitize=address - -fno-omit-frame-pointer - - -Wall - -Wextra - -pedantic - ) - && CFLAGS="${compile_flags[*]} -std=c89" - && CXXFLAGS="${compile_flags[*]} -std=c++98" - && LDFLAGS='-g -fsanitize=address' - && cmake_args=( - -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} - - -Wdev - -Werror=dev - -Wdeprecated - -Werror=deprecated - - -DCMAKE_C_COMPILER=clang-8 - -DCMAKE_CXX_COMPILER=clang++-8 - -DCMAKE_C_FLAGS="${CFLAGS}" - -DCMAKE_CXX_FLAGS="${CXXFLAGS}" - -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" - -DCMAKE_MODULE_LINKER_FLAGS="${LDFLAGS}" - -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}" - ) - && cmake "${cmake_args[@]}" -DCMAKE_INSTALL_INCLUDEDIR=include123 .. # -Werror would fail checks! - - make VERBOSE=1 C_FLAGS="${CFLAGS} -fPIC -Werror" CXX_FLAGS="${CXXFLAGS} -Werror" all - - make VERBOSE=1 C_FLAGS="${CFLAGS} -fPIC -Werror" CXX_FLAGS="${CXXFLAGS} -Werror" test ARGS=--verbose - - cat Testing/Temporary/LastTest.log - - make install - - ./doc/release.sh - - make DESTDIR="${PWD}"/ROOT/ install - - find ROOT | sort - - popd - - pushd cmake/test_find_package - - cmake "${cmake_args[@]}" . - - make VERBOSE=1 - - ./hello - - popd - - git fetch --tags --unshallow origin # for "git describe" in make-distcheck.sh - - ./make-distcheck.sh -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} # without AddressSanitizer - - "! git status | fgrep -A100 'Untracked files:' # works best at the very end" diff --git a/CMakeLists.txt b/CMakeLists.txt index 70088b1..4b1ce44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,14 +38,14 @@ cmake_minimum_required(VERSION 3.3) project(uriparser VERSION - 0.9.4 + 0.9.5 LANGUAGES C ) -# See https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +# See https://verbump.de/ for what these numbers do set(URIPARSER_SO_CURRENT 1) -set(URIPARSER_SO_REVISION 27) +set(URIPARSER_SO_REVISION 28) set(URIPARSER_SO_AGE 0) include(CheckCCompilerFlag) @@ -65,6 +65,7 @@ option(URIPARSER_BUILD_TOOLS "Build tools (e.g. CLI \"uriparse\")" ON) option(URIPARSER_BUILD_CHAR "Build code supporting data type 'char'" ON) option(URIPARSER_BUILD_WCHAR_T "Build code supporting data type 'wchar_t'" ON) option(URIPARSER_ENABLE_INSTALL "Enable installation of uriparser" ON) +option(URIPARSER_WARNINGS_AS_ERRORS "Treat all compiler warnings as errors" OFF) set(URIPARSER_MSVC_RUNTIME "" CACHE STRING "Use of specific runtime library (/MT /MTd /MD /MDd) with MSVC") if(NOT URIPARSER_BUILD_CHAR AND NOT URIPARSER_BUILD_WCHAR_T) @@ -103,6 +104,14 @@ if(URIPARSER_COMPILER_SUPPORTS_VISIBILITY) set(URIPARSER_EXTRA_COMPILE_FLAGS "${URIPARSER_EXTRA_COMPILE_FLAGS} -fvisibility=hidden") endif() +if(URIPARSER_WARNINGS_AS_ERRORS) + if(MSVC) + add_definitions(/WX) + else() + set(URIPARSER_EXTRA_COMPILE_FLAGS "${URIPARSER_EXTRA_COMPILE_FLAGS} -Werror") + endif() +endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${URIPARSER_EXTRA_COMPILE_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${URIPARSER_EXTRA_COMPILE_FLAGS}") @@ -111,40 +120,40 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${URIPARSER_EXTRA_COMPILE_FLAGS}") # check_symbol_exists(wprintf wchar.h HAVE_WPRINTF) check_function_exists(reallocarray HAVE_REALLOCARRAY) # no luck with CheckSymbolExists -configure_file(src/UriConfig.h.in config.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/UriConfig.h.in config.h) # # C library # set(API_HEADER_FILES - include/uriparser/UriBase.h - include/uriparser/UriDefsAnsi.h - include/uriparser/UriDefsConfig.h - include/uriparser/UriDefsUnicode.h - include/uriparser/Uri.h - include/uriparser/UriIp4.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/UriBase.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/UriDefsAnsi.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/UriDefsConfig.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/UriDefsUnicode.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/Uri.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/UriIp4.h ) set(LIBRARY_CODE_FILES - src/UriCommon.c - src/UriCommon.h - src/UriCompare.c - src/UriEscape.c - src/UriFile.c - src/UriIp4Base.c - src/UriIp4Base.h - src/UriIp4.c - src/UriMemory.c - src/UriMemory.h - src/UriNormalizeBase.c - src/UriNormalizeBase.h - src/UriNormalize.c - src/UriParseBase.c - src/UriParseBase.h - src/UriParse.c - src/UriQuery.c - src/UriRecompose.c - src/UriResolve.c - src/UriShorten.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriCommon.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriCommon.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriCompare.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriEscape.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriFile.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriIp4Base.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriIp4Base.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriIp4.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriMemory.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriMemory.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriNormalizeBase.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriNormalizeBase.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriNormalize.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriParseBase.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriParseBase.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriParse.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriQuery.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriRecompose.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriResolve.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/UriShorten.c ) add_library(uriparser @@ -157,7 +166,10 @@ if(NOT MSVC) set_property(TARGET uriparser PROPERTY VERSION ${URIPARSER_SO_CURRENT_MINUS_AGE}.${URIPARSER_SO_AGE}.${URIPARSER_SO_REVISION}) set_property(TARGET uriparser PROPERTY SOVERSION ${URIPARSER_SO_CURRENT_MINUS_AGE}) if(WIN32) - set_property(TARGET uriparser PROPERTY SUFFIX "-${URIPARSER_SO_CURRENT_MINUS_AGE}${CMAKE_SHARED_LIBRARY_SUFFIX}") + set_target_properties(uriparser PROPERTIES + OUTPUT_NAME uriparser + RUNTIME_OUTPUT_NAME uriparser-${URIPARSER_SO_CURRENT_MINUS_AGE} + ARCHIVE_OUTPUT_NAME uriparser) endif() endif() @@ -214,7 +226,7 @@ uriparser_install( # if(URIPARSER_BUILD_TOOLS) add_executable(uriparse - tool/uriparse.c + ${CMAKE_CURRENT_SOURCE_DIR}/tool/uriparse.c ) target_link_libraries(uriparse PUBLIC uriparser) @@ -260,10 +272,10 @@ if(URIPARSER_BUILD_TESTS) find_package(GTest 1.8.0 REQUIRED) add_executable(testrunner - test/FourSuite.cpp - test/MemoryManagerSuite.cpp - test/test.cpp - test/VersionSuite.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/FourSuite.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/MemoryManagerSuite.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/VersionSuite.cpp # These library code files have non-public symbols that the test suite # needs to link to, so they appear here as well: @@ -290,6 +302,15 @@ if(URIPARSER_BUILD_TESTS) ${GTEST_BOTH_LIBRARIES} ) + # NOTE: uriparser does not use pthreads itself but gtest does + find_package(Threads REQUIRED) + target_link_libraries(testrunner PRIVATE Threads::Threads) + + if(MSVC) + # Specify unwind semantics so that MSVC knowns how to handle exceptions + target_compile_options(testrunner PRIVATE /EHsc) + endif() + add_test( NAME test @@ -305,11 +326,20 @@ endif() # if(URIPARSER_BUILD_DOCS) find_package(Doxygen REQUIRED dot doxygen) - find_program(QHG_LOCATION - NAMES - qhelpgenerator - qhelpgenerator-qt5 # e.g. CentOS 7 - ) + + set(QHG_LOCATION "" CACHE FILEPATH "Path to qhelpgenerator program (default: auto-detect)") + if(NOT QHG_LOCATION) + find_package(Qt5Help QUIET) + if(TARGET Qt5::qhelpgenerator) + get_target_property(QHG_LOCATION Qt5::qhelpgenerator LOCATION) + mark_as_advanced(Qt5Core_DIR) + mark_as_advanced(Qt5Gui_DIR) + mark_as_advanced(Qt5Help_DIR) + mark_as_advanced(Qt5Sql_DIR) + mark_as_advanced(Qt5Widgets_DIR) + endif() + endif() + include(FindHTMLHelp) # Generate Doxyfile @@ -323,8 +353,8 @@ if(URIPARSER_BUILD_DOCS) else() set(GENERATE_QHP NO) endif() - configure_file(doc/Doxyfile.in doc/Doxyfile @ONLY) - configure_file(doc/release.sh.in doc/release.sh @ONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in doc/Doxyfile @ONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/release.sh.in doc/release.sh @ONLY) add_custom_target(doc ALL @@ -358,7 +388,7 @@ endif() # CMake files for find_package(uriparser [..] CONFIG [..]) # configure_package_config_file( - cmake/uriparser-config.cmake.in + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/uriparser-config.cmake.in cmake/uriparser-config.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/uriparser-${PROJECT_VERSION}/ @@ -393,7 +423,7 @@ uriparser_install( # pkg-config file # if(NOT MSVC) - configure_file(liburiparser.pc.in liburiparser.pc @ONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/liburiparser.pc.in liburiparser.pc @ONLY) uriparser_install( FILES ${CMAKE_CURRENT_BINARY_DIR}/liburiparser.pc @@ -408,13 +438,25 @@ endif() message(STATUS "===========================================================================") message(STATUS "") message(STATUS "Configuration") -message(STATUS " Prefix ............... ${CMAKE_INSTALL_PREFIX}") -message(STATUS " Shared libraries ..... ${BUILD_SHARED_LIBS}") -message(STATUS " Code for char * ...... ${URIPARSER_BUILD_CHAR}") -message(STATUS " Code for wchar_t * ... ${URIPARSER_BUILD_WCHAR_T}") -message(STATUS " Tools ................ ${URIPARSER_BUILD_TOOLS}") -message(STATUS " Test suite ........... ${URIPARSER_BUILD_TESTS}") -message(STATUS " Documentation ........ ${URIPARSER_BUILD_DOCS}") +message(STATUS " Build type ............. ${CMAKE_BUILD_TYPE}") +message(STATUS " Shared libraries ....... ${BUILD_SHARED_LIBS}") +message(STATUS " Compiler flags") +message(STATUS " C .................... ${CMAKE_C_FLAGS}") +message(STATUS " C++ .................. ${CMAKE_CXX_FLAGS}") +message(STATUS " Linker flags") +message(STATUS " Executable ........... ${CMAKE_EXE_LINKER_FLAGS}") +message(STATUS " Module ............... ${CMAKE_MODULE_LINKER_FLAGS}") +message(STATUS " Shared ............... ${CMAKE_SHARED_LINKER_FLAGS}") +message(STATUS " Paths") +message(STATUS " Prefix ............... ${CMAKE_INSTALL_PREFIX}") +message(STATUS " qhelpgenerator ....... ${QHG_LOCATION}") +message(STATUS "") +message(STATUS " Features") +message(STATUS " Code for char * ...... ${URIPARSER_BUILD_CHAR}") +message(STATUS " Code for wchar_t * ... ${URIPARSER_BUILD_WCHAR_T}") +message(STATUS " Tools ................ ${URIPARSER_BUILD_TOOLS}") +message(STATUS " Test suite ........... ${URIPARSER_BUILD_TESTS}") +message(STATUS " Documentation ........ ${URIPARSER_BUILD_DOCS}") message(STATUS "") if(CMAKE_GENERATOR STREQUAL "Unix Makefiles") message(STATUS "Continue with") @@ -2,6 +2,43 @@ NOTE: uriparser is looking for help with a few things: https://github.com/uriparser/uriparser/labels/help%20wanted If you can help, please get in touch. Thanks! +2021-03-18 -- 0.9.5 + + * Fixed: Fix a bug regarding section "5.2.4. Remove Dot Segments" + of RFC 3986 that affected both normalization and reference resolution + with regard to trailing slashes (GitHub #92, #97) + Thanks to Dan Pape for the report! + * Fixed: MinGW: Fix name of static library (GitHub #90) + Thanks to SpaceIm for the patch and Sandro Mani for review! + * Fixed: Use correct inline marker "__forceinline" for Intel C++ Compiler + (GitHub #93) + Thanks to jensenrichardson for the patch! + * Fixed: Link against pthreads for (default) -DURIPARSER_BUILD_TESTS=ON + (GitHub #99, #100) + * Fixed: When integrated using CMake function add_subdirectory, installation + could fail due to lack of prefix ${CMAKE_CURRENT_SOURCE_DIR} (GitHub #98) + Thanks for the patch to Shehzan Mohammed! + * Fixed: Addressed MSVC compile warning about lack of /EHsc when compiling + the C++ test suite code (GitHub #102) + * Fixed: Stopped misadvertising wide characters as Unicode support + (GitHub #104) + * Added: CMake option URIPARSER_WARNINGS_AS_ERRORS=(ON|OFF) + to turn compile warnings into errors, defaults to "OFF" (GitHub #102) + * Improved: pkg-config: Use ${prefix} and ${exec_prefix} to ease + overriding variables using --define-variable=NAME=VALUE, + e.g. as done on OpenWRT (GitHub #91) + Thanks to Karel Kočí for the pull request! + * Improved: Auto-detection of the qhelpgenerator command based on CMake + package "Qt5Help" when available. CMake option "QHG_LOCATION" can still + be used to enforce a specific location (GitHub #103) + Thanks for his help to Andreas Sturmlechner! + * Improved: Make documentation use pkg-config in example on how to + check for uriparser from within configure.ac (GNU Autoconf) + (GitHub #37, #106) + * Improved: In testing code, add a missing 'extern "C"' (GitHub #109) + Thanks to Jørgen Ibsen for the patch! + * Soname: 1:28:0 — see https://verbump.de/ for what these numbers do + 2020-05-31 -- 0.9.4 * Fixed: testrunner: No longer crashes when compiled with NDEBUG (GitHub #67) @@ -22,7 +59,7 @@ NOTE: uriparser is looking for help with a few things: * Added: CMake option URIPARSER_ENABLE_INSTALL to toggle installation of files, defaults to "ON" (GitHub #74, #75) Thanks to Scott Donelan for the patch! - * Soname: 1:26:0 + * Soname: 1:27:0 2019-04-28 -- 0.9.3 @@ -487,7 +524,7 @@ NOTE: uriparser is looking for help with a few things: 2007-03-26 -- 0.3.0 * Added: New API, old marked deprecated - * Added: Unicode support (think wchar_t) + * Added: Added support for wide strings (think wchar_t) * Added: Doxygen code documentation * Added: Test suite using CppTest * Changed: Library code is now licensed under the new BSD license. @@ -1,4 +1,4 @@ -[![Travis CI Build Status](https://travis-ci.org/uriparser/uriparser.svg?branch=master)](https://travis-ci.org/uriparser/uriparser) +[![Build and test](https://github.com/uriparser/uriparser/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/uriparser/uriparser/actions/workflows/build-and-test.yml) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/uriparseradmin/uriparser?svg=true)](https://ci.appveyor.com/project/uriparseradmin/uriparser) @@ -10,7 +10,7 @@ URI parsing and handling library written in C89 ("ANSI C"). uriparser is cross-platform, fast, -supports Unicode, and +supports both `char` and `wchar_t`, and is licensed under the [New BSD license](https://github.com/uriparser/uriparser/blob/master/COPYING). To learn more about uriparser, @@ -55,8 +55,8 @@ CMAKE_BUILD_TYPE:STRING= // Install path prefix, prepended onto install directories. CMAKE_INSTALL_PREFIX:PATH=/usr/local -// Path to a program. -QHG_LOCATION:FILEPATH=/usr/bin/qhelpgenerator +// Path to qhelpgenerator program (default: auto-detect) +QHG_LOCATION:FILEPATH= // Build code supporting data type 'char' URIPARSER_BUILD_CHAR:BOOL=ON @@ -78,4 +78,7 @@ URIPARSER_ENABLE_INSTALL:BOOL=ON // Use of specific runtime library (/MT /MTd /MD /MDd) with MSVC URIPARSER_MSVC_RUNTIME:STRING= + +// Treat all compiler warnings as errors +URIPARSER_WARNINGS_AS_ERRORS:BOOL=OFF ``` @@ -4,9 +4,11 @@ Adeodato Sim Adrian Manrique Alexander Klink Arkadiusz Miskiewicz +Andreas Sturmlechner Blair Sadewitz Chris Hills Cristian Rodriguez +Dan Pape Daniel Chapiesky Daniel Solano Gómez David Demelier @@ -22,11 +24,13 @@ Friedrich Delgado Friedrichs Gary Mazzaferro Graham Percival Harvey Vrsalovic +jensenrichardson Jerome Custodio Joel Cunningham Jørgen Ibsen Juan Pablo Gonzlez Tognarelli KangLin +Karel Kočí Kouhei Sutou Kurt Schwehr Marc Novakowski @@ -51,6 +55,8 @@ Sandro Mani Schrijvers Luc Scott Donelan Sezai Tekin +Shehzan Mohammed +SpaceIm Valentin Haenel Vitaly Lipatov Yang Yu diff --git a/appveyor.yml b/appveyor.yml index 09890c0..7e36cdb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -88,6 +88,7 @@ before_build: -DGTEST_ROOT=googletest-release-%GTEST_VERSION%/googletest -DURIPARSER_BUILD_DOCS=OFF -DURIPARSER_MSVC_RUNTIME=/MT + -DURIPARSER_WARNINGS_AS_ERRORS=ON .. build: diff --git a/doc/Mainpage.txt b/doc/Mainpage.txt index bb5723c..19d8115 100644 --- a/doc/Mainpage.txt +++ b/doc/Mainpage.txt @@ -10,8 +10,8 @@ * - <a href="#shortening">Creating References</a> * - <a href="#filenames">Filenames and URIs</a> * - <a href="#normalization">Normalizing URIs</a> - * - <a href="#querystrings">Working with query strings</a> - * - <a href="#chartypes">Ansi and Unicode</a> + * - <a href="#querystrings">Working with Query Strings</a> + * - <a href="#chartypes">Narrow Strings and Wide Strings</a> * - <a href="#autoconf">Autoconf Check</a> * * @@ -226,7 +226,7 @@ * @endcode * * - * @section querystrings Working with query strings + * @section querystrings Working with Query Strings * <a href="http://tools.ietf.org/html/rfc3986" target="_blank">RFC 3986</a> * itself does not understand the query part of a URI as a list of key/value pairs. * But HTML 2.0 does and defines a media type <i>application/x-www-form-urlencoded</i> @@ -281,37 +281,20 @@ * @endcode * * - * @section chartypes Ansi and Unicode + * @section chartypes Narrow Strings and Wide Strings * uriparser comes with two versions of every structure and function: - * one handling Ansi text (char *) and one working with Unicode text (wchar_t *), + * one handling narrow strings (<code>char *</code>) and one working with wide strings (<code>wchar_t *</code>), * for instance - * - uriParseSingleUriA() for Ansi and - * - uriParseSingleUriW() for Unicode. + * - uriParseSingleUriA() for <code>char *</code> + * - uriParseSingleUriW() for <code>wchar_t *</code>. * - * This tutorial only shows the usage of the Ansi editions but - * their Unicode counterparts work in the very same way. + * This tutorial only shows the usage of the narrow string editions but + * their wide string counterparts work in the very same way. * * * @section autoconf Autoconf Check * You can use the code below to make <c>./configure</c> test for presence - * of uriparser 0.6.4 or later. - * - *<div class="fragment"><pre class="fragment">URIPARSER_MISSING=<span class="stringliteral">"Please install uriparser 0.9.0 or later. - * On a Debian-based system enter 'sudo apt-get install liburiparser-dev'."</span> - *AC_CHECK_LIB(uriparser, uriParseSingleUriA,, AC_MSG_ERROR(${URIPARSER_MISSING})) - *AC_CHECK_HEADER(uriparser/Uri.h,, AC_MSG_ERROR(${URIPARSER_MISSING})) - *<b></b> - *URIPARSER_TOO_OLD=<span class="stringliteral">"uriparser 0.9.0 or later is required, your copy is too old."</span> - *AC_COMPILE_IFELSE([ - *<span class="preprocessor">\#include <uriparser/Uri.h> - *\#if (defined(URI_VER_MAJOR) && defined(URI_VER_MINOR) && defined(URI_VER_RELEASE) \\<b></b> - *&& ((URI_VER_MAJOR > 0) \\<b></b> - *|| ((URI_VER_MAJOR == 0) && (URI_VER_MINOR > 9)) \\<b></b> - *|| ((URI_VER_MAJOR == 0) && (URI_VER_MINOR == 9) && (URI_VER_RELEASE >= 0)) \\<b></b> - *))</span> - *<span class="comment"><b></b>/<b></b>* FINE *<b></b>/</span> - *<span class="preprocessor">\#else - *\# error uriparser not recent enough - *\#endif</span> - *],,AC_MSG_ERROR(${URIPARSER_TOO_OLD}))</pre></div> + * of uriparser 0.9.0 or later. + * + *<div class="fragment"><pre class="fragment">PKG_CHECK_MODULES([URIPARSER], [liburiparser >= 0.9.0], [], [])</pre></div> */ diff --git a/include/uriparser/Uri.h b/include/uriparser/Uri.h index e822d33..44d8760 100644 --- a/include/uriparser/Uri.h +++ b/include/uriparser/Uri.h @@ -1,4 +1,4 @@ -/* 520782e6334595efe9dee874cfa720d7b49de30fa51caba8bce352e55f521ee1 (0.9.4+) +/* 6db8b5726a796167bb96b3d83ff9ac6792a01474dbe3778deb3c2a25d60b3693 (0.9.5+) * * uriparser - RFC 3986 URI parsing library * diff --git a/include/uriparser/UriBase.h b/include/uriparser/UriBase.h index 4147882..565abcf 100644 --- a/include/uriparser/UriBase.h +++ b/include/uriparser/UriBase.h @@ -55,7 +55,7 @@ /* Version */ #define URI_VER_MAJOR 0 #define URI_VER_MINOR 9 -#define URI_VER_RELEASE 4 +#define URI_VER_RELEASE 5 #define URI_VER_SUFFIX_ANSI "" #define URI_VER_SUFFIX_UNICODE URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI) diff --git a/include/uriparser/UriDefsConfig.h b/include/uriparser/UriDefsConfig.h index 392229a..51bc93e 100644 --- a/include/uriparser/UriDefsConfig.h +++ b/include/uriparser/UriDefsConfig.h @@ -59,15 +59,15 @@ /* No encoding at all */ # error URI_NO_ANSI and URI_NO_UNICODE cannot go together. # else -/* Unicode only */ +/* Wide strings only */ # define URI_ENABLE_UNICODE 1 # endif #else # ifdef URI_NO_UNICODE -/* ANSI only */ +/* Narrow strings only */ # define URI_ENABLE_ANSI 1 # else -/* Both ANSI and Unicode */ +/* Both narrow and wide strings */ # define URI_ENABLE_ANSI 1 # define URI_ENABLE_UNICODE 1 # endif @@ -82,7 +82,7 @@ /* Intel C/C++ */ /* http://predef.sourceforge.net/precomp.html#sec20 */ /* http://www.intel.com/support/performancetools/c/windows/sb/CS-007751.htm#2 */ -# define URI_INLINE __force_inline +# define URI_INLINE __forceinline #elif defined(_MSC_VER) /* Microsoft Visual C++ */ /* http://predef.sourceforge.net/precomp.html#sec32 */ diff --git a/include/uriparser/UriDefsUnicode.h b/include/uriparser/UriDefsUnicode.h index 08e4728..01421f5 100644 --- a/include/uriparser/UriDefsUnicode.h +++ b/include/uriparser/UriDefsUnicode.h @@ -39,7 +39,7 @@ /** * @file UriDefsUnicode.h - * Holds definitions for the Unicode pass. + * Holds definitions for the wide string pass. * NOTE: This header is included N times, not once. */ diff --git a/liburiparser.pc.in b/liburiparser.pc.in index 22c7c95..9547860 100644 --- a/liburiparser.pc.in +++ b/liburiparser.pc.in @@ -1,7 +1,7 @@ prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=@CMAKE_INSTALL_PREFIX@ -libdir=@CMAKE_INSTALL_FULL_LIBDIR@ -includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ +exec_prefix=${prefix} +libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ Name: liburiparser Description: URI parsing and handling library diff --git a/src/UriCommon.c b/src/UriCommon.c index 60bd319..7ba92f2 100644 --- a/src/UriCommon.c +++ b/src/UriCommon.c @@ -119,17 +119,6 @@ int URI_FUNC(CompareRange)( -/* Properly removes "." and ".." path segments */ -UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri, - UriBool relative, UriMemoryManager * memory) { - if (uri == NULL) { - return URI_TRUE; - } - return URI_FUNC(RemoveDotSegmentsEx)(uri, relative, uri->owner, memory); -} - - - UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, UriBool relative, UriBool pathOwned, UriMemoryManager * memory) { URI_TYPE(PathSegment) * walker; @@ -149,7 +138,13 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, URI_TYPE(PathSegment) * const prev = walker->reserved; URI_TYPE(PathSegment) * const nextBackup = walker->next; - /* Is this dot segment essential? */ + /* + * Is this dot segment essential, + * i.e. is there a chance of changing semantics by dropping this dot segment? + * + * For example, changing "./http://foo" into "http://foo" would change semantics + * and hence the dot segment is essential to that case and cannot be removed. + */ removeSegment = URI_TRUE; if (relative && (walker == uri->pathHead) && (walker->next != NULL)) { const URI_CHAR * ch = walker->next->text.first; @@ -162,16 +157,23 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, } if (removeSegment) { + /* .. then let's go remove that segment. */ /* Last segment? */ if (walker->next != NULL) { - /* Not last segment */ + /* Not last segment, i.e. first or middle segment + * OLD: (prev|NULL) <- walker <- next + * NEW: (prev|NULL) <----------- next */ walker->next->reserved = prev; if (prev == NULL) { - /* First but not last segment */ + /* First but not last segment + * OLD: head -> walker -> next + * NEW: head -----------> next */ uri->pathHead = walker->next; } else { - /* Middle segment */ + /* Middle segment + * OLD: prev -> walker -> next + * NEW: prev -----------> next */ prev->next = walker->next; } @@ -220,11 +222,16 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, removeSegment = URI_TRUE; if (relative) { if (prev == NULL) { + /* We cannot remove traversal beyond because the + * URI is relative and may be resolved later. + * So we can simplify "a/../b/d" to "b/d" but + * we cannot simplify "../b/d" (outside of reference resolution). */ removeSegment = URI_FALSE; } else if ((prev != NULL) && ((prev->text.afterLast - prev->text.first) == 2) && ((prev->text.first)[0] == _UT('.')) && ((prev->text.first)[1] == _UT('.'))) { + /* We need to protect against mis-simplifying "a/../../b" to "a/b". */ removeSegment = URI_FALSE; } } @@ -234,9 +241,14 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, /* Not first segment */ prevPrev = prev->reserved; if (prevPrev != NULL) { - /* Not even prev is the first one */ + /* Not even prev is the first one + * OLD: prevPrev -> prev -> walker -> (next|NULL) + * NEW: prevPrev -------------------> (next|NULL) */ prevPrev->next = walker->next; if (walker->next != NULL) { + /* Update parent relationship as well + * OLD: prevPrev <- prev <- walker <- next + * NEW: prevPrev <------------------- next */ walker->next->reserved = prevPrev; } else { /* Last segment -> insert "" segment to represent trailing slash, update tail */ @@ -302,29 +314,58 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, } } else { URI_TYPE(PathSegment) * const anotherNextBackup = walker->next; - /* First segment -> update head pointer */ - uri->pathHead = walker->next; + int freeWalker = URI_TRUE; + + /* First segment */ if (walker->next != NULL) { + /* First segment of multiple -> update head + * OLD: head -> walker -> next + * NEW: head -----------> next */ + uri->pathHead = walker->next; + + /* Update parent link as well + * OLD: head <- walker <- next + * NEW: head <----------- next */ walker->next->reserved = NULL; } else { - /* Last segment -> update tail */ - uri->pathTail = NULL; + if (uri->absolutePath) { + /* First and only segment -> update head + * OLD: head -> walker -> NULL + * NEW: head -----------> NULL */ + uri->pathHead = NULL; + + /* Last segment -> update tail + * OLD: tail -> walker + * NEW: tail -> NULL */ + uri->pathTail = NULL; + } else { + /* Re-use segment for "" path segment to represent trailing slash, + * then update head and tail */ + if (pathOwned && (walker->text.first != walker->text.afterLast)) { + memory->free(memory, (URI_CHAR *)walker->text.first); + } + walker->text.first = URI_FUNC(SafeToPointTo); + walker->text.afterLast = URI_FUNC(SafeToPointTo); + freeWalker = URI_FALSE; + } } - if (pathOwned && (walker->text.first != walker->text.afterLast)) { - memory->free(memory, (URI_CHAR *)walker->text.first); + if (freeWalker) { + if (pathOwned && (walker->text.first != walker->text.afterLast)) { + memory->free(memory, (URI_CHAR *)walker->text.first); + } + memory->free(memory, walker); } - memory->free(memory, walker); walker = anotherNextBackup; } } } break; - - } + } /* end of switch */ if (!removeSegment) { + /* .. then let's move to the next element, and start again. */ if (walker->next != NULL) { walker->next->reserved = walker; } else { @@ -344,7 +385,10 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { const UriBool ABSOLUTE = URI_FALSE; - return URI_FUNC(RemoveDotSegments)(uri, ABSOLUTE, memory); + if (uri == NULL) { + return URI_TRUE; + } + return URI_FUNC(RemoveDotSegmentsEx)(uri, ABSOLUTE, uri->owner, memory); } diff --git a/src/UriCommon.h b/src/UriCommon.h index 10bc250..42311dd 100644 --- a/src/UriCommon.h +++ b/src/UriCommon.h @@ -84,8 +84,6 @@ int URI_FUNC(CompareRange)( UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); -UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri, UriBool relative, - UriMemoryManager * memory); UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, UriBool relative, UriBool pathOwned, UriMemoryManager * memory); diff --git a/test/MemoryManagerSuite.cpp b/test/MemoryManagerSuite.cpp index 4cda664..a828d76 100644 --- a/test/MemoryManagerSuite.cpp +++ b/test/MemoryManagerSuite.cpp @@ -27,7 +27,11 @@ #include <gtest/gtest.h> #include <uriparser/Uri.h> + +// For defaultMemoryManager +extern "C" { #include "../src/UriMemory.h" +} namespace { diff --git a/test/test.cpp b/test/test.cpp index 9a189f9..4b156a4 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -311,7 +311,7 @@ TEST(UriSuite, TestUri) { ASSERT_TRUE(0 == uriParseUriA(&stateA, "//user:pass@localhost/one/two/three")); uriFreeUriMembersA(&uriA); - // ANSI and Unicode + // Both narrow and wide string version ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://www.example.com/")); uriFreeUriMembersA(&uriA); ASSERT_TRUE(0 == uriParseUriW(&stateW, L"http://www.example.com/")); @@ -1098,6 +1098,19 @@ TEST(UriSuite, TestAddBase) { // Bug related to absolutePath flag set despite presence of host ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"/", L"http://a/")); ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"/g/", L"http://a/g/")); + + // GitHub issue #92 + EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/../d;p?q", L"../..", L"http://a/")); + EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/../d;p?q", L"../../", L"http://a/")); + + EXPECT_TRUE(testAddBaseHelper(L"http://a/b/../c/d;p?q", L"../..", L"http://a/")); + EXPECT_TRUE(testAddBaseHelper(L"http://a/b/../c/d;p?q", L"../../", L"http://a/")); + + EXPECT_TRUE(testAddBaseHelper(L"http://a/../b/c/d;p?q", L"../..", L"http://a/")); + EXPECT_TRUE(testAddBaseHelper(L"http://a/../b/c/d;p?q", L"../../", L"http://a/")); + + EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../../..", L"http://a/")); + EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../../../", L"http://a/")); } namespace { @@ -1477,6 +1490,48 @@ TEST(UriSuite, TestNormalizeSyntaxComponents) { URI_NORMALIZE_FRAGMENT)); } +TEST(UriSuite, TestNormalizeSyntaxPath) { + // These are from GitHub issue #92 + EXPECT_TRUE(testNormalizeSyntaxHelper( + L"http://a/b/c/../../..", + L"http://a/", + URI_NORMALIZE_PATH)); + EXPECT_TRUE(testNormalizeSyntaxHelper( + L"http://a/b/../c/../..", + L"http://a/", + URI_NORMALIZE_PATH)); + EXPECT_TRUE(testNormalizeSyntaxHelper( + L"http://a/b/c/../../..", + L"http://a/", + URI_NORMALIZE_PATH)); + + // .. and these are related + EXPECT_TRUE(testNormalizeSyntaxHelper( + L"http://a/..", + L"http://a/", + URI_NORMALIZE_PATH)); + EXPECT_TRUE(testNormalizeSyntaxHelper( + L"/..", + L"/", + URI_NORMALIZE_PATH)); + EXPECT_TRUE(testNormalizeSyntaxHelper( + L"http://a/..///", + L"http://a///", + URI_NORMALIZE_PATH)); + EXPECT_TRUE(testNormalizeSyntaxHelper( + L"http://a/..///..", + L"http://a//", + URI_NORMALIZE_PATH)); + EXPECT_TRUE(testNormalizeSyntaxHelper( + L"a/b/c/../../..", + L"", + URI_NORMALIZE_PATH)); + EXPECT_TRUE(testNormalizeSyntaxHelper( + L"a/b/../../c/..", + L"", + URI_NORMALIZE_PATH)); +} + TEST(UriSuite, TestNormalizeCrashBug20080224) { UriParserStateW stateW; int res; |