mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Add ext/uri skeleton along with uriparser (#18658)
Relates to https://github.com/php/php-src/pull/14461/ and https://wiki.php.net/rfc/url_parsing_api
This commit is contained in:
parent
c0865ac013
commit
d585a5609d
43 changed files with 10166 additions and 0 deletions
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -31,3 +31,4 @@
|
|||
|
||||
# Vendored libraries
|
||||
/ext/lexbor/lexbor linguist-vendored
|
||||
/ext/uri/uriparser linguist-vendored
|
||||
|
|
5
.github/labeler.yml
vendored
5
.github/labeler.yml
vendored
|
@ -320,6 +320,11 @@
|
|||
- any-glob-to-any-file:
|
||||
- ext/tokenizer/**/*
|
||||
|
||||
"Extension: uri":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- ext/uri/**/*
|
||||
|
||||
"Extension: xml":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
|
|
|
@ -503,6 +503,12 @@ PRIMARY MAINTAINER: Andrei Zmievski <andrei@php.net> (2002 - 2002)
|
|||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: uri
|
||||
PRIMARY MAINTAINER Máté Kocsis <kocsismate@php.net> (2025 - 2025)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 8.5.0
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: zip
|
||||
PRIMARY MAINTAINER: Pierre-Alain Joye <pajoye@php.net> (2006 - 2011)
|
||||
Remi Collet <remi@php.net> (2013-2020)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
19. xxHash (ext/hash/xxhash)
|
||||
20. Lexbor (ext/lexbor/lexbor) see ext/lexbor/LICENSE
|
||||
21. Portions of libcperciva (ext/hash/hash_sha_{ni,sse2}.c) see the header in the source file
|
||||
22. uriparser (ext/uri/uriparser) see ext/uri/uriparser/COPYING
|
||||
|
||||
3. pcre2lib (ext/pcre)
|
||||
|
||||
|
|
|
@ -9,3 +9,4 @@ ignore:
|
|||
- "ext/lexbor/lexbor/ports"
|
||||
- "ext/lexbor/lexbor/tag"
|
||||
- "ext/pcre/pcre2lib"
|
||||
- "ext/uri/uriparser"
|
||||
|
|
|
@ -69,6 +69,7 @@ CREDIT_LINE("System V Semaphores", "Tom May");
|
|||
CREDIT_LINE("System V Shared Memory", "Christian Cartus");
|
||||
CREDIT_LINE("tidy", "John Coggeshall, Ilia Alshanetsky");
|
||||
CREDIT_LINE("tokenizer", "Andrei Zmievski, Johannes Schlueter");
|
||||
CREDIT_LINE("uri", "Máté Kocsis, Tim Düsterhus, Ignace Nyamagana Butera, Arnaud Le Blanc, Dennis Snell, Niels Dossche, Nicolas Grekas");
|
||||
CREDIT_LINE("XML", "Stig Bakken, Thies C. Arntzen, Sterling Hughes");
|
||||
CREDIT_LINE("XMLReader", "Rob Richards");
|
||||
CREDIT_LINE("XMLWriter", "Rob Richards, Pierre-Alain Joye");
|
||||
|
|
2
ext/uri/CREDITS
Normal file
2
ext/uri/CREDITS
Normal file
|
@ -0,0 +1,2 @@
|
|||
uri
|
||||
Máté Kocsis, Tim Düsterhus, Ignace Nyamagana Butera, Arnaud Le Blanc, Dennis Snell, Niels Dossche, Nicolas Grekas
|
20
ext/uri/config.m4
Normal file
20
ext/uri/config.m4
Normal file
|
@ -0,0 +1,20 @@
|
|||
dnl Configure options
|
||||
dnl
|
||||
|
||||
PHP_INSTALL_HEADERS([ext/uri], m4_normalize([
|
||||
php_uri.h
|
||||
]))
|
||||
|
||||
AC_DEFINE([URI_ENABLE_ANSI], [1], [Define to 1 for enabling ANSI support of uriparser.])
|
||||
AC_DEFINE([URI_NO_UNICODE], [1], [Define to 1 for disabling unicode support of uriparser.])
|
||||
|
||||
URIPARSER_DIR="uriparser"
|
||||
URIPARSER_SOURCES="$URIPARSER_DIR/src/UriCommon.c $URIPARSER_DIR/src/UriCompare.c $URIPARSER_DIR/src/UriEscape.c \
|
||||
$URIPARSER_DIR/src/UriFile.c $URIPARSER_DIR/src/UriIp4.c $URIPARSER_DIR/src/UriIp4Base.c \
|
||||
$URIPARSER_DIR/src/UriMemory.c $URIPARSER_DIR/src/UriNormalize.c $URIPARSER_DIR/src/UriNormalizeBase.c \
|
||||
$URIPARSER_DIR/src/UriParse.c $URIPARSER_DIR/src/UriParseBase.c $URIPARSER_DIR/src/UriQuery.c \
|
||||
$URIPARSER_DIR/src/UriRecompose.c $URIPARSER_DIR/src/UriResolve.c $URIPARSER_DIR/src/UriShorten.c"
|
||||
|
||||
PHP_NEW_EXTENSION(uri, [php_uri.c $URIPARSER_SOURCES], [no],,[-I$ext_builddir/$URIPARSER_DIR/include -DURI_STATIC_BUILD -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1])
|
||||
PHP_ADD_EXTENSION_DEP(uri, lexbor)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/$URIPARSER_DIR/src $ext_builddir/$URIPARSER_DIR/include)
|
9
ext/uri/config.w32
Normal file
9
ext/uri/config.w32
Normal file
|
@ -0,0 +1,9 @@
|
|||
EXTENSION("uri", "php_uri.c", false /* never shared */, "/I ext/lexbor /I ext/uri/uriparser/include /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
|
||||
|
||||
AC_DEFINE("URI_ENABLE_ANSI", 1, "Define to 1 for enabling ANSI support of uriparser.")
|
||||
AC_DEFINE("URI_NO_UNICODE", 1, "Define to 1 for disabling unicode support of uriparser.")
|
||||
ADD_FLAG("CFLAGS_URI", "/D URI_STATIC_BUILD");
|
||||
|
||||
ADD_EXTENSION_DEP('uri', 'lexbor');
|
||||
ADD_SOURCES("ext/uri/uriparser/src", "UriCommon.c UriCompare.c UriEscape.c UriFile.c UriIp4.c UriIp4Base.c UriMemory.c UriNormalize.c UriNormalizeBase.c UriParse.c UriParseBase.c UriQuery.c UriRecompose.c UriShorten.c", "uri");
|
||||
PHP_INSTALL_HEADERS("ext/uri", "php_uri.h uriparser/src uriparser/include");
|
90
ext/uri/php_uri.c
Normal file
90
ext/uri/php_uri.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| https://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Máté Kocsis <kocsismate@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#include "Zend/zend_interfaces.h"
|
||||
#include "Zend/zend_exceptions.h"
|
||||
#include "Zend/zend_attributes.h"
|
||||
#include "main/php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
|
||||
#include "php_uri.h"
|
||||
#include "php_uri_arginfo.h"
|
||||
#include "uriparser/src/UriConfig.h"
|
||||
|
||||
zend_class_entry *uri_exception_ce;
|
||||
zend_class_entry *invalid_uri_exception_ce;
|
||||
zend_class_entry *whatwg_invalid_url_exception_ce;
|
||||
|
||||
#define URIPARSER_VERSION PACKAGE_VERSION
|
||||
|
||||
static const zend_module_dep uri_deps[] = {
|
||||
ZEND_MOD_REQUIRED("lexbor")
|
||||
ZEND_MOD_END
|
||||
};
|
||||
|
||||
|
||||
static PHP_MINIT_FUNCTION(uri)
|
||||
{
|
||||
uri_exception_ce = register_class_Uri_UriException(zend_ce_exception);
|
||||
invalid_uri_exception_ce = register_class_Uri_InvalidUriException(uri_exception_ce);
|
||||
whatwg_invalid_url_exception_ce = register_class_Uri_WhatWg_InvalidUrlException(invalid_uri_exception_ce);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static PHP_MINFO_FUNCTION(uri)
|
||||
{
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_row(2, "uri support", "active");
|
||||
php_info_print_table_row(2, "uriparser library version", URIPARSER_VERSION);
|
||||
php_info_print_table_end();
|
||||
}
|
||||
|
||||
static PHP_MSHUTDOWN_FUNCTION(uri)
|
||||
{
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_RINIT_FUNCTION(uri)
|
||||
{
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_RSHUTDOWN_FUNCTION(uri)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
zend_module_entry uri_module_entry = {
|
||||
STANDARD_MODULE_HEADER_EX, NULL,
|
||||
uri_deps,
|
||||
"uri", /* Extension name */
|
||||
NULL, /* zend_function_entry */
|
||||
PHP_MINIT(uri), /* PHP_MINIT - Module initialization */
|
||||
PHP_MSHUTDOWN(uri), /* PHP_MSHUTDOWN - Module shutdown */
|
||||
PHP_RINIT(uri), /* PHP_RINIT - Request initialization */
|
||||
PHP_RSHUTDOWN(uri), /* PHP_RSHUTDOWN - Request shutdown */
|
||||
PHP_MINFO(uri), /* PHP_MINFO - Module info */
|
||||
PHP_VERSION, /* Version */
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
24
ext/uri/php_uri.h
Normal file
24
ext/uri/php_uri.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| https://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Máté Kocsis <kocsismate@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef PHP_URI_H
|
||||
#define PHP_URI_H
|
||||
|
||||
extern zend_module_entry uri_module_entry;
|
||||
#define phpext_uri_ptr &uri_module_entry
|
||||
|
||||
|
||||
#endif
|
23
ext/uri/php_uri.stub.php
Normal file
23
ext/uri/php_uri.stub.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/** @generate-class-entries */
|
||||
|
||||
namespace Uri {
|
||||
/** @strict-properties */
|
||||
class UriException extends \Exception
|
||||
{
|
||||
}
|
||||
|
||||
/** @strict-properties */
|
||||
class InvalidUriException extends \Uri\UriException
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace Uri\WhatWg {
|
||||
/** @strict-properties */
|
||||
class InvalidUrlException extends \Uri\InvalidUriException
|
||||
{
|
||||
public readonly array $errors;
|
||||
}
|
||||
}
|
38
ext/uri/php_uri_arginfo.h
generated
Normal file
38
ext/uri/php_uri_arginfo.h
generated
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 35460b24cf237585dabdc9813212c343034cf591 */
|
||||
|
||||
static zend_class_entry *register_class_Uri_UriException(zend_class_entry *class_entry_Exception)
|
||||
{
|
||||
zend_class_entry ce, *class_entry;
|
||||
|
||||
INIT_NS_CLASS_ENTRY(ce, "Uri", "UriException", NULL);
|
||||
class_entry = zend_register_internal_class_with_flags(&ce, class_entry_Exception, ZEND_ACC_NO_DYNAMIC_PROPERTIES);
|
||||
|
||||
return class_entry;
|
||||
}
|
||||
|
||||
static zend_class_entry *register_class_Uri_InvalidUriException(zend_class_entry *class_entry_Uri_UriException)
|
||||
{
|
||||
zend_class_entry ce, *class_entry;
|
||||
|
||||
INIT_NS_CLASS_ENTRY(ce, "Uri", "InvalidUriException", NULL);
|
||||
class_entry = zend_register_internal_class_with_flags(&ce, class_entry_Uri_UriException, ZEND_ACC_NO_DYNAMIC_PROPERTIES);
|
||||
|
||||
return class_entry;
|
||||
}
|
||||
|
||||
static zend_class_entry *register_class_Uri_WhatWg_InvalidUrlException(zend_class_entry *class_entry_Uri_InvalidUriException)
|
||||
{
|
||||
zend_class_entry ce, *class_entry;
|
||||
|
||||
INIT_NS_CLASS_ENTRY(ce, "Uri\\WhatWg", "InvalidUrlException", NULL);
|
||||
class_entry = zend_register_internal_class_with_flags(&ce, class_entry_Uri_InvalidUriException, ZEND_ACC_NO_DYNAMIC_PROPERTIES);
|
||||
|
||||
zval property_errors_default_value;
|
||||
ZVAL_UNDEF(&property_errors_default_value);
|
||||
zend_string *property_errors_name = zend_string_init("errors", sizeof("errors") - 1, 1);
|
||||
zend_declare_typed_property(class_entry, property_errors_name, &property_errors_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY));
|
||||
zend_string_release(property_errors_name);
|
||||
|
||||
return class_entry;
|
||||
}
|
36
ext/uri/uriparser/COPYING
Normal file
36
ext/uri/uriparser/COPYING
Normal file
|
@ -0,0 +1,36 @@
|
|||
uriparser - RFC 3986 URI parsing library
|
||||
|
||||
Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of
|
||||
its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
1146
ext/uri/uriparser/include/uriparser/Uri.h
Normal file
1146
ext/uri/uriparser/include/uriparser/Uri.h
Normal file
File diff suppressed because it is too large
Load diff
373
ext/uri/uriparser/include/uriparser/UriBase.h
Normal file
373
ext/uri/uriparser/include/uriparser/UriBase.h
Normal file
|
@ -0,0 +1,373 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file UriBase.h
|
||||
* Holds definitions independent of the encoding pass.
|
||||
*/
|
||||
|
||||
#ifndef URI_BASE_H
|
||||
#define URI_BASE_H 1
|
||||
|
||||
|
||||
|
||||
/* Version helper macro */
|
||||
#define URI_ANSI_TO_UNICODE(x) L##x
|
||||
|
||||
|
||||
|
||||
/* Version */
|
||||
#define URI_VER_MAJOR 0
|
||||
#define URI_VER_MINOR 9
|
||||
#define URI_VER_RELEASE 8
|
||||
#define URI_VER_SUFFIX_ANSI ""
|
||||
#define URI_VER_SUFFIX_UNICODE URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI)
|
||||
|
||||
|
||||
|
||||
/* More version helper macros */
|
||||
#define URI_INT_TO_ANSI_HELPER(x) #x
|
||||
#define URI_INT_TO_ANSI(x) URI_INT_TO_ANSI_HELPER(x)
|
||||
|
||||
#define URI_INT_TO_UNICODE_HELPER(x) URI_ANSI_TO_UNICODE(#x)
|
||||
#define URI_INT_TO_UNICODE(x) URI_INT_TO_UNICODE_HELPER(x)
|
||||
|
||||
#define URI_VER_ANSI_HELPER(ma, mi, r, s) \
|
||||
URI_INT_TO_ANSI(ma) "." \
|
||||
URI_INT_TO_ANSI(mi) "." \
|
||||
URI_INT_TO_ANSI(r) \
|
||||
s
|
||||
|
||||
#define URI_VER_UNICODE_HELPER(ma, mi, r, s) \
|
||||
URI_INT_TO_UNICODE(ma) L"." \
|
||||
URI_INT_TO_UNICODE(mi) L"." \
|
||||
URI_INT_TO_UNICODE(r) \
|
||||
s
|
||||
|
||||
|
||||
|
||||
/* Full version strings */
|
||||
#define URI_VER_ANSI URI_VER_ANSI_HELPER(URI_VER_MAJOR, URI_VER_MINOR, URI_VER_RELEASE, URI_VER_SUFFIX_ANSI)
|
||||
#define URI_VER_UNICODE URI_VER_UNICODE_HELPER(URI_VER_MAJOR, URI_VER_MINOR, URI_VER_RELEASE, URI_VER_SUFFIX_UNICODE)
|
||||
|
||||
|
||||
|
||||
/* Unused parameter macro */
|
||||
#ifdef __GNUC__
|
||||
# define URI_UNUSED(x) unused_##x __attribute__((unused))
|
||||
#else
|
||||
# define URI_UNUSED(x) x
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Import/export decorator */
|
||||
#if defined(_MSC_VER)
|
||||
# if defined(URI_STATIC_BUILD)
|
||||
# define URI_PUBLIC
|
||||
# elif defined(URI_LIBRARY_BUILD)
|
||||
# define URI_PUBLIC __declspec(dllexport)
|
||||
# else
|
||||
# define URI_PUBLIC __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# if ! defined(URI_LIBRARY_BUILD) || ! defined(URI_VISIBILITY)
|
||||
# define URI_PUBLIC
|
||||
# else
|
||||
# define URI_PUBLIC __attribute__ ((visibility("default")))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef int UriBool; /**< Boolean type */
|
||||
|
||||
#define URI_TRUE 1
|
||||
#define URI_FALSE 0
|
||||
|
||||
|
||||
|
||||
/* Shared errors */
|
||||
#define URI_SUCCESS 0
|
||||
#define URI_ERROR_SYNTAX 1 /* Parsed text violates expected format */
|
||||
#define URI_ERROR_NULL 2 /* One of the params passed was NULL
|
||||
although it mustn't be */
|
||||
#define URI_ERROR_MALLOC 3 /* Requested memory could not be allocated */
|
||||
#define URI_ERROR_OUTPUT_TOO_LARGE 4 /* Some output is to large for the receiving buffer */
|
||||
#define URI_ERROR_NOT_IMPLEMENTED 8 /* The called function is not implemented yet */
|
||||
#define URI_ERROR_RANGE_INVALID 9 /* The parameters passed contained invalid ranges */
|
||||
#define URI_ERROR_MEMORY_MANAGER_INCOMPLETE 10 /* [>=0.9.0] The UriMemoryManager passed does not implement all needed functions */
|
||||
|
||||
|
||||
/* Errors specific to ToString */
|
||||
#define URI_ERROR_TOSTRING_TOO_LONG URI_ERROR_OUTPUT_TOO_LARGE /* Deprecated, test for URI_ERROR_OUTPUT_TOO_LARGE instead */
|
||||
|
||||
/* Errors specific to AddBaseUri */
|
||||
#define URI_ERROR_ADDBASE_REL_BASE 5 /* Given base is not absolute */
|
||||
|
||||
/* Errors specific to RemoveBaseUri */
|
||||
#define URI_ERROR_REMOVEBASE_REL_BASE 6 /* Given base is not absolute */
|
||||
#define URI_ERROR_REMOVEBASE_REL_SOURCE 7 /* Given base is not absolute */
|
||||
|
||||
/* Error specific to uriTestMemoryManager */
|
||||
#define URI_ERROR_MEMORY_MANAGER_FAULTY 11 /* [>=0.9.0] The UriMemoryManager given did not pass the test suite */
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <stdio.h> /* For NULL, snprintf */
|
||||
# include <ctype.h> /* For wchar_t */
|
||||
# include <string.h> /* For strlen, memset, memcpy */
|
||||
# include <stdlib.h> /* For malloc */
|
||||
#endif /* URI_DOXYGEN */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Holds an IPv4 address.
|
||||
*/
|
||||
typedef struct UriIp4Struct {
|
||||
unsigned char data[4]; /**< Each octet in one byte */
|
||||
} UriIp4; /**< @copydoc UriIp4Struct */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Holds an IPv6 address.
|
||||
*/
|
||||
typedef struct UriIp6Struct {
|
||||
unsigned char data[16]; /**< Each quad in two bytes */
|
||||
} UriIp6; /**< @copydoc UriIp6Struct */
|
||||
|
||||
|
||||
struct UriMemoryManagerStruct; /* foward declaration to break loop */
|
||||
|
||||
|
||||
/**
|
||||
* Function signature that custom malloc(3) functions must conform to
|
||||
*
|
||||
* @since 0.9.0
|
||||
*/
|
||||
typedef void * (*UriFuncMalloc)(struct UriMemoryManagerStruct *, size_t);
|
||||
|
||||
/**
|
||||
* Function signature that custom calloc(3) functions must conform to
|
||||
*
|
||||
* @since 0.9.0
|
||||
*/
|
||||
typedef void * (*UriFuncCalloc)(struct UriMemoryManagerStruct *, size_t, size_t);
|
||||
|
||||
/**
|
||||
* Function signature that custom realloc(3) functions must conform to
|
||||
*
|
||||
* @since 0.9.0
|
||||
*/
|
||||
typedef void * (*UriFuncRealloc)(struct UriMemoryManagerStruct *, void *, size_t);
|
||||
|
||||
/**
|
||||
* Function signature that custom reallocarray(3) functions must conform to
|
||||
*
|
||||
* @since 0.9.0
|
||||
*/
|
||||
typedef void * (*UriFuncReallocarray)(struct UriMemoryManagerStruct *, void *, size_t, size_t);
|
||||
|
||||
/**
|
||||
* Function signature that custom free(3) functions must conform to
|
||||
*
|
||||
* @since 0.9.0
|
||||
*/
|
||||
typedef void (*UriFuncFree)(struct UriMemoryManagerStruct *, void *);
|
||||
|
||||
|
||||
/**
|
||||
* Class-like interface of custom memory managers
|
||||
*
|
||||
* @see uriCompleteMemoryManager
|
||||
* @see uriEmulateCalloc
|
||||
* @see uriEmulateReallocarray
|
||||
* @see uriTestMemoryManager
|
||||
* @since 0.9.0
|
||||
*/
|
||||
typedef struct UriMemoryManagerStruct {
|
||||
UriFuncMalloc malloc; /**< Pointer to custom malloc(3) */
|
||||
UriFuncCalloc calloc; /**< Pointer to custom calloc(3); to emulate using malloc and memset see uriEmulateCalloc */
|
||||
UriFuncRealloc realloc; /**< Pointer to custom realloc(3) */
|
||||
UriFuncReallocarray reallocarray; /**< Pointer to custom reallocarray(3); to emulate using realloc see uriEmulateReallocarray */
|
||||
UriFuncFree free; /**< Pointer to custom free(3) */
|
||||
void * userData; /**< Pointer to data that the other function members need access to */
|
||||
} UriMemoryManager; /**< @copydoc UriMemoryManagerStruct */
|
||||
|
||||
|
||||
/**
|
||||
* Specifies a line break conversion mode.
|
||||
*/
|
||||
typedef enum UriBreakConversionEnum {
|
||||
URI_BR_TO_LF, /**< Convert to Unix line breaks ("\\x0a") */
|
||||
URI_BR_TO_CRLF, /**< Convert to Windows line breaks ("\\x0d\\x0a") */
|
||||
URI_BR_TO_CR, /**< Convert to Macintosh line breaks ("\\x0d") */
|
||||
URI_BR_TO_UNIX = URI_BR_TO_LF, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_LF */
|
||||
URI_BR_TO_WINDOWS = URI_BR_TO_CRLF, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_CRLF */
|
||||
URI_BR_TO_MAC = URI_BR_TO_CR, /**< @copydoc UriBreakConversionEnum::URI_BR_TO_CR */
|
||||
URI_BR_DONT_TOUCH /**< Copy line breaks unmodified */
|
||||
} UriBreakConversion; /**< @copydoc UriBreakConversionEnum */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specifies which component of a %URI has to be normalized.
|
||||
*/
|
||||
typedef enum UriNormalizationMaskEnum {
|
||||
URI_NORMALIZED = 0, /**< Do not normalize anything */
|
||||
URI_NORMALIZE_SCHEME = 1 << 0, /**< Normalize scheme (fix uppercase letters) */
|
||||
URI_NORMALIZE_USER_INFO = 1 << 1, /**< Normalize user info (fix uppercase percent-encodings) */
|
||||
URI_NORMALIZE_HOST = 1 << 2, /**< Normalize host (fix uppercase letters) */
|
||||
URI_NORMALIZE_PATH = 1 << 3, /**< Normalize path (fix uppercase percent-encodings and redundant dot segments) */
|
||||
URI_NORMALIZE_QUERY = 1 << 4, /**< Normalize query (fix uppercase percent-encodings) */
|
||||
URI_NORMALIZE_FRAGMENT = 1 << 5 /**< Normalize fragment (fix uppercase percent-encodings) */
|
||||
} UriNormalizationMask; /**< @copydoc UriNormalizationMaskEnum */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specifies how to resolve %URI references.
|
||||
*/
|
||||
typedef enum UriResolutionOptionsEnum {
|
||||
URI_RESOLVE_STRICTLY = 0, /**< Full RFC conformance */
|
||||
URI_RESOLVE_IDENTICAL_SCHEME_COMPAT = 1 << 0 /**< Treat %URI to resolve with identical scheme as having no scheme */
|
||||
} UriResolutionOptions; /**< @copydoc UriResolutionOptionsEnum */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Wraps a memory manager backend that only provides malloc and free
|
||||
* to make a complete memory manager ready to be used.
|
||||
*
|
||||
* The core feature of this wrapper is that you don't need to implement
|
||||
* realloc if you don't want to. The wrapped memory manager uses
|
||||
* backend->malloc, memcpy, and backend->free and soieof(size_t) extra
|
||||
* bytes per allocation to emulate fallback realloc for you.
|
||||
*
|
||||
* memory->calloc is uriEmulateCalloc.
|
||||
* memory->free uses backend->free and handles the size header.
|
||||
* memory->malloc uses backend->malloc and adds a size header.
|
||||
* memory->realloc uses memory->malloc, memcpy, and memory->free and reads
|
||||
* the size header.
|
||||
* memory->reallocarray is uriEmulateReallocarray.
|
||||
*
|
||||
* The internal workings behind memory->free, memory->malloc, and
|
||||
* memory->realloc may change so the functions exposed by these function
|
||||
* pointer sshould be consided internal and not public API.
|
||||
*
|
||||
* @param memory <b>OUT</b>: Where to write the wrapped memory manager to
|
||||
* @param backend <b>IN</b>: Memory manager to use as a backend
|
||||
* @return Error code or 0 on success
|
||||
*
|
||||
* @see uriEmulateCalloc
|
||||
* @see uriEmulateReallocarray
|
||||
* @see UriMemoryManager
|
||||
* @since 0.9.0
|
||||
*/
|
||||
URI_PUBLIC int uriCompleteMemoryManager(UriMemoryManager * memory,
|
||||
UriMemoryManager * backend);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Offers emulation of calloc(3) based on memory->malloc and memset.
|
||||
* See "man 3 calloc" as well.
|
||||
*
|
||||
* @param memory <b>IN</b>: Memory manager to use, should not be NULL
|
||||
* @param nmemb <b>IN</b>: Number of elements to allocate
|
||||
* @param size <b>IN</b>: Size in bytes per element
|
||||
* @return Pointer to allocated memory or NULL
|
||||
*
|
||||
* @see uriCompleteMemoryManager
|
||||
* @see uriEmulateReallocarray
|
||||
* @see UriMemoryManager
|
||||
* @since 0.9.0
|
||||
*/
|
||||
URI_PUBLIC void * uriEmulateCalloc(UriMemoryManager * memory,
|
||||
size_t nmemb, size_t size);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Offers emulation of reallocarray(3) based on memory->realloc.
|
||||
* See "man 3 reallocarray" as well.
|
||||
*
|
||||
* @param memory <b>IN</b>: Memory manager to use, should not be NULL
|
||||
* @param ptr <b>IN</b>: Pointer allocated using memory->malloc/... or NULL
|
||||
* @param nmemb <b>IN</b>: Number of elements to allocate
|
||||
* @param size <b>IN</b>: Size in bytes per element
|
||||
* @return Pointer to allocated memory or NULL
|
||||
*
|
||||
* @see uriCompleteMemoryManager
|
||||
* @see uriEmulateCalloc
|
||||
* @see UriMemoryManager
|
||||
* @since 0.9.0
|
||||
*/
|
||||
URI_PUBLIC void * uriEmulateReallocarray(UriMemoryManager * memory,
|
||||
void * ptr, size_t nmemb, size_t size);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Run multiple tests against a given memory manager.
|
||||
* For example, one test
|
||||
* 1. allocates a small amount of memory,
|
||||
* 2. writes some magic bytes to it,
|
||||
* 3. reallocates it,
|
||||
* 4. checks that previous values are still present,
|
||||
* 5. and frees that memory.
|
||||
*
|
||||
* It is recommended to compile with AddressSanitizer enabled
|
||||
* to take full advantage of uriTestMemoryManager.
|
||||
*
|
||||
* @param memory <b>IN</b>: Memory manager to use, should not be NULL
|
||||
* @return Error code or 0 on success
|
||||
*
|
||||
* @see uriEmulateCalloc
|
||||
* @see uriEmulateReallocarray
|
||||
* @see UriMemoryManager
|
||||
* @since 0.9.0
|
||||
*/
|
||||
URI_PUBLIC int uriTestMemoryManager(UriMemoryManager * memory);
|
||||
|
||||
|
||||
|
||||
#endif /* URI_BASE_H */
|
82
ext/uri/uriparser/include/uriparser/UriDefsAnsi.h
Normal file
82
ext/uri/uriparser/include/uriparser/UriDefsAnsi.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file UriDefsAnsi.h
|
||||
* Holds definitions for the ANSI pass.
|
||||
* NOTE: This header is included N times, not once.
|
||||
*/
|
||||
|
||||
/* Allow multi inclusion */
|
||||
#include "UriDefsConfig.h"
|
||||
|
||||
|
||||
|
||||
#undef URI_CHAR
|
||||
#define URI_CHAR char
|
||||
|
||||
#undef _UT
|
||||
#define _UT(x) x
|
||||
|
||||
|
||||
|
||||
#undef URI_FUNC
|
||||
#define URI_FUNC(x) uri##x##A
|
||||
|
||||
#undef URI_TYPE
|
||||
#define URI_TYPE(x) Uri##x##A
|
||||
|
||||
|
||||
|
||||
#undef URI_STRLEN
|
||||
#define URI_STRLEN strlen
|
||||
#undef URI_STRCPY
|
||||
#define URI_STRCPY strcpy
|
||||
#undef URI_STRCMP
|
||||
#define URI_STRCMP strcmp
|
||||
#undef URI_STRNCMP
|
||||
#define URI_STRNCMP strncmp
|
||||
|
||||
/* TODO Remove on next source-compatibility break */
|
||||
#undef URI_SNPRINTF
|
||||
#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32))
|
||||
# define URI_SNPRINTF _snprintf
|
||||
#else
|
||||
# define URI_SNPRINTF snprintf
|
||||
#endif
|
101
ext/uri/uriparser/include/uriparser/UriDefsConfig.h
Normal file
101
ext/uri/uriparser/include/uriparser/UriDefsConfig.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file UriDefsConfig.h
|
||||
* Adjusts the internal configuration after processing external definitions.
|
||||
*/
|
||||
|
||||
#ifndef URI_DEFS_CONFIG_H
|
||||
#define URI_DEFS_CONFIG_H 1
|
||||
|
||||
|
||||
|
||||
/* Deny external overriding */
|
||||
#undef URI_ENABLE_ANSI /* Internal for !URI_NO_ANSI */
|
||||
#undef URI_ENABLE_UNICODE /* Internal for !URI_NO_UNICODE */
|
||||
|
||||
|
||||
|
||||
/* Encoding */
|
||||
#ifdef URI_NO_ANSI
|
||||
# ifdef URI_NO_UNICODE
|
||||
/* No encoding at all */
|
||||
# error URI_NO_ANSI and URI_NO_UNICODE cannot go together.
|
||||
# else
|
||||
/* Wide strings only */
|
||||
# define URI_ENABLE_UNICODE 1
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_NO_UNICODE
|
||||
/* Narrow strings only */
|
||||
# define URI_ENABLE_ANSI 1
|
||||
# else
|
||||
/* Both narrow and wide strings */
|
||||
# define URI_ENABLE_ANSI 1
|
||||
# define URI_ENABLE_UNICODE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Function inlining, not ANSI/ISO C! */
|
||||
#if defined(URI_DOXYGEN)
|
||||
# define URI_INLINE
|
||||
#elif defined(__INTEL_COMPILER)
|
||||
/* 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 __forceinline
|
||||
#elif defined(_MSC_VER)
|
||||
/* Microsoft Visual C++ */
|
||||
/* http://predef.sourceforge.net/precomp.html#sec32 */
|
||||
/* http://msdn2.microsoft.com/en-us/library/ms882281.aspx */
|
||||
# define URI_INLINE __forceinline
|
||||
#elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
|
||||
/* C99, "inline" is a keyword */
|
||||
# define URI_INLINE inline
|
||||
#else
|
||||
/* No inlining */
|
||||
# define URI_INLINE
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* URI_DEFS_CONFIG_H */
|
82
ext/uri/uriparser/include/uriparser/UriDefsUnicode.h
Normal file
82
ext/uri/uriparser/include/uriparser/UriDefsUnicode.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file UriDefsUnicode.h
|
||||
* Holds definitions for the wide string pass.
|
||||
* NOTE: This header is included N times, not once.
|
||||
*/
|
||||
|
||||
/* Allow multi inclusion */
|
||||
#include "UriDefsConfig.h"
|
||||
|
||||
|
||||
|
||||
#undef URI_CHAR
|
||||
#define URI_CHAR wchar_t
|
||||
|
||||
#undef _UT
|
||||
#define _UT(x) L##x
|
||||
|
||||
|
||||
|
||||
#undef URI_FUNC
|
||||
#define URI_FUNC(x) uri##x##W
|
||||
|
||||
#undef URI_TYPE
|
||||
#define URI_TYPE(x) Uri##x##W
|
||||
|
||||
|
||||
|
||||
#undef URI_STRLEN
|
||||
#define URI_STRLEN wcslen
|
||||
#undef URI_STRCPY
|
||||
#define URI_STRCPY wcscpy
|
||||
#undef URI_STRCMP
|
||||
#define URI_STRCMP wcscmp
|
||||
#undef URI_STRNCMP
|
||||
#define URI_STRNCMP wcsncmp
|
||||
|
||||
/* TODO Remove on next source-compatibility break */
|
||||
#undef URI_SNPRINTF
|
||||
#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32))
|
||||
# define URI_SNPRINTF _snwprintf
|
||||
#else
|
||||
# define URI_SNPRINTF swprintf
|
||||
#endif
|
110
ext/uri/uriparser/include/uriparser/UriIp4.h
Normal file
110
ext/uri/uriparser/include/uriparser/UriIp4.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file UriIp4.h
|
||||
* Holds the IPv4 parser interface.
|
||||
* NOTE: This header includes itself twice.
|
||||
*/
|
||||
|
||||
#if (defined(URI_PASS_ANSI) && !defined(URI_IP4_TWICE_H_ANSI)) \
|
||||
|| (defined(URI_PASS_UNICODE) && !defined(URI_IP4_TWICE_H_UNICODE)) \
|
||||
|| (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* What encodings are enabled? */
|
||||
#include "UriDefsConfig.h"
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriIp4.h"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriIp4.h"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
/* Only one pass for each encoding */
|
||||
#elif (defined(URI_PASS_ANSI) && !defined(URI_IP4_TWICE_H_ANSI) \
|
||||
&& defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \
|
||||
&& !defined(URI_IP4_TWICE_H_UNICODE) && defined(URI_ENABLE_UNICODE))
|
||||
# ifdef URI_PASS_ANSI
|
||||
# define URI_IP4_TWICE_H_ANSI 1
|
||||
# include "UriDefsAnsi.h"
|
||||
# else
|
||||
# define URI_IP4_TWICE_H_UNICODE 1
|
||||
# include "UriDefsUnicode.h"
|
||||
# include <wchar.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include "UriBase.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts a IPv4 text representation into four bytes.
|
||||
*
|
||||
* @param octetOutput Output destination
|
||||
* @param first First character of IPv4 text to parse
|
||||
* @param afterLast Position to stop parsing at
|
||||
* @return Error code or 0 on success
|
||||
*/
|
||||
URI_PUBLIC int URI_FUNC(ParseIpFourAddress)(unsigned char * octetOutput,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
616
ext/uri/uriparser/src/UriCommon.c
Normal file
616
ext/uri/uriparser/src/UriCommon.c
Normal file
|
@ -0,0 +1,616 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriCommon.c"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriCommon.c"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_PASS_ANSI
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# include <wchar.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/Uri.h>
|
||||
# include "UriCommon.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*extern*/ const URI_CHAR * const URI_FUNC(SafeToPointTo) = _UT("X");
|
||||
/*extern*/ const URI_CHAR * const URI_FUNC(ConstPwd) = _UT(".");
|
||||
/*extern*/ const URI_CHAR * const URI_FUNC(ConstParent) = _UT("..");
|
||||
|
||||
|
||||
|
||||
void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) {
|
||||
if (uri == NULL) {
|
||||
return;
|
||||
}
|
||||
memset(uri, 0, sizeof(URI_TYPE(Uri)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Compares two text ranges for equal text content */
|
||||
int URI_FUNC(CompareRange)(
|
||||
const URI_TYPE(TextRange) * a,
|
||||
const URI_TYPE(TextRange) * b) {
|
||||
int diff;
|
||||
|
||||
/* NOTE: Both NULL means equal! */
|
||||
if ((a == NULL) || (b == NULL)) {
|
||||
return ((a == NULL) ? 0 : 1) - ((b == NULL) ? 0 : 1);
|
||||
}
|
||||
|
||||
/* NOTE: Both NULL means equal! */
|
||||
if ((a->first == NULL) || (b->first == NULL)) {
|
||||
return ((a->first == NULL) ? 0 : 1) - ((b->first == NULL) ? 0 : 1);
|
||||
}
|
||||
|
||||
diff = ((int)(a->afterLast - a->first) - (int)(b->afterLast - b->first));
|
||||
if (diff > 0) {
|
||||
return 1;
|
||||
} else if (diff < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
diff = URI_STRNCMP(a->first, b->first, (a->afterLast - a->first));
|
||||
|
||||
if (diff > 0) {
|
||||
return 1;
|
||||
} else if (diff < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
|
||||
UriBool relative, UriBool pathOwned, UriMemoryManager * memory) {
|
||||
URI_TYPE(PathSegment) * walker;
|
||||
if ((uri == NULL) || (uri->pathHead == NULL)) {
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
walker = uri->pathHead;
|
||||
walker->reserved = NULL; /* Prev pointer */
|
||||
do {
|
||||
UriBool removeSegment = URI_FALSE;
|
||||
int len = (int)(walker->text.afterLast - walker->text.first);
|
||||
switch (len) {
|
||||
case 1:
|
||||
if ((walker->text.first)[0] == _UT('.')) {
|
||||
/* "." segment -> remove if not essential */
|
||||
URI_TYPE(PathSegment) * const prev = walker->reserved;
|
||||
URI_TYPE(PathSegment) * const nextBackup = walker->next;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
for (; ch < walker->next->text.afterLast; ch++) {
|
||||
if (*ch == _UT(':')) {
|
||||
removeSegment = URI_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (removeSegment) {
|
||||
/* .. then let's go remove that segment. */
|
||||
/* Last segment? */
|
||||
if (walker->next != NULL) {
|
||||
/* 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
|
||||
* OLD: head -> walker -> next
|
||||
* NEW: head -----------> next */
|
||||
uri->pathHead = walker->next;
|
||||
} else {
|
||||
/* Middle segment
|
||||
* OLD: prev -> walker -> next
|
||||
* NEW: prev -----------> next */
|
||||
prev->next = walker->next;
|
||||
}
|
||||
|
||||
if (pathOwned && (walker->text.first != walker->text.afterLast)) {
|
||||
memory->free(memory, (URI_CHAR *)walker->text.first);
|
||||
}
|
||||
memory->free(memory, walker);
|
||||
} else {
|
||||
/* Last segment */
|
||||
if (pathOwned && (walker->text.first != walker->text.afterLast)) {
|
||||
memory->free(memory, (URI_CHAR *)walker->text.first);
|
||||
}
|
||||
|
||||
if (prev == NULL) {
|
||||
/* Last and first */
|
||||
if (URI_FUNC(IsHostSet)(uri)) {
|
||||
/* Replace "." with empty segment to represent trailing slash */
|
||||
walker->text.first = URI_FUNC(SafeToPointTo);
|
||||
walker->text.afterLast = URI_FUNC(SafeToPointTo);
|
||||
} else {
|
||||
memory->free(memory, walker);
|
||||
|
||||
uri->pathHead = NULL;
|
||||
uri->pathTail = NULL;
|
||||
}
|
||||
} else {
|
||||
/* Last but not first, replace "." with empty segment to represent trailing slash */
|
||||
walker->text.first = URI_FUNC(SafeToPointTo);
|
||||
walker->text.afterLast = URI_FUNC(SafeToPointTo);
|
||||
}
|
||||
}
|
||||
|
||||
walker = nextBackup;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (((walker->text.first)[0] == _UT('.'))
|
||||
&& ((walker->text.first)[1] == _UT('.'))) {
|
||||
/* Path ".." -> remove this and the previous segment */
|
||||
URI_TYPE(PathSegment) * const prev = walker->reserved;
|
||||
URI_TYPE(PathSegment) * prevPrev;
|
||||
URI_TYPE(PathSegment) * const nextBackup = walker->next;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeSegment) {
|
||||
if (prev != NULL) {
|
||||
/* Not first segment */
|
||||
prevPrev = prev->reserved;
|
||||
if (prevPrev != NULL) {
|
||||
/* 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 */
|
||||
URI_TYPE(PathSegment) * const segment = memory->calloc(memory, 1, sizeof(URI_TYPE(PathSegment)));
|
||||
if (segment == NULL) {
|
||||
if (pathOwned && (walker->text.first != walker->text.afterLast)) {
|
||||
memory->free(memory, (URI_CHAR *)walker->text.first);
|
||||
}
|
||||
memory->free(memory, walker);
|
||||
|
||||
if (pathOwned && (prev->text.first != prev->text.afterLast)) {
|
||||
memory->free(memory, (URI_CHAR *)prev->text.first);
|
||||
}
|
||||
memory->free(memory, prev);
|
||||
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
segment->text.first = URI_FUNC(SafeToPointTo);
|
||||
segment->text.afterLast = URI_FUNC(SafeToPointTo);
|
||||
prevPrev->next = segment;
|
||||
uri->pathTail = segment;
|
||||
}
|
||||
|
||||
if (pathOwned && (walker->text.first != walker->text.afterLast)) {
|
||||
memory->free(memory, (URI_CHAR *)walker->text.first);
|
||||
}
|
||||
memory->free(memory, walker);
|
||||
|
||||
if (pathOwned && (prev->text.first != prev->text.afterLast)) {
|
||||
memory->free(memory, (URI_CHAR *)prev->text.first);
|
||||
}
|
||||
memory->free(memory, prev);
|
||||
|
||||
walker = nextBackup;
|
||||
} else {
|
||||
/* Prev is the first segment */
|
||||
if (walker->next != NULL) {
|
||||
uri->pathHead = walker->next;
|
||||
walker->next->reserved = NULL;
|
||||
|
||||
if (pathOwned && (walker->text.first != walker->text.afterLast)) {
|
||||
memory->free(memory, (URI_CHAR *)walker->text.first);
|
||||
}
|
||||
memory->free(memory, walker);
|
||||
} else {
|
||||
/* Re-use segment for "" path segment to represent trailing slash, update tail */
|
||||
URI_TYPE(PathSegment) * const segment = walker;
|
||||
if (pathOwned && (segment->text.first != segment->text.afterLast)) {
|
||||
memory->free(memory, (URI_CHAR *)segment->text.first);
|
||||
}
|
||||
segment->text.first = URI_FUNC(SafeToPointTo);
|
||||
segment->text.afterLast = URI_FUNC(SafeToPointTo);
|
||||
uri->pathHead = segment;
|
||||
uri->pathTail = segment;
|
||||
}
|
||||
|
||||
if (pathOwned && (prev->text.first != prev->text.afterLast)) {
|
||||
memory->free(memory, (URI_CHAR *)prev->text.first);
|
||||
}
|
||||
memory->free(memory, prev);
|
||||
|
||||
walker = nextBackup;
|
||||
}
|
||||
} else {
|
||||
URI_TYPE(PathSegment) * const anotherNextBackup = 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 {
|
||||
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 (freeWalker) {
|
||||
if (pathOwned && (walker->text.first != walker->text.afterLast)) {
|
||||
memory->free(memory, (URI_CHAR *)walker->text.first);
|
||||
}
|
||||
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 {
|
||||
/* Last segment -> update tail */
|
||||
uri->pathTail = walker;
|
||||
}
|
||||
walker = walker->next;
|
||||
}
|
||||
} while (walker != NULL);
|
||||
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Properly removes "." and ".." path segments */
|
||||
UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri,
|
||||
UriMemoryManager * memory) {
|
||||
const UriBool ABSOLUTE = URI_FALSE;
|
||||
if (uri == NULL) {
|
||||
return URI_TRUE;
|
||||
}
|
||||
return URI_FUNC(RemoveDotSegmentsEx)(uri, ABSOLUTE, uri->owner, memory);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig) {
|
||||
switch (hexdig) {
|
||||
case _UT('0'):
|
||||
case _UT('1'):
|
||||
case _UT('2'):
|
||||
case _UT('3'):
|
||||
case _UT('4'):
|
||||
case _UT('5'):
|
||||
case _UT('6'):
|
||||
case _UT('7'):
|
||||
case _UT('8'):
|
||||
case _UT('9'):
|
||||
return (unsigned char)(9 + hexdig - _UT('9'));
|
||||
|
||||
case _UT('a'):
|
||||
case _UT('b'):
|
||||
case _UT('c'):
|
||||
case _UT('d'):
|
||||
case _UT('e'):
|
||||
case _UT('f'):
|
||||
return (unsigned char)(15 + hexdig - _UT('f'));
|
||||
|
||||
case _UT('A'):
|
||||
case _UT('B'):
|
||||
case _UT('C'):
|
||||
case _UT('D'):
|
||||
case _UT('E'):
|
||||
case _UT('F'):
|
||||
return (unsigned char)(15 + hexdig - _UT('F'));
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
URI_CHAR URI_FUNC(HexToLetter)(unsigned int value) {
|
||||
/* Uppercase recommended in section 2.1. of RFC 3986 *
|
||||
* https://datatracker.ietf.org/doc/html/rfc3986#section-2.1 */
|
||||
return URI_FUNC(HexToLetterEx)(value, URI_TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
URI_CHAR URI_FUNC(HexToLetterEx)(unsigned int value, UriBool uppercase) {
|
||||
switch (value) {
|
||||
case 0: return _UT('0');
|
||||
case 1: return _UT('1');
|
||||
case 2: return _UT('2');
|
||||
case 3: return _UT('3');
|
||||
case 4: return _UT('4');
|
||||
case 5: return _UT('5');
|
||||
case 6: return _UT('6');
|
||||
case 7: return _UT('7');
|
||||
case 8: return _UT('8');
|
||||
case 9: return _UT('9');
|
||||
|
||||
case 10: return (uppercase == URI_TRUE) ? _UT('A') : _UT('a');
|
||||
case 11: return (uppercase == URI_TRUE) ? _UT('B') : _UT('b');
|
||||
case 12: return (uppercase == URI_TRUE) ? _UT('C') : _UT('c');
|
||||
case 13: return (uppercase == URI_TRUE) ? _UT('D') : _UT('d');
|
||||
case 14: return (uppercase == URI_TRUE) ? _UT('E') : _UT('e');
|
||||
default: return (uppercase == URI_TRUE) ? _UT('F') : _UT('f');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Checks if a URI has the host component set. */
|
||||
UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri) {
|
||||
return (uri != NULL)
|
||||
&& ((uri->hostText.first != NULL)
|
||||
|| (uri->hostData.ip4 != NULL)
|
||||
|| (uri->hostData.ip6 != NULL)
|
||||
|| (uri->hostData.ipFuture.first != NULL)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Copies the path segment list from one URI to another. */
|
||||
UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest,
|
||||
const URI_TYPE(Uri) * source, UriMemoryManager * memory) {
|
||||
if (source->pathHead == NULL) {
|
||||
/* No path component */
|
||||
dest->pathHead = NULL;
|
||||
dest->pathTail = NULL;
|
||||
} else {
|
||||
/* Copy list but not the text contained */
|
||||
URI_TYPE(PathSegment) * sourceWalker = source->pathHead;
|
||||
URI_TYPE(PathSegment) * destPrev = NULL;
|
||||
do {
|
||||
URI_TYPE(PathSegment) * cur = memory->malloc(memory, sizeof(URI_TYPE(PathSegment)));
|
||||
if (cur == NULL) {
|
||||
/* Fix broken list */
|
||||
if (destPrev != NULL) {
|
||||
destPrev->next = NULL;
|
||||
}
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
|
||||
/* From this functions usage we know that *
|
||||
* the dest URI cannot be uri->owner */
|
||||
cur->text = sourceWalker->text;
|
||||
if (destPrev == NULL) {
|
||||
/* First segment ever */
|
||||
dest->pathHead = cur;
|
||||
} else {
|
||||
destPrev->next = cur;
|
||||
}
|
||||
destPrev = cur;
|
||||
sourceWalker = sourceWalker->next;
|
||||
} while (sourceWalker != NULL);
|
||||
dest->pathTail = destPrev;
|
||||
dest->pathTail->next = NULL;
|
||||
}
|
||||
|
||||
dest->absolutePath = source->absolutePath;
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Copies the authority part of an URI over to another. */
|
||||
UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest,
|
||||
const URI_TYPE(Uri) * source, UriMemoryManager * memory) {
|
||||
/* From this functions usage we know that *
|
||||
* the dest URI cannot be uri->owner */
|
||||
|
||||
/* Copy userInfo */
|
||||
dest->userInfo = source->userInfo;
|
||||
|
||||
/* Copy hostText */
|
||||
dest->hostText = source->hostText;
|
||||
|
||||
/* Copy hostData */
|
||||
if (source->hostData.ip4 != NULL) {
|
||||
dest->hostData.ip4 = memory->malloc(memory, sizeof(UriIp4));
|
||||
if (dest->hostData.ip4 == NULL) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
*(dest->hostData.ip4) = *(source->hostData.ip4);
|
||||
dest->hostData.ip6 = NULL;
|
||||
dest->hostData.ipFuture.first = NULL;
|
||||
dest->hostData.ipFuture.afterLast = NULL;
|
||||
} else if (source->hostData.ip6 != NULL) {
|
||||
dest->hostData.ip4 = NULL;
|
||||
dest->hostData.ip6 = memory->malloc(memory, sizeof(UriIp6));
|
||||
if (dest->hostData.ip6 == NULL) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
*(dest->hostData.ip6) = *(source->hostData.ip6);
|
||||
dest->hostData.ipFuture.first = NULL;
|
||||
dest->hostData.ipFuture.afterLast = NULL;
|
||||
} else {
|
||||
dest->hostData.ip4 = NULL;
|
||||
dest->hostData.ip6 = NULL;
|
||||
dest->hostData.ipFuture = source->hostData.ipFuture;
|
||||
}
|
||||
|
||||
/* Copy portText */
|
||||
dest->portText = source->portText;
|
||||
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri,
|
||||
UriMemoryManager * memory) {
|
||||
URI_TYPE(PathSegment) * segment;
|
||||
|
||||
if ( /* Case 1: absolute path, empty first segment */
|
||||
(uri->absolutePath
|
||||
&& (uri->pathHead != NULL)
|
||||
&& (uri->pathHead->text.afterLast == uri->pathHead->text.first))
|
||||
|
||||
/* Case 2: relative path, empty first and second segment */
|
||||
|| (!uri->absolutePath
|
||||
&& (uri->pathHead != NULL)
|
||||
&& (uri->pathHead->next != NULL)
|
||||
&& (uri->pathHead->text.afterLast == uri->pathHead->text.first)
|
||||
&& (uri->pathHead->next->text.afterLast == uri->pathHead->next->text.first))) {
|
||||
/* NOOP */
|
||||
} else {
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
segment = memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment)));
|
||||
if (segment == NULL) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
|
||||
/* Insert "." segment in front */
|
||||
segment->next = uri->pathHead;
|
||||
segment->text.first = URI_FUNC(ConstPwd);
|
||||
segment->text.afterLast = URI_FUNC(ConstPwd) + 1;
|
||||
uri->pathHead = segment;
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri,
|
||||
UriMemoryManager * memory) {
|
||||
/* Fix path if only one empty segment */
|
||||
if (!uri->absolutePath
|
||||
&& !URI_FUNC(IsHostSet)(uri)
|
||||
&& (uri->pathHead != NULL)
|
||||
&& (uri->pathHead->next == NULL)
|
||||
&& (uri->pathHead->text.first == uri->pathHead->text.afterLast)) {
|
||||
memory->free(memory, uri->pathHead);
|
||||
uri->pathHead = NULL;
|
||||
uri->pathTail = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
107
ext/uri/uriparser/src/UriCommon.h
Normal file
107
ext/uri/uriparser/src/UriCommon.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if (defined(URI_PASS_ANSI) && !defined(URI_COMMON_H_ANSI)) \
|
||||
|| (defined(URI_PASS_UNICODE) && !defined(URI_COMMON_H_UNICODE)) \
|
||||
|| (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriCommon.h"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriCommon.h"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
/* Only one pass for each encoding */
|
||||
#elif (defined(URI_PASS_ANSI) && !defined(URI_COMMON_H_ANSI) \
|
||||
&& defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \
|
||||
&& !defined(URI_COMMON_H_UNICODE) && defined(URI_ENABLE_UNICODE))
|
||||
# ifdef URI_PASS_ANSI
|
||||
# define URI_COMMON_H_ANSI 1
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# define URI_COMMON_H_UNICODE 1
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
/* Used to point to from empty path segments.
|
||||
* X.first and X.afterLast must be the same non-NULL value then. */
|
||||
extern const URI_CHAR * const URI_FUNC(SafeToPointTo);
|
||||
extern const URI_CHAR * const URI_FUNC(ConstPwd);
|
||||
extern const URI_CHAR * const URI_FUNC(ConstParent);
|
||||
|
||||
|
||||
|
||||
void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri);
|
||||
|
||||
int URI_FUNC(CompareRange)(
|
||||
const URI_TYPE(TextRange) * a,
|
||||
const URI_TYPE(TextRange) * b);
|
||||
|
||||
UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri,
|
||||
UriMemoryManager * memory);
|
||||
UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
|
||||
UriBool relative, UriBool pathOwned, UriMemoryManager * memory);
|
||||
|
||||
unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig);
|
||||
URI_CHAR URI_FUNC(HexToLetter)(unsigned int value);
|
||||
URI_CHAR URI_FUNC(HexToLetterEx)(unsigned int value, UriBool uppercase);
|
||||
|
||||
UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri);
|
||||
|
||||
UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source,
|
||||
UriMemoryManager * memory);
|
||||
UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest,
|
||||
const URI_TYPE(Uri) * source, UriMemoryManager * memory);
|
||||
|
||||
UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri, UriMemoryManager * memory);
|
||||
void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri,
|
||||
UriMemoryManager * memory);
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
168
ext/uri/uriparser/src/UriCompare.c
Normal file
168
ext/uri/uriparser/src/UriCompare.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriCompare.c"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriCompare.c"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_PASS_ANSI
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# include <wchar.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/Uri.h>
|
||||
# include <uriparser/UriIp4.h>
|
||||
# include "UriCommon.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a,
|
||||
const URI_TYPE(Uri) * b) {
|
||||
/* NOTE: Both NULL means equal! */
|
||||
if ((a == NULL) || (b == NULL)) {
|
||||
return ((a == NULL) && (b == NULL)) ? URI_TRUE : URI_FALSE;
|
||||
}
|
||||
|
||||
/* scheme */
|
||||
if (URI_FUNC(CompareRange)(&(a->scheme), &(b->scheme))) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
/* absolutePath */
|
||||
if ((a->scheme.first == NULL)&& (a->absolutePath != b->absolutePath)) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
/* userInfo */
|
||||
if (URI_FUNC(CompareRange)(&(a->userInfo), &(b->userInfo))) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
/* Host */
|
||||
if (((a->hostData.ip4 == NULL) != (b->hostData.ip4 == NULL))
|
||||
|| ((a->hostData.ip6 == NULL) != (b->hostData.ip6 == NULL))
|
||||
|| ((a->hostData.ipFuture.first == NULL)
|
||||
!= (b->hostData.ipFuture.first == NULL))) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
if (a->hostData.ip4 != NULL) {
|
||||
if (memcmp(a->hostData.ip4->data, b->hostData.ip4->data, 4)) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (a->hostData.ip6 != NULL) {
|
||||
if (memcmp(a->hostData.ip6->data, b->hostData.ip6->data, 16)) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (a->hostData.ipFuture.first != NULL) {
|
||||
if (URI_FUNC(CompareRange)(&(a->hostData.ipFuture), &(b->hostData.ipFuture))) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((a->hostData.ip4 == NULL)
|
||||
&& (a->hostData.ip6 == NULL)
|
||||
&& (a->hostData.ipFuture.first == NULL)) {
|
||||
if (URI_FUNC(CompareRange)(&(a->hostText), &(b->hostText))) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* portText */
|
||||
if (URI_FUNC(CompareRange)(&(a->portText), &(b->portText))) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
/* Path */
|
||||
if ((a->pathHead == NULL) != (b->pathHead == NULL)) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
if (a->pathHead != NULL) {
|
||||
URI_TYPE(PathSegment) * walkA = a->pathHead;
|
||||
URI_TYPE(PathSegment) * walkB = b->pathHead;
|
||||
do {
|
||||
if (URI_FUNC(CompareRange)(&(walkA->text), &(walkB->text))) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
if ((walkA->next == NULL) != (walkB->next == NULL)) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
walkA = walkA->next;
|
||||
walkB = walkB->next;
|
||||
} while (walkA != NULL);
|
||||
}
|
||||
|
||||
/* query */
|
||||
if (URI_FUNC(CompareRange)(&(a->query), &(b->query))) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
/* fragment */
|
||||
if (URI_FUNC(CompareRange)(&(a->fragment), &(b->fragment))) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
return URI_TRUE; /* Equal*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
53
ext/uri/uriparser/src/UriConfig.h
Normal file
53
ext/uri/uriparser/src/UriConfig.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2018, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(URI_CONFIG_H)
|
||||
# define URI_CONFIG_H 1
|
||||
|
||||
|
||||
|
||||
#define PACKAGE_VERSION "0.9.8"
|
||||
|
||||
/*
|
||||
#define HAVE_WPRINTF*
|
||||
#define HAVE_REALLOCARRAY
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#endif /* !defined(URI_CONFIG_H) */
|
51
ext/uri/uriparser/src/UriConfig.h.in
Normal file
51
ext/uri/uriparser/src/UriConfig.h.in
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2018, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(URI_CONFIG_H)
|
||||
# define URI_CONFIG_H 1
|
||||
|
||||
|
||||
|
||||
#define PACKAGE_VERSION "@PROJECT_VERSION@"
|
||||
|
||||
#cmakedefine HAVE_WPRINTF
|
||||
#cmakedefine HAVE_REALLOCARRAY
|
||||
|
||||
|
||||
|
||||
#endif /* !defined(URI_CONFIG_H) */
|
453
ext/uri/uriparser/src/UriEscape.c
Normal file
453
ext/uri/uriparser/src/UriEscape.c
Normal file
|
@ -0,0 +1,453 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriEscape.c"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriEscape.c"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_PASS_ANSI
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# include <wchar.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/Uri.h>
|
||||
# include "UriCommon.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
URI_CHAR * URI_FUNC(Escape)(const URI_CHAR * in, URI_CHAR * out,
|
||||
UriBool spaceToPlus, UriBool normalizeBreaks) {
|
||||
return URI_FUNC(EscapeEx)(in, NULL, out, spaceToPlus, normalizeBreaks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
URI_CHAR * URI_FUNC(EscapeEx)(const URI_CHAR * inFirst,
|
||||
const URI_CHAR * inAfterLast, URI_CHAR * out,
|
||||
UriBool spaceToPlus, UriBool normalizeBreaks) {
|
||||
const URI_CHAR * read = inFirst;
|
||||
URI_CHAR * write = out;
|
||||
UriBool prevWasCr = URI_FALSE;
|
||||
if ((out == NULL) || (inFirst == out)) {
|
||||
return NULL;
|
||||
} else if (inFirst == NULL) {
|
||||
if (out != NULL) {
|
||||
out[0] = _UT('\0');
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if ((inAfterLast != NULL) && (read >= inAfterLast)) {
|
||||
write[0] = _UT('\0');
|
||||
return write;
|
||||
}
|
||||
|
||||
switch (read[0]) {
|
||||
case _UT('\0'):
|
||||
write[0] = _UT('\0');
|
||||
return write;
|
||||
|
||||
case _UT(' '):
|
||||
if (spaceToPlus) {
|
||||
write[0] = _UT('+');
|
||||
write++;
|
||||
} else {
|
||||
write[0] = _UT('%');
|
||||
write[1] = _UT('2');
|
||||
write[2] = _UT('0');
|
||||
write += 3;
|
||||
}
|
||||
prevWasCr = URI_FALSE;
|
||||
break;
|
||||
|
||||
case _UT('a'): /* ALPHA */
|
||||
case _UT('A'):
|
||||
case _UT('b'):
|
||||
case _UT('B'):
|
||||
case _UT('c'):
|
||||
case _UT('C'):
|
||||
case _UT('d'):
|
||||
case _UT('D'):
|
||||
case _UT('e'):
|
||||
case _UT('E'):
|
||||
case _UT('f'):
|
||||
case _UT('F'):
|
||||
case _UT('g'):
|
||||
case _UT('G'):
|
||||
case _UT('h'):
|
||||
case _UT('H'):
|
||||
case _UT('i'):
|
||||
case _UT('I'):
|
||||
case _UT('j'):
|
||||
case _UT('J'):
|
||||
case _UT('k'):
|
||||
case _UT('K'):
|
||||
case _UT('l'):
|
||||
case _UT('L'):
|
||||
case _UT('m'):
|
||||
case _UT('M'):
|
||||
case _UT('n'):
|
||||
case _UT('N'):
|
||||
case _UT('o'):
|
||||
case _UT('O'):
|
||||
case _UT('p'):
|
||||
case _UT('P'):
|
||||
case _UT('q'):
|
||||
case _UT('Q'):
|
||||
case _UT('r'):
|
||||
case _UT('R'):
|
||||
case _UT('s'):
|
||||
case _UT('S'):
|
||||
case _UT('t'):
|
||||
case _UT('T'):
|
||||
case _UT('u'):
|
||||
case _UT('U'):
|
||||
case _UT('v'):
|
||||
case _UT('V'):
|
||||
case _UT('w'):
|
||||
case _UT('W'):
|
||||
case _UT('x'):
|
||||
case _UT('X'):
|
||||
case _UT('y'):
|
||||
case _UT('Y'):
|
||||
case _UT('z'):
|
||||
case _UT('Z'):
|
||||
case _UT('0'): /* DIGIT */
|
||||
case _UT('1'):
|
||||
case _UT('2'):
|
||||
case _UT('3'):
|
||||
case _UT('4'):
|
||||
case _UT('5'):
|
||||
case _UT('6'):
|
||||
case _UT('7'):
|
||||
case _UT('8'):
|
||||
case _UT('9'):
|
||||
case _UT('-'): /* "-" / "." / "_" / "~" */
|
||||
case _UT('.'):
|
||||
case _UT('_'):
|
||||
case _UT('~'):
|
||||
/* Copy unmodified */
|
||||
write[0] = read[0];
|
||||
write++;
|
||||
|
||||
prevWasCr = URI_FALSE;
|
||||
break;
|
||||
|
||||
case _UT('\x0a'):
|
||||
if (normalizeBreaks) {
|
||||
if (!prevWasCr) {
|
||||
write[0] = _UT('%');
|
||||
write[1] = _UT('0');
|
||||
write[2] = _UT('D');
|
||||
write[3] = _UT('%');
|
||||
write[4] = _UT('0');
|
||||
write[5] = _UT('A');
|
||||
write += 6;
|
||||
}
|
||||
} else {
|
||||
write[0] = _UT('%');
|
||||
write[1] = _UT('0');
|
||||
write[2] = _UT('A');
|
||||
write += 3;
|
||||
}
|
||||
prevWasCr = URI_FALSE;
|
||||
break;
|
||||
|
||||
case _UT('\x0d'):
|
||||
if (normalizeBreaks) {
|
||||
write[0] = _UT('%');
|
||||
write[1] = _UT('0');
|
||||
write[2] = _UT('D');
|
||||
write[3] = _UT('%');
|
||||
write[4] = _UT('0');
|
||||
write[5] = _UT('A');
|
||||
write += 6;
|
||||
} else {
|
||||
write[0] = _UT('%');
|
||||
write[1] = _UT('0');
|
||||
write[2] = _UT('D');
|
||||
write += 3;
|
||||
}
|
||||
prevWasCr = URI_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Percent encode */
|
||||
{
|
||||
const unsigned char code = (unsigned char)read[0];
|
||||
write[0] = _UT('%');
|
||||
write[1] = URI_FUNC(HexToLetter)(code >> 4);
|
||||
write[2] = URI_FUNC(HexToLetter)(code & 0x0f);
|
||||
write += 3;
|
||||
}
|
||||
prevWasCr = URI_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
read++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const URI_CHAR * URI_FUNC(UnescapeInPlace)(URI_CHAR * inout) {
|
||||
return URI_FUNC(UnescapeInPlaceEx)(inout, URI_FALSE, URI_BR_DONT_TOUCH);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const URI_CHAR * URI_FUNC(UnescapeInPlaceEx)(URI_CHAR * inout,
|
||||
UriBool plusToSpace, UriBreakConversion breakConversion) {
|
||||
URI_CHAR * read = inout;
|
||||
URI_CHAR * write = inout;
|
||||
UriBool prevWasCr = URI_FALSE;
|
||||
|
||||
if (inout == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
switch (read[0]) {
|
||||
case _UT('\0'):
|
||||
if (read > write) {
|
||||
write[0] = _UT('\0');
|
||||
}
|
||||
return write;
|
||||
|
||||
case _UT('%'):
|
||||
switch (read[1]) {
|
||||
case _UT('0'):
|
||||
case _UT('1'):
|
||||
case _UT('2'):
|
||||
case _UT('3'):
|
||||
case _UT('4'):
|
||||
case _UT('5'):
|
||||
case _UT('6'):
|
||||
case _UT('7'):
|
||||
case _UT('8'):
|
||||
case _UT('9'):
|
||||
case _UT('a'):
|
||||
case _UT('b'):
|
||||
case _UT('c'):
|
||||
case _UT('d'):
|
||||
case _UT('e'):
|
||||
case _UT('f'):
|
||||
case _UT('A'):
|
||||
case _UT('B'):
|
||||
case _UT('C'):
|
||||
case _UT('D'):
|
||||
case _UT('E'):
|
||||
case _UT('F'):
|
||||
switch (read[2]) {
|
||||
case _UT('0'):
|
||||
case _UT('1'):
|
||||
case _UT('2'):
|
||||
case _UT('3'):
|
||||
case _UT('4'):
|
||||
case _UT('5'):
|
||||
case _UT('6'):
|
||||
case _UT('7'):
|
||||
case _UT('8'):
|
||||
case _UT('9'):
|
||||
case _UT('a'):
|
||||
case _UT('b'):
|
||||
case _UT('c'):
|
||||
case _UT('d'):
|
||||
case _UT('e'):
|
||||
case _UT('f'):
|
||||
case _UT('A'):
|
||||
case _UT('B'):
|
||||
case _UT('C'):
|
||||
case _UT('D'):
|
||||
case _UT('E'):
|
||||
case _UT('F'):
|
||||
{
|
||||
/* Percent group found */
|
||||
const unsigned char left = URI_FUNC(HexdigToInt)(read[1]);
|
||||
const unsigned char right = URI_FUNC(HexdigToInt)(read[2]);
|
||||
const int code = 16 * left + right;
|
||||
switch (code) {
|
||||
case 10:
|
||||
switch (breakConversion) {
|
||||
case URI_BR_TO_LF:
|
||||
if (!prevWasCr) {
|
||||
write[0] = (URI_CHAR)10;
|
||||
write++;
|
||||
}
|
||||
break;
|
||||
|
||||
case URI_BR_TO_CRLF:
|
||||
if (!prevWasCr) {
|
||||
write[0] = (URI_CHAR)13;
|
||||
write[1] = (URI_CHAR)10;
|
||||
write += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case URI_BR_TO_CR:
|
||||
if (!prevWasCr) {
|
||||
write[0] = (URI_CHAR)13;
|
||||
write++;
|
||||
}
|
||||
break;
|
||||
|
||||
case URI_BR_DONT_TOUCH:
|
||||
default:
|
||||
write[0] = (URI_CHAR)10;
|
||||
write++;
|
||||
|
||||
}
|
||||
prevWasCr = URI_FALSE;
|
||||
break;
|
||||
|
||||
case 13:
|
||||
switch (breakConversion) {
|
||||
case URI_BR_TO_LF:
|
||||
write[0] = (URI_CHAR)10;
|
||||
write++;
|
||||
break;
|
||||
|
||||
case URI_BR_TO_CRLF:
|
||||
write[0] = (URI_CHAR)13;
|
||||
write[1] = (URI_CHAR)10;
|
||||
write += 2;
|
||||
break;
|
||||
|
||||
case URI_BR_TO_CR:
|
||||
write[0] = (URI_CHAR)13;
|
||||
write++;
|
||||
break;
|
||||
|
||||
case URI_BR_DONT_TOUCH:
|
||||
default:
|
||||
write[0] = (URI_CHAR)13;
|
||||
write++;
|
||||
|
||||
}
|
||||
prevWasCr = URI_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
write[0] = (URI_CHAR)(code);
|
||||
write++;
|
||||
|
||||
prevWasCr = URI_FALSE;
|
||||
|
||||
}
|
||||
read += 3;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Copy two chars unmodified and */
|
||||
/* look at this char again */
|
||||
if (read > write) {
|
||||
write[0] = read[0];
|
||||
write[1] = read[1];
|
||||
}
|
||||
read += 2;
|
||||
write += 2;
|
||||
|
||||
prevWasCr = URI_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Copy one char unmodified and */
|
||||
/* look at this char again */
|
||||
if (read > write) {
|
||||
write[0] = read[0];
|
||||
}
|
||||
read++;
|
||||
write++;
|
||||
|
||||
prevWasCr = URI_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case _UT('+'):
|
||||
if (plusToSpace) {
|
||||
/* Convert '+' to ' ' */
|
||||
write[0] = _UT(' ');
|
||||
} else {
|
||||
/* Copy one char unmodified */
|
||||
if (read > write) {
|
||||
write[0] = read[0];
|
||||
}
|
||||
}
|
||||
read++;
|
||||
write++;
|
||||
|
||||
prevWasCr = URI_FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Copy one char unmodified */
|
||||
if (read > write) {
|
||||
write[0] = read[0];
|
||||
}
|
||||
read++;
|
||||
write++;
|
||||
|
||||
prevWasCr = URI_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
242
ext/uri/uriparser/src/UriFile.c
Normal file
242
ext/uri/uriparser/src/UriFile.c
Normal file
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriFile.c"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriFile.c"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_PASS_ANSI
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# include <wchar.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/Uri.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h> /* for size_t, avoiding stddef.h for older MSVCs */
|
||||
|
||||
|
||||
|
||||
static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename,
|
||||
URI_CHAR * uriString, UriBool fromUnix) {
|
||||
const URI_CHAR * input = filename;
|
||||
const URI_CHAR * lastSep = input - 1;
|
||||
UriBool firstSegment = URI_TRUE;
|
||||
URI_CHAR * output = uriString;
|
||||
UriBool absolute;
|
||||
UriBool is_windows_network;
|
||||
|
||||
if ((filename == NULL) || (uriString == NULL)) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
is_windows_network = (filename[0] == _UT('\\')) && (filename[1] == _UT('\\'));
|
||||
absolute = fromUnix
|
||||
? (filename[0] == _UT('/'))
|
||||
: (((filename[0] != _UT('\0')) && (filename[1] == _UT(':')))
|
||||
|| is_windows_network);
|
||||
|
||||
if (absolute) {
|
||||
const URI_CHAR * const prefix = fromUnix
|
||||
? _UT("file://")
|
||||
: is_windows_network
|
||||
? _UT("file:")
|
||||
: _UT("file:///");
|
||||
const size_t prefixLen = URI_STRLEN(prefix);
|
||||
|
||||
/* Copy prefix */
|
||||
memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR));
|
||||
output += prefixLen;
|
||||
}
|
||||
|
||||
/* Copy and escape on the fly */
|
||||
for (;;) {
|
||||
if ((input[0] == _UT('\0'))
|
||||
|| (fromUnix && input[0] == _UT('/'))
|
||||
|| (!fromUnix && input[0] == _UT('\\'))) {
|
||||
/* Copy text after last separator */
|
||||
if (lastSep + 1 < input) {
|
||||
if (!fromUnix && absolute && (firstSegment == URI_TRUE)) {
|
||||
/* Quick hack to not convert "C:" to "C%3A" */
|
||||
const int charsToCopy = (int)(input - (lastSep + 1));
|
||||
memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR));
|
||||
output += charsToCopy;
|
||||
} else {
|
||||
output = URI_FUNC(EscapeEx)(lastSep + 1, input, output,
|
||||
URI_FALSE, URI_FALSE);
|
||||
}
|
||||
}
|
||||
firstSegment = URI_FALSE;
|
||||
}
|
||||
|
||||
if (input[0] == _UT('\0')) {
|
||||
output[0] = _UT('\0');
|
||||
break;
|
||||
} else if (fromUnix && (input[0] == _UT('/'))) {
|
||||
/* Copy separators unmodified */
|
||||
output[0] = _UT('/');
|
||||
output++;
|
||||
lastSep = input;
|
||||
} else if (!fromUnix && (input[0] == _UT('\\'))) {
|
||||
/* Convert backslashes to forward slashes */
|
||||
output[0] = _UT('/');
|
||||
output++;
|
||||
lastSep = input;
|
||||
}
|
||||
input++;
|
||||
}
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE int URI_FUNC(UriStringToFilename)(const URI_CHAR * uriString,
|
||||
URI_CHAR * filename, UriBool toUnix) {
|
||||
if ((uriString == NULL) || (filename == NULL)) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
{
|
||||
const UriBool file_unknown_slashes =
|
||||
URI_STRNCMP(uriString, _UT("file:"), URI_STRLEN(_UT("file:"))) == 0;
|
||||
const UriBool file_one_or_more_slashes = file_unknown_slashes
|
||||
&& (URI_STRNCMP(uriString, _UT("file:/"), URI_STRLEN(_UT("file:/"))) == 0);
|
||||
const UriBool file_two_or_more_slashes = file_one_or_more_slashes
|
||||
&& (URI_STRNCMP(uriString, _UT("file://"), URI_STRLEN(_UT("file://"))) == 0);
|
||||
const UriBool file_three_or_more_slashes = file_two_or_more_slashes
|
||||
&& (URI_STRNCMP(uriString, _UT("file:///"), URI_STRLEN(_UT("file:///"))) == 0);
|
||||
|
||||
const size_t charsToSkip = file_two_or_more_slashes
|
||||
? file_three_or_more_slashes
|
||||
? toUnix
|
||||
/* file:///bin/bash */
|
||||
? URI_STRLEN(_UT("file://"))
|
||||
/* file:///E:/Documents%20and%20Settings */
|
||||
: URI_STRLEN(_UT("file:///"))
|
||||
/* file://Server01/Letter.txt */
|
||||
: URI_STRLEN(_UT("file://"))
|
||||
: ((file_one_or_more_slashes && toUnix)
|
||||
/* file:/bin/bash */
|
||||
/* https://tools.ietf.org/html/rfc8089#appendix-B */
|
||||
? URI_STRLEN(_UT("file:"))
|
||||
: ((! toUnix && file_unknown_slashes && ! file_one_or_more_slashes)
|
||||
/* file:c:/path/to/file */
|
||||
/* https://tools.ietf.org/html/rfc8089#appendix-E.2 */
|
||||
? URI_STRLEN(_UT("file:"))
|
||||
: 0));
|
||||
const size_t charsToCopy = URI_STRLEN(uriString + charsToSkip) + 1;
|
||||
|
||||
const UriBool is_windows_network_with_authority =
|
||||
(toUnix == URI_FALSE)
|
||||
&& file_two_or_more_slashes
|
||||
&& ! file_three_or_more_slashes;
|
||||
|
||||
URI_CHAR * const unescape_target = is_windows_network_with_authority
|
||||
? (filename + 2)
|
||||
: filename;
|
||||
|
||||
if (is_windows_network_with_authority) {
|
||||
filename[0] = '\\';
|
||||
filename[1] = '\\';
|
||||
}
|
||||
|
||||
memcpy(unescape_target, uriString + charsToSkip, charsToCopy * sizeof(URI_CHAR));
|
||||
URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH);
|
||||
}
|
||||
|
||||
/* Convert forward slashes to backslashes */
|
||||
if (!toUnix) {
|
||||
URI_CHAR * walker = filename;
|
||||
while (walker[0] != _UT('\0')) {
|
||||
if (walker[0] == _UT('/')) {
|
||||
walker[0] = _UT('\\');
|
||||
}
|
||||
walker++;
|
||||
}
|
||||
}
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) {
|
||||
return URI_FUNC(FilenameToUriString)(filename, uriString, URI_TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) {
|
||||
return URI_FUNC(FilenameToUriString)(filename, uriString, URI_FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, URI_CHAR * filename) {
|
||||
return URI_FUNC(UriStringToFilename)(uriString, filename, URI_TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, URI_CHAR * filename) {
|
||||
return URI_FUNC(UriStringToFilename)(uriString, filename, URI_FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
329
ext/uri/uriparser/src/UriIp4.c
Normal file
329
ext/uri/uriparser/src/UriIp4.c
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file UriIp4.c
|
||||
* Holds the IPv4 parser implementation.
|
||||
* NOTE: This source file includes itself twice.
|
||||
*/
|
||||
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriIp4.c"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriIp4.c"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_PASS_ANSI
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/UriIp4.h>
|
||||
# include "UriIp4Base.h"
|
||||
# include <uriparser/UriBase.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Prototypes */
|
||||
static const URI_CHAR * URI_FUNC(ParseDecOctet)(UriIp4Parser * parser,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast);
|
||||
static const URI_CHAR * URI_FUNC(ParseDecOctetOne)(UriIp4Parser * parser,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast);
|
||||
static const URI_CHAR * URI_FUNC(ParseDecOctetTwo)(UriIp4Parser * parser,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast);
|
||||
static const URI_CHAR * URI_FUNC(ParseDecOctetThree)(UriIp4Parser * parser,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast);
|
||||
static const URI_CHAR * URI_FUNC(ParseDecOctetFour)(UriIp4Parser * parser,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* [ipFourAddress]->[decOctet]<.>[decOctet]<.>[decOctet]<.>[decOctet]
|
||||
*/
|
||||
int URI_FUNC(ParseIpFourAddress)(unsigned char * octetOutput,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast) {
|
||||
const URI_CHAR * after;
|
||||
UriIp4Parser parser;
|
||||
|
||||
/* Essential checks */
|
||||
if ((octetOutput == NULL) || (first == NULL)
|
||||
|| (afterLast <= first)) {
|
||||
return URI_ERROR_SYNTAX;
|
||||
}
|
||||
|
||||
/* Reset parser */
|
||||
parser.stackCount = 0;
|
||||
|
||||
/* Octet #1 */
|
||||
after = URI_FUNC(ParseDecOctet)(&parser, first, afterLast);
|
||||
if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) {
|
||||
return URI_ERROR_SYNTAX;
|
||||
}
|
||||
uriStackToOctet(&parser, octetOutput);
|
||||
|
||||
/* Octet #2 */
|
||||
after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast);
|
||||
if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) {
|
||||
return URI_ERROR_SYNTAX;
|
||||
}
|
||||
uriStackToOctet(&parser, octetOutput + 1);
|
||||
|
||||
/* Octet #3 */
|
||||
after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast);
|
||||
if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) {
|
||||
return URI_ERROR_SYNTAX;
|
||||
}
|
||||
uriStackToOctet(&parser, octetOutput + 2);
|
||||
|
||||
/* Octet #4 */
|
||||
after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast);
|
||||
if (after != afterLast) {
|
||||
return URI_ERROR_SYNTAX;
|
||||
}
|
||||
uriStackToOctet(&parser, octetOutput + 3);
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* [decOctet]-><0>
|
||||
* [decOctet]-><1>[decOctetOne]
|
||||
* [decOctet]-><2>[decOctetTwo]
|
||||
* [decOctet]-><3>[decOctetThree]
|
||||
* [decOctet]-><4>[decOctetThree]
|
||||
* [decOctet]-><5>[decOctetThree]
|
||||
* [decOctet]-><6>[decOctetThree]
|
||||
* [decOctet]-><7>[decOctetThree]
|
||||
* [decOctet]-><8>[decOctetThree]
|
||||
* [decOctet]-><9>[decOctetThree]
|
||||
*/
|
||||
static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctet)(UriIp4Parser * parser,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast) {
|
||||
if (first >= afterLast) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (*first) {
|
||||
case _UT('0'):
|
||||
uriPushToStack(parser, 0);
|
||||
return first + 1;
|
||||
|
||||
case _UT('1'):
|
||||
uriPushToStack(parser, 1);
|
||||
return (const URI_CHAR *)URI_FUNC(ParseDecOctetOne)(parser, first + 1, afterLast);
|
||||
|
||||
case _UT('2'):
|
||||
uriPushToStack(parser, 2);
|
||||
return (const URI_CHAR *)URI_FUNC(ParseDecOctetTwo)(parser, first + 1, afterLast);
|
||||
|
||||
case _UT('3'):
|
||||
case _UT('4'):
|
||||
case _UT('5'):
|
||||
case _UT('6'):
|
||||
case _UT('7'):
|
||||
case _UT('8'):
|
||||
case _UT('9'):
|
||||
uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9')));
|
||||
return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, afterLast);
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* [decOctetOne]-><NULL>
|
||||
* [decOctetOne]->[DIGIT][decOctetThree]
|
||||
*/
|
||||
static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetOne)(UriIp4Parser * parser,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast) {
|
||||
if (first >= afterLast) {
|
||||
return afterLast;
|
||||
}
|
||||
|
||||
switch (*first) {
|
||||
case _UT('0'):
|
||||
case _UT('1'):
|
||||
case _UT('2'):
|
||||
case _UT('3'):
|
||||
case _UT('4'):
|
||||
case _UT('5'):
|
||||
case _UT('6'):
|
||||
case _UT('7'):
|
||||
case _UT('8'):
|
||||
case _UT('9'):
|
||||
uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9')));
|
||||
return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, afterLast);
|
||||
|
||||
default:
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* [decOctetTwo]-><NULL>
|
||||
* [decOctetTwo]-><0>[decOctetThree]
|
||||
* [decOctetTwo]-><1>[decOctetThree]
|
||||
* [decOctetTwo]-><2>[decOctetThree]
|
||||
* [decOctetTwo]-><3>[decOctetThree]
|
||||
* [decOctetTwo]-><4>[decOctetThree]
|
||||
* [decOctetTwo]-><5>[decOctetFour]
|
||||
* [decOctetTwo]-><6>
|
||||
* [decOctetTwo]-><7>
|
||||
* [decOctetTwo]-><8>
|
||||
* [decOctetTwo]-><9>
|
||||
*/
|
||||
static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetTwo)(UriIp4Parser * parser,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast) {
|
||||
if (first >= afterLast) {
|
||||
return afterLast;
|
||||
}
|
||||
|
||||
switch (*first) {
|
||||
case _UT('0'):
|
||||
case _UT('1'):
|
||||
case _UT('2'):
|
||||
case _UT('3'):
|
||||
case _UT('4'):
|
||||
uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9')));
|
||||
return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, afterLast);
|
||||
|
||||
case _UT('5'):
|
||||
uriPushToStack(parser, 5);
|
||||
return (const URI_CHAR *)URI_FUNC(ParseDecOctetFour)(parser, first + 1, afterLast);
|
||||
|
||||
case _UT('6'):
|
||||
case _UT('7'):
|
||||
case _UT('8'):
|
||||
case _UT('9'):
|
||||
uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9')));
|
||||
return first + 1;
|
||||
|
||||
default:
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* [decOctetThree]-><NULL>
|
||||
* [decOctetThree]->[DIGIT]
|
||||
*/
|
||||
static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetThree)(UriIp4Parser * parser,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast) {
|
||||
if (first >= afterLast) {
|
||||
return afterLast;
|
||||
}
|
||||
|
||||
switch (*first) {
|
||||
case _UT('0'):
|
||||
case _UT('1'):
|
||||
case _UT('2'):
|
||||
case _UT('3'):
|
||||
case _UT('4'):
|
||||
case _UT('5'):
|
||||
case _UT('6'):
|
||||
case _UT('7'):
|
||||
case _UT('8'):
|
||||
case _UT('9'):
|
||||
uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9')));
|
||||
return first + 1;
|
||||
|
||||
default:
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* [decOctetFour]-><NULL>
|
||||
* [decOctetFour]-><0>
|
||||
* [decOctetFour]-><1>
|
||||
* [decOctetFour]-><2>
|
||||
* [decOctetFour]-><3>
|
||||
* [decOctetFour]-><4>
|
||||
* [decOctetFour]-><5>
|
||||
*/
|
||||
static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetFour)(UriIp4Parser * parser,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast) {
|
||||
if (first >= afterLast) {
|
||||
return afterLast;
|
||||
}
|
||||
|
||||
switch (*first) {
|
||||
case _UT('0'):
|
||||
case _UT('1'):
|
||||
case _UT('2'):
|
||||
case _UT('3'):
|
||||
case _UT('4'):
|
||||
case _UT('5'):
|
||||
uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9')));
|
||||
return first + 1;
|
||||
|
||||
default:
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
96
ext/uri/uriparser/src/UriIp4Base.c
Normal file
96
ext/uri/uriparser/src/UriIp4Base.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file UriIp4Base.c
|
||||
* Holds code independent of the encoding pass.
|
||||
*/
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include "UriIp4Base.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void uriStackToOctet(UriIp4Parser * parser, unsigned char * octet) {
|
||||
switch (parser->stackCount) {
|
||||
case 1:
|
||||
*octet = parser->stackOne;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*octet = parser->stackOne * 10
|
||||
+ parser->stackTwo;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
*octet = parser->stackOne * 100
|
||||
+ parser->stackTwo * 10
|
||||
+ parser->stackThree;
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
parser->stackCount = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uriPushToStack(UriIp4Parser * parser, unsigned char digit) {
|
||||
switch (parser->stackCount) {
|
||||
case 0:
|
||||
parser->stackOne = digit;
|
||||
parser->stackCount = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
parser->stackTwo = digit;
|
||||
parser->stackCount = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
parser->stackThree = digit;
|
||||
parser->stackCount = 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
59
ext/uri/uriparser/src/UriIp4Base.h
Normal file
59
ext/uri/uriparser/src/UriIp4Base.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef URI_IP4_BASE_H
|
||||
#define URI_IP4_BASE_H 1
|
||||
|
||||
|
||||
|
||||
typedef struct UriIp4ParserStruct {
|
||||
unsigned char stackCount;
|
||||
unsigned char stackOne;
|
||||
unsigned char stackTwo;
|
||||
unsigned char stackThree;
|
||||
} UriIp4Parser;
|
||||
|
||||
|
||||
|
||||
void uriPushToStack(UriIp4Parser * parser, unsigned char digit);
|
||||
void uriStackToOctet(UriIp4Parser * parser, unsigned char * octet);
|
||||
|
||||
|
||||
|
||||
#endif /* URI_IP4_BASE_H */
|
471
ext/uri/uriparser/src/UriMemory.c
Normal file
471
ext/uri/uriparser/src/UriMemory.c
Normal file
|
@ -0,0 +1,471 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2018, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2018, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file UriMemory.c
|
||||
* Holds memory manager implementation.
|
||||
*/
|
||||
|
||||
#include "UriConfig.h" /* for HAVE_REALLOCARRAY */
|
||||
|
||||
#ifdef HAVE_REALLOCARRAY
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
# endif
|
||||
# ifdef __NetBSD__
|
||||
# define _OPENBSD_SOURCE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include "UriMemory.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size) \
|
||||
do { \
|
||||
/* check for unsigned overflow */ \
|
||||
if ((nmemb != 0) && (total_size / nmemb != size)) { \
|
||||
errno = ENOMEM; \
|
||||
return NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
static void * uriDefaultMalloc(UriMemoryManager * URI_UNUSED(memory),
|
||||
size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void * uriDefaultCalloc(UriMemoryManager * URI_UNUSED(memory),
|
||||
size_t nmemb, size_t size) {
|
||||
return calloc(nmemb, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void * uriDefaultRealloc(UriMemoryManager * URI_UNUSED(memory),
|
||||
void * ptr, size_t size) {
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void * uriDefaultReallocarray(UriMemoryManager * URI_UNUSED(memory),
|
||||
void * ptr, size_t nmemb, size_t size) {
|
||||
#ifdef HAVE_REALLOCARRAY
|
||||
return reallocarray(ptr, nmemb, size);
|
||||
#else
|
||||
const size_t total_size = nmemb * size;
|
||||
|
||||
URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size); /* may return */
|
||||
|
||||
return realloc(ptr, total_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void uriDefaultFree(UriMemoryManager * URI_UNUSED(memory),
|
||||
void * ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
UriBool uriMemoryManagerIsComplete(const UriMemoryManager * memory) {
|
||||
return (memory
|
||||
&& memory->malloc
|
||||
&& memory->calloc
|
||||
&& memory->realloc
|
||||
&& memory->reallocarray
|
||||
&& memory->free) ? URI_TRUE : URI_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void * uriEmulateCalloc(UriMemoryManager * memory, size_t nmemb, size_t size) {
|
||||
void * buffer;
|
||||
const size_t total_size = nmemb * size;
|
||||
|
||||
if (memory == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size); /* may return */
|
||||
|
||||
buffer = memory->malloc(memory, total_size);
|
||||
if (buffer == NULL) {
|
||||
/* errno set by malloc */
|
||||
return NULL;
|
||||
}
|
||||
memset(buffer, 0, total_size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void * uriEmulateReallocarray(UriMemoryManager * memory,
|
||||
void * ptr, size_t nmemb, size_t size) {
|
||||
const size_t total_size = nmemb * size;
|
||||
|
||||
if (memory == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
URI_CHECK_ALLOC_OVERFLOW(total_size, nmemb, size); /* may return */
|
||||
|
||||
return memory->realloc(memory, ptr, total_size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void * uriDecorateMalloc(UriMemoryManager * memory,
|
||||
size_t size) {
|
||||
UriMemoryManager * backend;
|
||||
const size_t extraBytes = sizeof(size_t);
|
||||
void * buffer;
|
||||
|
||||
if (memory == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check for unsigned overflow */
|
||||
if (size > ((size_t)-1) - extraBytes) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
backend = (UriMemoryManager *)memory->userData;
|
||||
if (backend == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = backend->malloc(backend, extraBytes + size);
|
||||
if (buffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*(size_t *)buffer = size;
|
||||
|
||||
return (char *)buffer + extraBytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void * uriDecorateRealloc(UriMemoryManager * memory,
|
||||
void * ptr, size_t size) {
|
||||
void * newBuffer;
|
||||
size_t prevSize;
|
||||
|
||||
if (memory == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* man realloc: "If ptr is NULL, then the call is equivalent to
|
||||
* malloc(size), for *all* values of size" */
|
||||
if (ptr == NULL) {
|
||||
return memory->malloc(memory, size);
|
||||
}
|
||||
|
||||
/* man realloc: "If size is equal to zero, and ptr is *not* NULL,
|
||||
* then the call is equivalent to free(ptr)." */
|
||||
if (size == 0) {
|
||||
memory->free(memory, ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prevSize = *((size_t *)((char *)ptr - sizeof(size_t)));
|
||||
|
||||
/* Anything to do? */
|
||||
if (size <= prevSize) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
newBuffer = memory->malloc(memory, size);
|
||||
if (newBuffer == NULL) {
|
||||
/* errno set by malloc */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(newBuffer, ptr, prevSize);
|
||||
|
||||
memory->free(memory, ptr);
|
||||
|
||||
return newBuffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void uriDecorateFree(UriMemoryManager * memory, void * ptr) {
|
||||
UriMemoryManager * backend;
|
||||
|
||||
if ((ptr == NULL) || (memory == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
backend = (UriMemoryManager *)memory->userData;
|
||||
if (backend == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
backend->free(backend, (char *)ptr - sizeof(size_t));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uriCompleteMemoryManager(UriMemoryManager * memory,
|
||||
UriMemoryManager * backend) {
|
||||
if ((memory == NULL) || (backend == NULL)) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
if ((backend->malloc == NULL) || (backend->free == NULL)) {
|
||||
return URI_ERROR_MEMORY_MANAGER_INCOMPLETE;
|
||||
}
|
||||
|
||||
memory->calloc = uriEmulateCalloc;
|
||||
memory->reallocarray = uriEmulateReallocarray;
|
||||
|
||||
memory->malloc = uriDecorateMalloc;
|
||||
memory->realloc = uriDecorateRealloc;
|
||||
memory->free = uriDecorateFree;
|
||||
|
||||
memory->userData = backend;
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uriTestMemoryManager(UriMemoryManager * memory) {
|
||||
const size_t mallocSize = 7;
|
||||
const size_t callocNmemb = 3;
|
||||
const size_t callocSize = 5;
|
||||
const size_t callocTotalSize = callocNmemb * callocSize;
|
||||
const size_t reallocSize = 11;
|
||||
const size_t reallocarrayNmemb = 5;
|
||||
const size_t reallocarraySize = 7;
|
||||
const size_t reallocarrayTotal = reallocarrayNmemb * reallocarraySize;
|
||||
size_t index;
|
||||
char * buffer;
|
||||
|
||||
if (memory == NULL) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
if (uriMemoryManagerIsComplete(memory) != URI_TRUE) {
|
||||
return URI_ERROR_MEMORY_MANAGER_INCOMPLETE;
|
||||
}
|
||||
|
||||
/* malloc + free*/
|
||||
buffer = memory->malloc(memory, mallocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
buffer[mallocSize - 1] = '\xF1';
|
||||
memory->free(memory, buffer);
|
||||
buffer = NULL;
|
||||
|
||||
/* calloc + free */
|
||||
buffer = memory->calloc(memory, callocNmemb, callocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
for (index = 0; index < callocTotalSize; index++) { /* all zeros? */
|
||||
if (buffer[index] != '\0') {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
}
|
||||
buffer[callocTotalSize - 1] = '\xF2';
|
||||
memory->free(memory, buffer);
|
||||
buffer = NULL;
|
||||
|
||||
/* malloc + realloc + free */
|
||||
buffer = memory->malloc(memory, mallocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
for (index = 0; index < mallocSize; index++) {
|
||||
buffer[index] = '\xF3';
|
||||
}
|
||||
buffer = memory->realloc(memory, buffer, reallocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
for (index = 0; index < mallocSize; index++) { /* previous content? */
|
||||
if (buffer[index] != '\xF3') {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
}
|
||||
buffer[reallocSize - 1] = '\xF4';
|
||||
memory->free(memory, buffer);
|
||||
buffer = NULL;
|
||||
|
||||
/* malloc + realloc ptr!=NULL size==0 (equals free) */
|
||||
buffer = memory->malloc(memory, mallocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
buffer[mallocSize - 1] = '\xF5';
|
||||
memory->realloc(memory, buffer, 0);
|
||||
buffer = NULL;
|
||||
|
||||
/* realloc ptr==NULL size!=0 (equals malloc) + free */
|
||||
buffer = memory->realloc(memory, NULL, mallocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
buffer[mallocSize - 1] = '\xF6';
|
||||
memory->free(memory, buffer);
|
||||
buffer = NULL;
|
||||
|
||||
/* realloc ptr==NULL size==0 (equals malloc) + free */
|
||||
buffer = memory->realloc(memory, NULL, 0);
|
||||
if (buffer != NULL) {
|
||||
memory->free(memory, buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
/* malloc + reallocarray + free */
|
||||
buffer = memory->malloc(memory, mallocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
for (index = 0; index < mallocSize; index++) {
|
||||
buffer[index] = '\xF7';
|
||||
}
|
||||
buffer = memory->reallocarray(memory, buffer, reallocarrayNmemb,
|
||||
reallocarraySize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
for (index = 0; index < mallocSize; index++) { /* previous content? */
|
||||
if (buffer[index] != '\xF7') {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
}
|
||||
buffer[reallocarrayTotal - 1] = '\xF8';
|
||||
memory->free(memory, buffer);
|
||||
buffer = NULL;
|
||||
|
||||
/* malloc + reallocarray ptr!=NULL nmemb==0 size!=0 (equals free) */
|
||||
buffer = memory->malloc(memory, mallocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
buffer[mallocSize - 1] = '\xF9';
|
||||
memory->reallocarray(memory, buffer, 0, reallocarraySize);
|
||||
buffer = NULL;
|
||||
|
||||
/* malloc + reallocarray ptr!=NULL nmemb!=0 size==0 (equals free) */
|
||||
buffer = memory->malloc(memory, mallocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
buffer[mallocSize - 1] = '\xFA';
|
||||
memory->reallocarray(memory, buffer, reallocarrayNmemb, 0);
|
||||
buffer = NULL;
|
||||
|
||||
/* malloc + reallocarray ptr!=NULL nmemb==0 size==0 (equals free) */
|
||||
buffer = memory->malloc(memory, mallocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
buffer[mallocSize - 1] = '\xFB';
|
||||
memory->reallocarray(memory, buffer, 0, 0);
|
||||
buffer = NULL;
|
||||
|
||||
/* reallocarray ptr==NULL nmemb!=0 size!=0 (equals malloc) + free */
|
||||
buffer = memory->reallocarray(memory, NULL, callocNmemb, callocSize);
|
||||
if (buffer == NULL) {
|
||||
return URI_ERROR_MEMORY_MANAGER_FAULTY;
|
||||
}
|
||||
buffer[callocTotalSize - 1] = '\xFC';
|
||||
memory->free(memory, buffer);
|
||||
buffer = NULL;
|
||||
|
||||
/* reallocarray ptr==NULL nmemb==0 size!=0 (equals malloc) + free */
|
||||
buffer = memory->reallocarray(memory, NULL, 0, callocSize);
|
||||
if (buffer != NULL) {
|
||||
memory->free(memory, buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
/* reallocarray ptr==NULL nmemb!=0 size==0 (equals malloc) + free */
|
||||
buffer = memory->reallocarray(memory, NULL, callocNmemb, 0);
|
||||
if (buffer != NULL) {
|
||||
memory->free(memory, buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
/* reallocarray ptr==NULL nmemb==0 size==0 (equals malloc) + free */
|
||||
buffer = memory->reallocarray(memory, NULL, 0, 0);
|
||||
if (buffer != NULL) {
|
||||
memory->free(memory, buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*extern*/ UriMemoryManager defaultMemoryManager = {
|
||||
uriDefaultMalloc,
|
||||
uriDefaultCalloc,
|
||||
uriDefaultRealloc,
|
||||
uriDefaultReallocarray,
|
||||
uriDefaultFree,
|
||||
NULL /* userData */
|
||||
};
|
78
ext/uri/uriparser/src/UriMemory.h
Normal file
78
ext/uri/uriparser/src/UriMemory.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2018, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2018, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef URI_MEMORY_H
|
||||
#define URI_MEMORY_H 1
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/Uri.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define URI_CHECK_MEMORY_MANAGER(memory) \
|
||||
do { \
|
||||
if (memory == NULL) { \
|
||||
memory = &defaultMemoryManager; \
|
||||
} else if (uriMemoryManagerIsComplete(memory) != URI_TRUE) { \
|
||||
return URI_ERROR_MEMORY_MANAGER_INCOMPLETE; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define URIPARSER_EXTERN extern "C"
|
||||
#else
|
||||
# define URIPARSER_EXTERN extern
|
||||
#endif
|
||||
|
||||
URIPARSER_EXTERN UriMemoryManager defaultMemoryManager;
|
||||
|
||||
#undef URIPARSER_EXTERN
|
||||
|
||||
|
||||
|
||||
UriBool uriMemoryManagerIsComplete(const UriMemoryManager * memory);
|
||||
|
||||
|
||||
|
||||
#endif /* URI_MEMORY_H */
|
830
ext/uri/uriparser/src/UriNormalize.c
Normal file
830
ext/uri/uriparser/src/UriNormalize.c
Normal file
|
@ -0,0 +1,830 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file UriNormalize.c
|
||||
* Holds the RFC 3986 %URI normalization implementation.
|
||||
* NOTE: This source file includes itself twice.
|
||||
*/
|
||||
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriNormalize.c"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriNormalize.c"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_PASS_ANSI
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# include <wchar.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/Uri.h>
|
||||
# include "UriNormalizeBase.h"
|
||||
# include "UriCommon.h"
|
||||
# include "UriMemory.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
|
||||
static int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask,
|
||||
unsigned int * outMask, UriMemoryManager * memory);
|
||||
|
||||
static UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask,
|
||||
unsigned int maskTest, URI_TYPE(TextRange) * range,
|
||||
UriMemoryManager * memory);
|
||||
static UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri,
|
||||
unsigned int * doneMask, UriMemoryManager * memory);
|
||||
|
||||
static void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * first,
|
||||
const URI_CHAR ** afterLast);
|
||||
static UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first,
|
||||
const URI_CHAR ** afterLast, UriMemoryManager * memory);
|
||||
static void URI_FUNC(FixPercentEncodingEngine)(
|
||||
const URI_CHAR * inFirst, const URI_CHAR * inAfterLast,
|
||||
const URI_CHAR * outFirst, const URI_CHAR ** outAfterLast);
|
||||
|
||||
static UriBool URI_FUNC(ContainsUppercaseLetters)(const URI_CHAR * first,
|
||||
const URI_CHAR * afterLast);
|
||||
static UriBool URI_FUNC(ContainsUglyPercentEncoding)(const URI_CHAR * first,
|
||||
const URI_CHAR * afterLast);
|
||||
|
||||
static void URI_FUNC(LowercaseInplace)(const URI_CHAR * first,
|
||||
const URI_CHAR * afterLast);
|
||||
static void URI_FUNC(LowercaseInplaceExceptPercentEncoding)(const URI_CHAR * first,
|
||||
const URI_CHAR * afterLast);
|
||||
static UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first,
|
||||
const URI_CHAR ** afterLast, UriMemoryManager * memory);
|
||||
|
||||
static void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,
|
||||
unsigned int revertMask, UriMemoryManager * memory);
|
||||
|
||||
|
||||
|
||||
static URI_INLINE void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,
|
||||
unsigned int revertMask, UriMemoryManager * memory) {
|
||||
if (revertMask & URI_NORMALIZE_SCHEME) {
|
||||
/* NOTE: A scheme cannot be the empty string
|
||||
* so no need to compare .first with .afterLast, here. */
|
||||
memory->free(memory, (URI_CHAR *)uri->scheme.first);
|
||||
uri->scheme.first = NULL;
|
||||
uri->scheme.afterLast = NULL;
|
||||
}
|
||||
|
||||
if (revertMask & URI_NORMALIZE_USER_INFO) {
|
||||
if (uri->userInfo.first != uri->userInfo.afterLast) {
|
||||
memory->free(memory, (URI_CHAR *)uri->userInfo.first);
|
||||
}
|
||||
uri->userInfo.first = NULL;
|
||||
uri->userInfo.afterLast = NULL;
|
||||
}
|
||||
|
||||
if (revertMask & URI_NORMALIZE_HOST) {
|
||||
if (uri->hostData.ipFuture.first != NULL) {
|
||||
/* IPvFuture */
|
||||
/* NOTE: An IPvFuture address cannot be the empty string
|
||||
* so no need to compare .first with .afterLast, here. */
|
||||
memory->free(memory, (URI_CHAR *)uri->hostData.ipFuture.first);
|
||||
uri->hostData.ipFuture.first = NULL;
|
||||
uri->hostData.ipFuture.afterLast = NULL;
|
||||
uri->hostText.first = NULL;
|
||||
uri->hostText.afterLast = NULL;
|
||||
} else if (uri->hostText.first != NULL) {
|
||||
/* Regname */
|
||||
if (uri->hostText.first != uri->hostText.afterLast) {
|
||||
memory->free(memory, (URI_CHAR *)uri->hostText.first);
|
||||
}
|
||||
uri->hostText.first = NULL;
|
||||
uri->hostText.afterLast = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: Port cannot happen! */
|
||||
|
||||
if (revertMask & URI_NORMALIZE_PATH) {
|
||||
URI_TYPE(PathSegment) * walker = uri->pathHead;
|
||||
while (walker != NULL) {
|
||||
URI_TYPE(PathSegment) * const next = walker->next;
|
||||
if (walker->text.afterLast > walker->text.first) {
|
||||
memory->free(memory, (URI_CHAR *)walker->text.first);
|
||||
}
|
||||
memory->free(memory, walker);
|
||||
walker = next;
|
||||
}
|
||||
uri->pathHead = NULL;
|
||||
uri->pathTail = NULL;
|
||||
}
|
||||
|
||||
if (revertMask & URI_NORMALIZE_QUERY) {
|
||||
if (uri->query.first != uri->query.afterLast) {
|
||||
memory->free(memory, (URI_CHAR *)uri->query.first);
|
||||
}
|
||||
uri->query.first = NULL;
|
||||
uri->query.afterLast = NULL;
|
||||
}
|
||||
|
||||
if (revertMask & URI_NORMALIZE_FRAGMENT) {
|
||||
if (uri->fragment.first != uri->fragment.afterLast) {
|
||||
memory->free(memory, (URI_CHAR *)uri->fragment.first);
|
||||
}
|
||||
uri->fragment.first = NULL;
|
||||
uri->fragment.afterLast = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE UriBool URI_FUNC(ContainsUppercaseLetters)(const URI_CHAR * first,
|
||||
const URI_CHAR * afterLast) {
|
||||
if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {
|
||||
const URI_CHAR * i = first;
|
||||
for (; i < afterLast; i++) {
|
||||
/* 6.2.2.1 Case Normalization: uppercase letters in scheme or host */
|
||||
if ((*i >= _UT('A')) && (*i <= _UT('Z'))) {
|
||||
return URI_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE UriBool URI_FUNC(ContainsUglyPercentEncoding)(const URI_CHAR * first,
|
||||
const URI_CHAR * afterLast) {
|
||||
if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {
|
||||
const URI_CHAR * i = first;
|
||||
for (; i + 2 < afterLast; i++) {
|
||||
if (i[0] == _UT('%')) {
|
||||
/* 6.2.2.1 Case Normalization: *
|
||||
* lowercase percent-encodings */
|
||||
if (((i[1] >= _UT('a')) && (i[1] <= _UT('f')))
|
||||
|| ((i[2] >= _UT('a')) && (i[2] <= _UT('f')))) {
|
||||
return URI_TRUE;
|
||||
} else {
|
||||
/* 6.2.2.2 Percent-Encoding Normalization: *
|
||||
* percent-encoded unreserved characters */
|
||||
const unsigned char left = URI_FUNC(HexdigToInt)(i[1]);
|
||||
const unsigned char right = URI_FUNC(HexdigToInt)(i[2]);
|
||||
const int code = 16 * left + right;
|
||||
if (uriIsUnreserved(code)) {
|
||||
return URI_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE void URI_FUNC(LowercaseInplace)(const URI_CHAR * first,
|
||||
const URI_CHAR * afterLast) {
|
||||
if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {
|
||||
URI_CHAR * i = (URI_CHAR *)first;
|
||||
const int lowerUpperDiff = (_UT('a') - _UT('A'));
|
||||
for (; i < afterLast; i++) {
|
||||
if ((*i >= _UT('A')) && (*i <=_UT('Z'))) {
|
||||
*i = (URI_CHAR)(*i + lowerUpperDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE void URI_FUNC(LowercaseInplaceExceptPercentEncoding)(const URI_CHAR * first,
|
||||
const URI_CHAR * afterLast) {
|
||||
if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {
|
||||
URI_CHAR * i = (URI_CHAR *)first;
|
||||
const int lowerUpperDiff = (_UT('a') - _UT('A'));
|
||||
for (; i < afterLast; i++) {
|
||||
if ((*i >= _UT('A')) && (*i <=_UT('Z'))) {
|
||||
*i = (URI_CHAR)(*i + lowerUpperDiff);
|
||||
} else if (*i == _UT('%')) {
|
||||
if (i + 3 >= afterLast) {
|
||||
return;
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first,
|
||||
const URI_CHAR ** afterLast, UriMemoryManager * memory) {
|
||||
int lenInChars;
|
||||
const int lowerUpperDiff = (_UT('a') - _UT('A'));
|
||||
URI_CHAR * buffer;
|
||||
int i = 0;
|
||||
|
||||
if ((first == NULL) || (afterLast == NULL) || (*first == NULL)
|
||||
|| (*afterLast == NULL)) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
lenInChars = (int)(*afterLast - *first);
|
||||
if (lenInChars == 0) {
|
||||
return URI_TRUE;
|
||||
} else if (lenInChars < 0) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
buffer = memory->malloc(memory, lenInChars * sizeof(URI_CHAR));
|
||||
if (buffer == NULL) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
for (; i < lenInChars; i++) {
|
||||
if (((*first)[i] >= _UT('A')) && ((*first)[i] <=_UT('Z'))) {
|
||||
buffer[i] = (URI_CHAR)((*first)[i] + lowerUpperDiff);
|
||||
} else {
|
||||
buffer[i] = (*first)[i];
|
||||
}
|
||||
}
|
||||
|
||||
*first = buffer;
|
||||
*afterLast = buffer + lenInChars;
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* NOTE: Implementation must stay inplace-compatible */
|
||||
static URI_INLINE void URI_FUNC(FixPercentEncodingEngine)(
|
||||
const URI_CHAR * inFirst, const URI_CHAR * inAfterLast,
|
||||
const URI_CHAR * outFirst, const URI_CHAR ** outAfterLast) {
|
||||
URI_CHAR * write = (URI_CHAR *)outFirst;
|
||||
const int lenInChars = (int)(inAfterLast - inFirst);
|
||||
int i = 0;
|
||||
|
||||
/* All but last two */
|
||||
for (; i + 2 < lenInChars; i++) {
|
||||
if (inFirst[i] != _UT('%')) {
|
||||
write[0] = inFirst[i];
|
||||
write++;
|
||||
} else {
|
||||
/* 6.2.2.2 Percent-Encoding Normalization: *
|
||||
* percent-encoded unreserved characters */
|
||||
const URI_CHAR one = inFirst[i + 1];
|
||||
const URI_CHAR two = inFirst[i + 2];
|
||||
const unsigned char left = URI_FUNC(HexdigToInt)(one);
|
||||
const unsigned char right = URI_FUNC(HexdigToInt)(two);
|
||||
const int code = 16 * left + right;
|
||||
if (uriIsUnreserved(code)) {
|
||||
write[0] = (URI_CHAR)(code);
|
||||
write++;
|
||||
} else {
|
||||
/* 6.2.2.1 Case Normalization: *
|
||||
* lowercase percent-encodings */
|
||||
write[0] = _UT('%');
|
||||
write[1] = URI_FUNC(HexToLetter)(left);
|
||||
write[2] = URI_FUNC(HexToLetter)(right);
|
||||
write += 3;
|
||||
}
|
||||
|
||||
i += 2; /* For the two chars of the percent group we just ate */
|
||||
}
|
||||
}
|
||||
|
||||
/* Last two */
|
||||
for (; i < lenInChars; i++) {
|
||||
write[0] = inFirst[i];
|
||||
write++;
|
||||
}
|
||||
|
||||
*outAfterLast = write;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * first,
|
||||
const URI_CHAR ** afterLast) {
|
||||
/* Death checks */
|
||||
if ((first == NULL) || (afterLast == NULL) || (*afterLast == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fix inplace */
|
||||
URI_FUNC(FixPercentEncodingEngine)(first, *afterLast, first, afterLast);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first,
|
||||
const URI_CHAR ** afterLast, UriMemoryManager * memory) {
|
||||
int lenInChars;
|
||||
URI_CHAR * buffer;
|
||||
|
||||
/* Death checks */
|
||||
if ((first == NULL) || (afterLast == NULL)
|
||||
|| (*first == NULL) || (*afterLast == NULL)) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
/* Old text length */
|
||||
lenInChars = (int)(*afterLast - *first);
|
||||
if (lenInChars == 0) {
|
||||
return URI_TRUE;
|
||||
} else if (lenInChars < 0) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
/* New buffer */
|
||||
buffer = memory->malloc(memory, lenInChars * sizeof(URI_CHAR));
|
||||
if (buffer == NULL) {
|
||||
return URI_FALSE;
|
||||
}
|
||||
|
||||
/* Fix on copy */
|
||||
URI_FUNC(FixPercentEncodingEngine)(*first, *afterLast, buffer, afterLast);
|
||||
*first = buffer;
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask,
|
||||
unsigned int maskTest, URI_TYPE(TextRange) * range,
|
||||
UriMemoryManager * memory) {
|
||||
if (((*doneMask & maskTest) == 0)
|
||||
&& (range->first != NULL)
|
||||
&& (range->afterLast != NULL)
|
||||
&& (range->afterLast > range->first)) {
|
||||
const int lenInChars = (int)(range->afterLast - range->first);
|
||||
const int lenInBytes = lenInChars * sizeof(URI_CHAR);
|
||||
URI_CHAR * dup = memory->malloc(memory, lenInBytes);
|
||||
if (dup == NULL) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
memcpy(dup, range->first, lenInBytes);
|
||||
range->first = dup;
|
||||
range->afterLast = dup + lenInChars;
|
||||
*doneMask |= maskTest;
|
||||
}
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri,
|
||||
unsigned int * doneMask, UriMemoryManager * memory) {
|
||||
URI_TYPE(PathSegment) * walker = uri->pathHead;
|
||||
if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_SCHEME,
|
||||
&(uri->scheme), memory)
|
||||
|| !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_USER_INFO,
|
||||
&(uri->userInfo), memory)
|
||||
|| !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_QUERY,
|
||||
&(uri->query), memory)
|
||||
|| !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_FRAGMENT,
|
||||
&(uri->fragment), memory)) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
|
||||
/* Host */
|
||||
if ((*doneMask & URI_NORMALIZE_HOST) == 0) {
|
||||
if (uri->hostData.ipFuture.first != NULL) {
|
||||
/* IPvFuture */
|
||||
if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST,
|
||||
&(uri->hostData.ipFuture), memory)) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
uri->hostText.first = uri->hostData.ipFuture.first;
|
||||
uri->hostText.afterLast = uri->hostData.ipFuture.afterLast;
|
||||
} else if (uri->hostText.first != NULL) {
|
||||
/* Regname */
|
||||
if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST,
|
||||
&(uri->hostText), memory)) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Path */
|
||||
if ((*doneMask & URI_NORMALIZE_PATH) == 0) {
|
||||
while (walker != NULL) {
|
||||
if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(walker->text), memory)) {
|
||||
/* Free allocations done so far and kill path */
|
||||
|
||||
/* Kill path to one before walker (if any) */
|
||||
URI_TYPE(PathSegment) * ranger = uri->pathHead;
|
||||
while (ranger != walker) {
|
||||
URI_TYPE(PathSegment) * const next = ranger->next;
|
||||
if ((ranger->text.first != NULL)
|
||||
&& (ranger->text.afterLast != NULL)
|
||||
&& (ranger->text.afterLast > ranger->text.first)) {
|
||||
memory->free(memory, (URI_CHAR *)ranger->text.first);
|
||||
}
|
||||
memory->free(memory, ranger);
|
||||
ranger = next;
|
||||
}
|
||||
|
||||
/* Kill path from walker */
|
||||
while (walker != NULL) {
|
||||
URI_TYPE(PathSegment) * const next = walker->next;
|
||||
memory->free(memory, walker);
|
||||
walker = next;
|
||||
}
|
||||
|
||||
uri->pathHead = NULL;
|
||||
uri->pathTail = NULL;
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
walker = walker->next;
|
||||
}
|
||||
*doneMask |= URI_NORMALIZE_PATH;
|
||||
}
|
||||
|
||||
/* Port text, must come last so we don't have to undo that one if it fails. *
|
||||
* Otherwise we would need and extra enum flag for it although the port *
|
||||
* cannot go unnormalized... */
|
||||
if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(uri->portText), memory)) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int URI_FUNC(NormalizeSyntaxMaskRequired)(const URI_TYPE(Uri) * uri) {
|
||||
unsigned int outMask = URI_NORMALIZED; /* for NULL uri */
|
||||
URI_FUNC(NormalizeSyntaxMaskRequiredEx)(uri, &outMask);
|
||||
return outMask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(NormalizeSyntaxMaskRequiredEx)(const URI_TYPE(Uri) * uri,
|
||||
unsigned int * outMask) {
|
||||
UriMemoryManager * const memory = NULL; /* no use of memory manager */
|
||||
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 4) \
|
||||
|| ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2)))
|
||||
/* Slower code that fixes a warning, not sure if this is a smart idea */
|
||||
URI_TYPE(Uri) writeableClone;
|
||||
#endif
|
||||
|
||||
if ((uri == NULL) || (outMask == NULL)) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 4) \
|
||||
|| ((__GNUC__ == 4) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 2)))
|
||||
/* Slower code that fixes a warning, not sure if this is a smart idea */
|
||||
memcpy(&writeableClone, uri, 1 * sizeof(URI_TYPE(Uri)));
|
||||
URI_FUNC(NormalizeSyntaxEngine)(&writeableClone, 0, outMask, memory);
|
||||
#else
|
||||
URI_FUNC(NormalizeSyntaxEngine)((URI_TYPE(Uri) *)uri, 0, outMask, memory);
|
||||
#endif
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(NormalizeSyntaxEx)(URI_TYPE(Uri) * uri, unsigned int mask) {
|
||||
return URI_FUNC(NormalizeSyntaxExMm)(uri, mask, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(NormalizeSyntaxExMm)(URI_TYPE(Uri) * uri, unsigned int mask,
|
||||
UriMemoryManager * memory) {
|
||||
URI_CHECK_MEMORY_MANAGER(memory); /* may return */
|
||||
return URI_FUNC(NormalizeSyntaxEngine)(uri, mask, NULL, memory);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(NormalizeSyntax)(URI_TYPE(Uri) * uri) {
|
||||
return URI_FUNC(NormalizeSyntaxEx)(uri, (unsigned int)-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri,
|
||||
unsigned int inMask, unsigned int * outMask,
|
||||
UriMemoryManager * memory) {
|
||||
unsigned int doneMask = URI_NORMALIZED;
|
||||
|
||||
/* Not just doing inspection? -> memory manager required! */
|
||||
if (outMask == NULL) {
|
||||
assert(memory != NULL);
|
||||
}
|
||||
|
||||
if (uri == NULL) {
|
||||
if (outMask != NULL) {
|
||||
*outMask = URI_NORMALIZED;
|
||||
return URI_SUCCESS;
|
||||
} else {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (outMask != NULL) {
|
||||
/* Reset mask */
|
||||
*outMask = URI_NORMALIZED;
|
||||
} else if (inMask == URI_NORMALIZED) {
|
||||
/* Nothing to do */
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Scheme, host */
|
||||
if (outMask != NULL) {
|
||||
const UriBool normalizeScheme = URI_FUNC(ContainsUppercaseLetters)(
|
||||
uri->scheme.first, uri->scheme.afterLast);
|
||||
const UriBool normalizeHostCase = URI_FUNC(ContainsUppercaseLetters)(
|
||||
uri->hostText.first, uri->hostText.afterLast);
|
||||
if (normalizeScheme) {
|
||||
*outMask |= URI_NORMALIZE_SCHEME;
|
||||
}
|
||||
|
||||
if (normalizeHostCase) {
|
||||
*outMask |= URI_NORMALIZE_HOST;
|
||||
} else {
|
||||
const UriBool normalizeHostPrecent = URI_FUNC(ContainsUglyPercentEncoding)(
|
||||
uri->hostText.first, uri->hostText.afterLast);
|
||||
if (normalizeHostPrecent) {
|
||||
*outMask |= URI_NORMALIZE_HOST;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Scheme */
|
||||
if ((inMask & URI_NORMALIZE_SCHEME) && (uri->scheme.first != NULL)) {
|
||||
if (uri->owner) {
|
||||
URI_FUNC(LowercaseInplace)(uri->scheme.first, uri->scheme.afterLast);
|
||||
} else {
|
||||
if (!URI_FUNC(LowercaseMalloc)(&(uri->scheme.first), &(uri->scheme.afterLast), memory)) {
|
||||
URI_FUNC(PreventLeakage)(uri, doneMask, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
doneMask |= URI_NORMALIZE_SCHEME;
|
||||
}
|
||||
}
|
||||
|
||||
/* Host */
|
||||
if (inMask & URI_NORMALIZE_HOST) {
|
||||
if (uri->hostData.ipFuture.first != NULL) {
|
||||
/* IPvFuture */
|
||||
if (uri->owner) {
|
||||
URI_FUNC(LowercaseInplace)(uri->hostData.ipFuture.first,
|
||||
uri->hostData.ipFuture.afterLast);
|
||||
} else {
|
||||
if (!URI_FUNC(LowercaseMalloc)(&(uri->hostData.ipFuture.first),
|
||||
&(uri->hostData.ipFuture.afterLast), memory)) {
|
||||
URI_FUNC(PreventLeakage)(uri, doneMask, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
doneMask |= URI_NORMALIZE_HOST;
|
||||
}
|
||||
uri->hostText.first = uri->hostData.ipFuture.first;
|
||||
uri->hostText.afterLast = uri->hostData.ipFuture.afterLast;
|
||||
} else if ((uri->hostText.first != NULL)
|
||||
&& (uri->hostData.ip4 == NULL)) {
|
||||
/* Regname or IPv6 */
|
||||
if (uri->owner) {
|
||||
URI_FUNC(FixPercentEncodingInplace)(uri->hostText.first,
|
||||
&(uri->hostText.afterLast));
|
||||
} else {
|
||||
if (!URI_FUNC(FixPercentEncodingMalloc)(
|
||||
&(uri->hostText.first),
|
||||
&(uri->hostText.afterLast),
|
||||
memory)) {
|
||||
URI_FUNC(PreventLeakage)(uri, doneMask, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
doneMask |= URI_NORMALIZE_HOST;
|
||||
}
|
||||
|
||||
URI_FUNC(LowercaseInplaceExceptPercentEncoding)(uri->hostText.first,
|
||||
uri->hostText.afterLast);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* User info */
|
||||
if (outMask != NULL) {
|
||||
const UriBool normalizeUserInfo = URI_FUNC(ContainsUglyPercentEncoding)(
|
||||
uri->userInfo.first, uri->userInfo.afterLast);
|
||||
if (normalizeUserInfo) {
|
||||
*outMask |= URI_NORMALIZE_USER_INFO;
|
||||
}
|
||||
} else {
|
||||
if ((inMask & URI_NORMALIZE_USER_INFO) && (uri->userInfo.first != NULL)) {
|
||||
if (uri->owner) {
|
||||
URI_FUNC(FixPercentEncodingInplace)(uri->userInfo.first, &(uri->userInfo.afterLast));
|
||||
} else {
|
||||
if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->userInfo.first),
|
||||
&(uri->userInfo.afterLast), memory)) {
|
||||
URI_FUNC(PreventLeakage)(uri, doneMask, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
doneMask |= URI_NORMALIZE_USER_INFO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Path */
|
||||
if (outMask != NULL) {
|
||||
const URI_TYPE(PathSegment) * walker = uri->pathHead;
|
||||
while (walker != NULL) {
|
||||
const URI_CHAR * const first = walker->text.first;
|
||||
const URI_CHAR * const afterLast = walker->text.afterLast;
|
||||
if ((first != NULL)
|
||||
&& (afterLast != NULL)
|
||||
&& (afterLast > first)
|
||||
&& (
|
||||
(((afterLast - first) == 1)
|
||||
&& (first[0] == _UT('.')))
|
||||
||
|
||||
(((afterLast - first) == 2)
|
||||
&& (first[0] == _UT('.'))
|
||||
&& (first[1] == _UT('.')))
|
||||
||
|
||||
URI_FUNC(ContainsUglyPercentEncoding)(first, afterLast)
|
||||
)) {
|
||||
*outMask |= URI_NORMALIZE_PATH;
|
||||
break;
|
||||
}
|
||||
walker = walker->next;
|
||||
}
|
||||
} else if (inMask & URI_NORMALIZE_PATH) {
|
||||
URI_TYPE(PathSegment) * walker;
|
||||
const UriBool relative = ((uri->scheme.first == NULL)
|
||||
&& !uri->absolutePath) ? URI_TRUE : URI_FALSE;
|
||||
|
||||
/* Fix percent-encoding for each segment */
|
||||
walker = uri->pathHead;
|
||||
if (uri->owner) {
|
||||
while (walker != NULL) {
|
||||
URI_FUNC(FixPercentEncodingInplace)(walker->text.first, &(walker->text.afterLast));
|
||||
walker = walker->next;
|
||||
}
|
||||
} else {
|
||||
while (walker != NULL) {
|
||||
if (!URI_FUNC(FixPercentEncodingMalloc)(&(walker->text.first),
|
||||
&(walker->text.afterLast), memory)) {
|
||||
URI_FUNC(PreventLeakage)(uri, doneMask, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
walker = walker->next;
|
||||
}
|
||||
doneMask |= URI_NORMALIZE_PATH;
|
||||
}
|
||||
|
||||
/* 6.2.2.3 Path Segment Normalization */
|
||||
if (!URI_FUNC(RemoveDotSegmentsEx)(uri, relative,
|
||||
(uri->owner == URI_TRUE)
|
||||
|| ((doneMask & URI_NORMALIZE_PATH) != 0),
|
||||
memory)) {
|
||||
URI_FUNC(PreventLeakage)(uri, doneMask, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
URI_FUNC(FixEmptyTrailSegment)(uri, memory);
|
||||
}
|
||||
|
||||
/* Query, fragment */
|
||||
if (outMask != NULL) {
|
||||
const UriBool normalizeQuery = URI_FUNC(ContainsUglyPercentEncoding)(
|
||||
uri->query.first, uri->query.afterLast);
|
||||
const UriBool normalizeFragment = URI_FUNC(ContainsUglyPercentEncoding)(
|
||||
uri->fragment.first, uri->fragment.afterLast);
|
||||
if (normalizeQuery) {
|
||||
*outMask |= URI_NORMALIZE_QUERY;
|
||||
}
|
||||
|
||||
if (normalizeFragment) {
|
||||
*outMask |= URI_NORMALIZE_FRAGMENT;
|
||||
}
|
||||
} else {
|
||||
/* Query */
|
||||
if ((inMask & URI_NORMALIZE_QUERY) && (uri->query.first != NULL)) {
|
||||
if (uri->owner) {
|
||||
URI_FUNC(FixPercentEncodingInplace)(uri->query.first, &(uri->query.afterLast));
|
||||
} else {
|
||||
if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->query.first),
|
||||
&(uri->query.afterLast), memory)) {
|
||||
URI_FUNC(PreventLeakage)(uri, doneMask, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
doneMask |= URI_NORMALIZE_QUERY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fragment */
|
||||
if ((inMask & URI_NORMALIZE_FRAGMENT) && (uri->fragment.first != NULL)) {
|
||||
if (uri->owner) {
|
||||
URI_FUNC(FixPercentEncodingInplace)(uri->fragment.first, &(uri->fragment.afterLast));
|
||||
} else {
|
||||
if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->fragment.first),
|
||||
&(uri->fragment.afterLast), memory)) {
|
||||
URI_FUNC(PreventLeakage)(uri, doneMask, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
doneMask |= URI_NORMALIZE_FRAGMENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Dup all not duped yet */
|
||||
if ((outMask == NULL) && !uri->owner) {
|
||||
if (!URI_FUNC(MakeOwnerEngine)(uri, &doneMask, memory)) {
|
||||
URI_FUNC(PreventLeakage)(uri, doneMask, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
uri->owner = URI_TRUE;
|
||||
}
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(MakeOwnerMm)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {
|
||||
unsigned int doneMask = URI_NORMALIZED;
|
||||
|
||||
URI_CHECK_MEMORY_MANAGER(memory); /* may return */
|
||||
|
||||
if (uri == NULL) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
if (uri->owner == URI_TRUE) {
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
if (! URI_FUNC(MakeOwnerEngine)(uri, &doneMask, memory)) {
|
||||
URI_FUNC(PreventLeakage)(uri, doneMask, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
uri->owner = URI_TRUE;
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri) {
|
||||
return URI_FUNC(MakeOwnerMm)(uri, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
119
ext/uri/uriparser/src/UriNormalizeBase.c
Normal file
119
ext/uri/uriparser/src/UriNormalizeBase.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include "UriNormalizeBase.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
UriBool uriIsUnreserved(int code) {
|
||||
switch (code) {
|
||||
case L'a': /* ALPHA */
|
||||
case L'A':
|
||||
case L'b':
|
||||
case L'B':
|
||||
case L'c':
|
||||
case L'C':
|
||||
case L'd':
|
||||
case L'D':
|
||||
case L'e':
|
||||
case L'E':
|
||||
case L'f':
|
||||
case L'F':
|
||||
case L'g':
|
||||
case L'G':
|
||||
case L'h':
|
||||
case L'H':
|
||||
case L'i':
|
||||
case L'I':
|
||||
case L'j':
|
||||
case L'J':
|
||||
case L'k':
|
||||
case L'K':
|
||||
case L'l':
|
||||
case L'L':
|
||||
case L'm':
|
||||
case L'M':
|
||||
case L'n':
|
||||
case L'N':
|
||||
case L'o':
|
||||
case L'O':
|
||||
case L'p':
|
||||
case L'P':
|
||||
case L'q':
|
||||
case L'Q':
|
||||
case L'r':
|
||||
case L'R':
|
||||
case L's':
|
||||
case L'S':
|
||||
case L't':
|
||||
case L'T':
|
||||
case L'u':
|
||||
case L'U':
|
||||
case L'v':
|
||||
case L'V':
|
||||
case L'w':
|
||||
case L'W':
|
||||
case L'x':
|
||||
case L'X':
|
||||
case L'y':
|
||||
case L'Y':
|
||||
case L'z':
|
||||
case L'Z':
|
||||
case L'0': /* DIGIT */
|
||||
case L'1':
|
||||
case L'2':
|
||||
case L'3':
|
||||
case L'4':
|
||||
case L'5':
|
||||
case L'6':
|
||||
case L'7':
|
||||
case L'8':
|
||||
case L'9':
|
||||
case L'-': /* "-" / "." / "_" / "~" */
|
||||
case L'.':
|
||||
case L'_':
|
||||
case L'~':
|
||||
return URI_TRUE;
|
||||
|
||||
default:
|
||||
return URI_FALSE;
|
||||
}
|
||||
}
|
53
ext/uri/uriparser/src/UriNormalizeBase.h
Normal file
53
ext/uri/uriparser/src/UriNormalizeBase.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef URI_NORMALIZE_BASE_H
|
||||
#define URI_NORMALIZE_BASE_H 1
|
||||
|
||||
|
||||
|
||||
#include <uriparser/UriBase.h>
|
||||
|
||||
|
||||
|
||||
UriBool uriIsUnreserved(int code);
|
||||
|
||||
|
||||
|
||||
#endif /* URI_NORMALIZE_BASE_H */
|
2409
ext/uri/uriparser/src/UriParse.c
Normal file
2409
ext/uri/uriparser/src/UriParse.c
Normal file
File diff suppressed because it is too large
Load diff
90
ext/uri/uriparser/src/UriParseBase.c
Normal file
90
ext/uri/uriparser/src/UriParseBase.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include "UriParseBase.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void uriWriteQuadToDoubleByte(const unsigned char * hexDigits, int digitCount, unsigned char * output) {
|
||||
switch (digitCount) {
|
||||
case 1:
|
||||
/* 0x___? -> \x00 \x0? */
|
||||
output[0] = 0;
|
||||
output[1] = hexDigits[0];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* 0x__?? -> \0xx \x?? */
|
||||
output[0] = 0;
|
||||
output[1] = 16 * hexDigits[0] + hexDigits[1];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* 0x_??? -> \0x? \x?? */
|
||||
output[0] = hexDigits[0];
|
||||
output[1] = 16 * hexDigits[1] + hexDigits[2];
|
||||
break;
|
||||
|
||||
case 4:
|
||||
/* 0x???? -> \0?? \x?? */
|
||||
output[0] = 16 * hexDigits[0] + hexDigits[1];
|
||||
output[1] = 16 * hexDigits[2] + hexDigits[3];
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char uriGetOctetValue(const unsigned char * digits, int digitCount) {
|
||||
switch (digitCount) {
|
||||
case 1:
|
||||
return digits[0];
|
||||
|
||||
case 2:
|
||||
return 10 * digits[0] + digits[1];
|
||||
|
||||
case 3:
|
||||
default:
|
||||
return 100 * digits[0] + 10 * digits[1] + digits[2];
|
||||
|
||||
}
|
||||
}
|
55
ext/uri/uriparser/src/UriParseBase.h
Normal file
55
ext/uri/uriparser/src/UriParseBase.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef URI_PARSE_BASE_H
|
||||
#define URI_PARSE_BASE_H 1
|
||||
|
||||
|
||||
|
||||
#include <uriparser/UriBase.h>
|
||||
|
||||
|
||||
|
||||
void uriWriteQuadToDoubleByte(const unsigned char * hexDigits, int digitCount,
|
||||
unsigned char * output);
|
||||
unsigned char uriGetOctetValue(const unsigned char * digits, int digitCount);
|
||||
|
||||
|
||||
|
||||
#endif /* URI_PARSE_BASE_H */
|
505
ext/uri/uriparser/src/UriQuery.c
Normal file
505
ext/uri/uriparser/src/UriQuery.c
Normal file
|
@ -0,0 +1,505 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriQuery.c"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriQuery.c"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_PASS_ANSI
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# include <wchar.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/Uri.h>
|
||||
# include "UriCommon.h"
|
||||
# include "UriMemory.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
|
||||
static int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest,
|
||||
const URI_TYPE(QueryList) * queryList,
|
||||
int maxChars, int * charsWritten, int * charsRequired,
|
||||
UriBool spaceToPlus, UriBool normalizeBreaks);
|
||||
|
||||
static UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) ** prevNext,
|
||||
int * itemCount, const URI_CHAR * keyFirst, const URI_CHAR * keyAfter,
|
||||
const URI_CHAR * valueFirst, const URI_CHAR * valueAfter,
|
||||
UriBool plusToSpace, UriBreakConversion breakConversion,
|
||||
UriMemoryManager * memory);
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(ComposeQueryCharsRequired)(const URI_TYPE(QueryList) * queryList,
|
||||
int * charsRequired) {
|
||||
const UriBool spaceToPlus = URI_TRUE;
|
||||
const UriBool normalizeBreaks = URI_TRUE;
|
||||
|
||||
return URI_FUNC(ComposeQueryCharsRequiredEx)(queryList, charsRequired,
|
||||
spaceToPlus, normalizeBreaks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(ComposeQueryCharsRequiredEx)(const URI_TYPE(QueryList) * queryList,
|
||||
int * charsRequired, UriBool spaceToPlus, UriBool normalizeBreaks) {
|
||||
if ((queryList == NULL) || (charsRequired == NULL)) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
return URI_FUNC(ComposeQueryEngine)(NULL, queryList, 0, NULL,
|
||||
charsRequired, spaceToPlus, normalizeBreaks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(ComposeQuery)(URI_CHAR * dest,
|
||||
const URI_TYPE(QueryList) * queryList, int maxChars, int * charsWritten) {
|
||||
const UriBool spaceToPlus = URI_TRUE;
|
||||
const UriBool normalizeBreaks = URI_TRUE;
|
||||
|
||||
return URI_FUNC(ComposeQueryEx)(dest, queryList, maxChars, charsWritten,
|
||||
spaceToPlus, normalizeBreaks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(ComposeQueryEx)(URI_CHAR * dest,
|
||||
const URI_TYPE(QueryList) * queryList, int maxChars, int * charsWritten,
|
||||
UriBool spaceToPlus, UriBool normalizeBreaks) {
|
||||
if ((dest == NULL) || (queryList == NULL)) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
if (maxChars < 1) {
|
||||
return URI_ERROR_OUTPUT_TOO_LARGE;
|
||||
}
|
||||
|
||||
return URI_FUNC(ComposeQueryEngine)(dest, queryList, maxChars,
|
||||
charsWritten, NULL, spaceToPlus, normalizeBreaks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(ComposeQueryMalloc)(URI_CHAR ** dest,
|
||||
const URI_TYPE(QueryList) * queryList) {
|
||||
const UriBool spaceToPlus = URI_TRUE;
|
||||
const UriBool normalizeBreaks = URI_TRUE;
|
||||
|
||||
return URI_FUNC(ComposeQueryMallocEx)(dest, queryList,
|
||||
spaceToPlus, normalizeBreaks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(ComposeQueryMallocEx)(URI_CHAR ** dest,
|
||||
const URI_TYPE(QueryList) * queryList,
|
||||
UriBool spaceToPlus, UriBool normalizeBreaks) {
|
||||
return URI_FUNC(ComposeQueryMallocExMm)(dest, queryList, spaceToPlus,
|
||||
normalizeBreaks, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(ComposeQueryMallocExMm)(URI_CHAR ** dest,
|
||||
const URI_TYPE(QueryList) * queryList,
|
||||
UriBool spaceToPlus, UriBool normalizeBreaks,
|
||||
UriMemoryManager * memory) {
|
||||
int charsRequired;
|
||||
int res;
|
||||
URI_CHAR * queryString;
|
||||
|
||||
if (dest == NULL) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
URI_CHECK_MEMORY_MANAGER(memory); /* may return */
|
||||
|
||||
/* Calculate space */
|
||||
res = URI_FUNC(ComposeQueryCharsRequiredEx)(queryList, &charsRequired,
|
||||
spaceToPlus, normalizeBreaks);
|
||||
if (res != URI_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
if (charsRequired == INT_MAX) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
charsRequired++;
|
||||
|
||||
/* Allocate space */
|
||||
queryString = memory->calloc(memory, charsRequired, sizeof(URI_CHAR));
|
||||
if (queryString == NULL) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
/* Put query in */
|
||||
res = URI_FUNC(ComposeQueryEx)(queryString, queryList, charsRequired,
|
||||
NULL, spaceToPlus, normalizeBreaks);
|
||||
if (res != URI_SUCCESS) {
|
||||
memory->free(memory, queryString);
|
||||
return res;
|
||||
}
|
||||
|
||||
*dest = queryString;
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest,
|
||||
const URI_TYPE(QueryList) * queryList,
|
||||
int maxChars, int * charsWritten, int * charsRequired,
|
||||
UriBool spaceToPlus, UriBool normalizeBreaks) {
|
||||
UriBool firstItem = URI_TRUE;
|
||||
int ampersandLen = 0; /* increased to 1 from second item on */
|
||||
URI_CHAR * write = dest;
|
||||
|
||||
/* Subtract terminator */
|
||||
if (dest == NULL) {
|
||||
*charsRequired = 0;
|
||||
} else {
|
||||
maxChars--;
|
||||
}
|
||||
|
||||
while (queryList != NULL) {
|
||||
const URI_CHAR * const key = queryList->key;
|
||||
const URI_CHAR * const value = queryList->value;
|
||||
const int worstCase = (normalizeBreaks == URI_TRUE ? 6 : 3);
|
||||
const size_t keyLen = (key == NULL) ? 0 : URI_STRLEN(key);
|
||||
int keyRequiredChars;
|
||||
const size_t valueLen = (value == NULL) ? 0 : URI_STRLEN(value);
|
||||
int valueRequiredChars;
|
||||
|
||||
if ((keyLen >= (size_t)INT_MAX / worstCase) || (valueLen >= (size_t)INT_MAX / worstCase)) {
|
||||
return URI_ERROR_OUTPUT_TOO_LARGE;
|
||||
}
|
||||
keyRequiredChars = worstCase * (int)keyLen;
|
||||
valueRequiredChars = worstCase * (int)valueLen;
|
||||
|
||||
if (dest == NULL) {
|
||||
(*charsRequired) += ampersandLen + keyRequiredChars + ((value == NULL)
|
||||
? 0
|
||||
: 1 + valueRequiredChars);
|
||||
|
||||
if (firstItem == URI_TRUE) {
|
||||
ampersandLen = 1;
|
||||
firstItem = URI_FALSE;
|
||||
}
|
||||
} else {
|
||||
if ((write - dest) + ampersandLen + keyRequiredChars > maxChars) {
|
||||
return URI_ERROR_OUTPUT_TOO_LARGE;
|
||||
}
|
||||
|
||||
/* Copy key */
|
||||
if (firstItem == URI_TRUE) {
|
||||
ampersandLen = 1;
|
||||
firstItem = URI_FALSE;
|
||||
} else {
|
||||
write[0] = _UT('&');
|
||||
write++;
|
||||
}
|
||||
write = URI_FUNC(EscapeEx)(key, key + keyLen,
|
||||
write, spaceToPlus, normalizeBreaks);
|
||||
|
||||
if (value != NULL) {
|
||||
if ((write - dest) + 1 + valueRequiredChars > maxChars) {
|
||||
return URI_ERROR_OUTPUT_TOO_LARGE;
|
||||
}
|
||||
|
||||
/* Copy value */
|
||||
write[0] = _UT('=');
|
||||
write++;
|
||||
write = URI_FUNC(EscapeEx)(value, value + valueLen,
|
||||
write, spaceToPlus, normalizeBreaks);
|
||||
}
|
||||
}
|
||||
|
||||
queryList = queryList->next;
|
||||
}
|
||||
|
||||
if (dest != NULL) {
|
||||
write[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = (int)(write - dest) + 1; /* .. for terminator */
|
||||
}
|
||||
}
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) ** prevNext,
|
||||
int * itemCount, const URI_CHAR * keyFirst, const URI_CHAR * keyAfter,
|
||||
const URI_CHAR * valueFirst, const URI_CHAR * valueAfter,
|
||||
UriBool plusToSpace, UriBreakConversion breakConversion,
|
||||
UriMemoryManager * memory) {
|
||||
const int keyLen = (int)(keyAfter - keyFirst);
|
||||
const int valueLen = (int)(valueAfter - valueFirst);
|
||||
URI_CHAR * key;
|
||||
URI_CHAR * value;
|
||||
|
||||
if ((prevNext == NULL) || (itemCount == NULL)
|
||||
|| (keyFirst == NULL) || (keyAfter == NULL)
|
||||
|| (keyFirst > keyAfter) || (valueFirst > valueAfter)
|
||||
|| ((keyFirst == keyAfter)
|
||||
&& (valueFirst == NULL) && (valueAfter == NULL))) {
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
/* Append new empty item */
|
||||
*prevNext = memory->malloc(memory, 1 * sizeof(URI_TYPE(QueryList)));
|
||||
if (*prevNext == NULL) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
(*prevNext)->next = NULL;
|
||||
|
||||
|
||||
/* Fill key */
|
||||
key = memory->malloc(memory, (keyLen + 1) * sizeof(URI_CHAR));
|
||||
if (key == NULL) {
|
||||
memory->free(memory, *prevNext);
|
||||
*prevNext = NULL;
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
|
||||
key[keyLen] = _UT('\0');
|
||||
if (keyLen > 0) {
|
||||
/* Copy 1:1 */
|
||||
memcpy(key, keyFirst, keyLen * sizeof(URI_CHAR));
|
||||
|
||||
/* Unescape */
|
||||
URI_FUNC(UnescapeInPlaceEx)(key, plusToSpace, breakConversion);
|
||||
}
|
||||
(*prevNext)->key = key;
|
||||
|
||||
|
||||
/* Fill value */
|
||||
if (valueFirst != NULL) {
|
||||
value = memory->malloc(memory, (valueLen + 1) * sizeof(URI_CHAR));
|
||||
if (value == NULL) {
|
||||
memory->free(memory, key);
|
||||
memory->free(memory, *prevNext);
|
||||
*prevNext = NULL;
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
|
||||
value[valueLen] = _UT('\0');
|
||||
if (valueLen > 0) {
|
||||
/* Copy 1:1 */
|
||||
memcpy(value, valueFirst, valueLen * sizeof(URI_CHAR));
|
||||
|
||||
/* Unescape */
|
||||
URI_FUNC(UnescapeInPlaceEx)(value, plusToSpace, breakConversion);
|
||||
}
|
||||
(*prevNext)->value = value;
|
||||
} else {
|
||||
value = NULL;
|
||||
}
|
||||
(*prevNext)->value = value;
|
||||
|
||||
(*itemCount)++;
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void URI_FUNC(FreeQueryList)(URI_TYPE(QueryList) * queryList) {
|
||||
URI_FUNC(FreeQueryListMm)(queryList, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(FreeQueryListMm)(URI_TYPE(QueryList) * queryList,
|
||||
UriMemoryManager * memory) {
|
||||
URI_CHECK_MEMORY_MANAGER(memory); /* may return */
|
||||
while (queryList != NULL) {
|
||||
URI_TYPE(QueryList) * nextBackup = queryList->next;
|
||||
memory->free(memory, (URI_CHAR *)queryList->key); /* const cast */
|
||||
memory->free(memory, (URI_CHAR *)queryList->value); /* const cast */
|
||||
memory->free(memory, queryList);
|
||||
queryList = nextBackup;
|
||||
}
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(DissectQueryMalloc)(URI_TYPE(QueryList) ** dest, int * itemCount,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast) {
|
||||
const UriBool plusToSpace = URI_TRUE;
|
||||
const UriBreakConversion breakConversion = URI_BR_DONT_TOUCH;
|
||||
|
||||
return URI_FUNC(DissectQueryMallocEx)(dest, itemCount, first, afterLast,
|
||||
plusToSpace, breakConversion);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(DissectQueryMallocEx)(URI_TYPE(QueryList) ** dest, int * itemCount,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast,
|
||||
UriBool plusToSpace, UriBreakConversion breakConversion) {
|
||||
return URI_FUNC(DissectQueryMallocExMm)(dest, itemCount, first, afterLast,
|
||||
plusToSpace, breakConversion, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(DissectQueryMallocExMm)(URI_TYPE(QueryList) ** dest, int * itemCount,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast,
|
||||
UriBool plusToSpace, UriBreakConversion breakConversion,
|
||||
UriMemoryManager * memory) {
|
||||
const URI_CHAR * walk = first;
|
||||
const URI_CHAR * keyFirst = first;
|
||||
const URI_CHAR * keyAfter = NULL;
|
||||
const URI_CHAR * valueFirst = NULL;
|
||||
const URI_CHAR * valueAfter = NULL;
|
||||
URI_TYPE(QueryList) ** prevNext = dest;
|
||||
int nullCounter;
|
||||
int * itemsAppended = (itemCount == NULL) ? &nullCounter : itemCount;
|
||||
|
||||
if ((dest == NULL) || (first == NULL) || (afterLast == NULL)) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
if (first > afterLast) {
|
||||
return URI_ERROR_RANGE_INVALID;
|
||||
}
|
||||
|
||||
URI_CHECK_MEMORY_MANAGER(memory); /* may return */
|
||||
|
||||
*dest = NULL;
|
||||
*itemsAppended = 0;
|
||||
|
||||
/* Parse query string */
|
||||
for (; walk < afterLast; walk++) {
|
||||
switch (*walk) {
|
||||
case _UT('&'):
|
||||
if (valueFirst != NULL) {
|
||||
valueAfter = walk;
|
||||
} else {
|
||||
keyAfter = walk;
|
||||
}
|
||||
|
||||
if (URI_FUNC(AppendQueryItem)(prevNext, itemsAppended,
|
||||
keyFirst, keyAfter, valueFirst, valueAfter,
|
||||
plusToSpace, breakConversion, memory)
|
||||
== URI_FALSE) {
|
||||
/* Free list we built */
|
||||
*itemsAppended = 0;
|
||||
URI_FUNC(FreeQueryListMm)(*dest, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
/* Make future items children of the current */
|
||||
if ((prevNext != NULL) && (*prevNext != NULL)) {
|
||||
prevNext = &((*prevNext)->next);
|
||||
}
|
||||
|
||||
if (walk + 1 < afterLast) {
|
||||
keyFirst = walk + 1;
|
||||
} else {
|
||||
keyFirst = NULL;
|
||||
}
|
||||
keyAfter = NULL;
|
||||
valueFirst = NULL;
|
||||
valueAfter = NULL;
|
||||
break;
|
||||
|
||||
case _UT('='):
|
||||
/* NOTE: WE treat the first '=' as a separator, */
|
||||
/* all following go into the value part */
|
||||
if (keyAfter == NULL) {
|
||||
keyAfter = walk;
|
||||
if (walk + 1 <= afterLast) {
|
||||
valueFirst = walk + 1;
|
||||
valueAfter = walk + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valueFirst != NULL) {
|
||||
/* Must be key/value pair */
|
||||
valueAfter = walk;
|
||||
} else {
|
||||
/* Must be key only */
|
||||
keyAfter = walk;
|
||||
}
|
||||
|
||||
if (URI_FUNC(AppendQueryItem)(prevNext, itemsAppended, keyFirst, keyAfter,
|
||||
valueFirst, valueAfter, plusToSpace, breakConversion, memory)
|
||||
== URI_FALSE) {
|
||||
/* Free list we built */
|
||||
*itemsAppended = 0;
|
||||
URI_FUNC(FreeQueryListMm)(*dest, memory);
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
577
ext/uri/uriparser/src/UriRecompose.c
Normal file
577
ext/uri/uriparser/src/UriRecompose.c
Normal file
|
@ -0,0 +1,577 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriRecompose.c"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriRecompose.c"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_PASS_ANSI
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# include <wchar.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/Uri.h>
|
||||
# include "UriCommon.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(Uri) * uri,
|
||||
int maxChars, int * charsWritten, int * charsRequired);
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(ToStringCharsRequired)(const URI_TYPE(Uri) * uri,
|
||||
int * charsRequired) {
|
||||
const int MAX_CHARS = ((unsigned int)-1) >> 1;
|
||||
return URI_FUNC(ToStringEngine)(NULL, uri, MAX_CHARS, NULL, charsRequired);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(ToString)(URI_CHAR * dest, const URI_TYPE(Uri) * uri,
|
||||
int maxChars, int * charsWritten) {
|
||||
return URI_FUNC(ToStringEngine)(dest, uri, maxChars, charsWritten, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest,
|
||||
const URI_TYPE(Uri) * uri, int maxChars, int * charsWritten,
|
||||
int * charsRequired) {
|
||||
int written = 0;
|
||||
if ((uri == NULL) || ((dest == NULL) && (charsRequired == NULL))) {
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
if (maxChars < 1) {
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
maxChars--; /* So we don't have to subtract 1 for '\0' all the time */
|
||||
|
||||
/* [01/19] result = "" */
|
||||
if (dest != NULL) {
|
||||
dest[0] = _UT('\0');
|
||||
} else {
|
||||
(*charsRequired) = 0;
|
||||
}
|
||||
/* [02/19] if defined(scheme) then */
|
||||
if (uri->scheme.first != NULL) {
|
||||
/* [03/19] append scheme to result; */
|
||||
const int charsToWrite
|
||||
= (int)(uri->scheme.afterLast - uri->scheme.first);
|
||||
if (dest != NULL) {
|
||||
if (written + charsToWrite <= maxChars) {
|
||||
memcpy(dest + written, uri->scheme.first,
|
||||
charsToWrite * sizeof(URI_CHAR));
|
||||
written += charsToWrite;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += charsToWrite;
|
||||
}
|
||||
/* [04/19] append ":" to result; */
|
||||
if (dest != NULL) {
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT(":"),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 1;
|
||||
}
|
||||
/* [05/19] endif; */
|
||||
}
|
||||
/* [06/19] if defined(authority) then */
|
||||
if (URI_FUNC(IsHostSet)(uri)) {
|
||||
/* [07/19] append "//" to result; */
|
||||
if (dest != NULL) {
|
||||
if (written + 2 <= maxChars) {
|
||||
memcpy(dest + written, _UT("//"),
|
||||
2 * sizeof(URI_CHAR));
|
||||
written += 2;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 2;
|
||||
}
|
||||
/* [08/19] append authority to result; */
|
||||
/* UserInfo */
|
||||
if (uri->userInfo.first != NULL) {
|
||||
const int charsToWrite = (int)(uri->userInfo.afterLast - uri->userInfo.first);
|
||||
if (dest != NULL) {
|
||||
if (written + charsToWrite <= maxChars) {
|
||||
memcpy(dest + written, uri->userInfo.first,
|
||||
charsToWrite * sizeof(URI_CHAR));
|
||||
written += charsToWrite;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT("@"),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += charsToWrite + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Host */
|
||||
if (uri->hostData.ip4 != NULL) {
|
||||
/* IPv4 */
|
||||
int i = 0;
|
||||
for (; i < 4; i++) {
|
||||
const unsigned char value = uri->hostData.ip4->data[i];
|
||||
const int charsToWrite = (value > 99) ? 3 : ((value > 9) ? 2 : 1);
|
||||
if (dest != NULL) {
|
||||
if (written + charsToWrite <= maxChars) {
|
||||
URI_CHAR text[4];
|
||||
if (value > 99) {
|
||||
text[0] = _UT('0') + (value / 100);
|
||||
text[1] = _UT('0') + ((value % 100) / 10);
|
||||
text[2] = _UT('0') + (value % 10);
|
||||
} else if (value > 9) {
|
||||
text[0] = _UT('0') + (value / 10);
|
||||
text[1] = _UT('0') + (value % 10);
|
||||
} else {
|
||||
text[0] = _UT('0') + value;
|
||||
}
|
||||
text[charsToWrite] = _UT('\0');
|
||||
memcpy(dest + written, text, charsToWrite * sizeof(URI_CHAR));
|
||||
written += charsToWrite;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
if (i < 3) {
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT("."),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += charsToWrite + ((i == 3) ? 0 : 1);
|
||||
}
|
||||
}
|
||||
} else if (uri->hostData.ip6 != NULL) {
|
||||
/* IPv6 */
|
||||
int i = 0;
|
||||
if (dest != NULL) {
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT("["),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 1;
|
||||
}
|
||||
|
||||
for (; i < 16; i++) {
|
||||
const unsigned char value = uri->hostData.ip6->data[i];
|
||||
if (dest != NULL) {
|
||||
if (written + 2 <= maxChars) {
|
||||
URI_CHAR text[3];
|
||||
text[0] = URI_FUNC(HexToLetterEx)(value / 16, URI_FALSE);
|
||||
text[1] = URI_FUNC(HexToLetterEx)(value % 16, URI_FALSE);
|
||||
text[2] = _UT('\0');
|
||||
memcpy(dest + written, text, 2 * sizeof(URI_CHAR));
|
||||
written += 2;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 2;
|
||||
}
|
||||
if (((i & 1) == 1) && (i < 15)) {
|
||||
if (dest != NULL) {
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT(":"),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dest != NULL) {
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT("]"),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 1;
|
||||
}
|
||||
} else if (uri->hostData.ipFuture.first != NULL) {
|
||||
/* IPvFuture */
|
||||
const int charsToWrite = (int)(uri->hostData.ipFuture.afterLast
|
||||
- uri->hostData.ipFuture.first);
|
||||
if (dest != NULL) {
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT("["),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
|
||||
if (written + charsToWrite <= maxChars) {
|
||||
memcpy(dest + written, uri->hostData.ipFuture.first, charsToWrite * sizeof(URI_CHAR));
|
||||
written += charsToWrite;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT("]"),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 1 + charsToWrite + 1;
|
||||
}
|
||||
} else if (uri->hostText.first != NULL) {
|
||||
/* Regname */
|
||||
const int charsToWrite = (int)(uri->hostText.afterLast - uri->hostText.first);
|
||||
if (dest != NULL) {
|
||||
if (written + charsToWrite <= maxChars) {
|
||||
memcpy(dest + written, uri->hostText.first,
|
||||
charsToWrite * sizeof(URI_CHAR));
|
||||
written += charsToWrite;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += charsToWrite;
|
||||
}
|
||||
}
|
||||
|
||||
/* Port */
|
||||
if (uri->portText.first != NULL) {
|
||||
const int charsToWrite = (int)(uri->portText.afterLast - uri->portText.first);
|
||||
if (dest != NULL) {
|
||||
/* Leading ':' */
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT(":"),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
|
||||
/* Port number */
|
||||
if (written + charsToWrite <= maxChars) {
|
||||
memcpy(dest + written, uri->portText.first,
|
||||
charsToWrite * sizeof(URI_CHAR));
|
||||
written += charsToWrite;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 1 + charsToWrite;
|
||||
}
|
||||
}
|
||||
/* [09/19] endif; */
|
||||
}
|
||||
/* [10/19] append path to result; */
|
||||
/* Slash needed here? */
|
||||
if (uri->absolutePath || ((uri->pathHead != NULL)
|
||||
&& URI_FUNC(IsHostSet)(uri))) {
|
||||
if (dest != NULL) {
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT("/"),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uri->pathHead != NULL) {
|
||||
URI_TYPE(PathSegment) * walker = uri->pathHead;
|
||||
do {
|
||||
const int charsToWrite = (int)(walker->text.afterLast - walker->text.first);
|
||||
if (dest != NULL) {
|
||||
if (written + charsToWrite <= maxChars) {
|
||||
memcpy(dest + written, walker->text.first,
|
||||
charsToWrite * sizeof(URI_CHAR));
|
||||
written += charsToWrite;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += charsToWrite;
|
||||
}
|
||||
|
||||
/* Not last segment -> append slash */
|
||||
if (walker->next != NULL) {
|
||||
if (dest != NULL) {
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT("/"),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 1;
|
||||
}
|
||||
}
|
||||
|
||||
walker = walker->next;
|
||||
} while (walker != NULL);
|
||||
}
|
||||
/* [11/19] if defined(query) then */
|
||||
if (uri->query.first != NULL) {
|
||||
/* [12/19] append "?" to result; */
|
||||
if (dest != NULL) {
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT("?"),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 1;
|
||||
}
|
||||
/* [13/19] append query to result; */
|
||||
{
|
||||
const int charsToWrite
|
||||
= (int)(uri->query.afterLast - uri->query.first);
|
||||
if (dest != NULL) {
|
||||
if (written + charsToWrite <= maxChars) {
|
||||
memcpy(dest + written, uri->query.first,
|
||||
charsToWrite * sizeof(URI_CHAR));
|
||||
written += charsToWrite;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += charsToWrite;
|
||||
}
|
||||
}
|
||||
/* [14/19] endif; */
|
||||
}
|
||||
/* [15/19] if defined(fragment) then */
|
||||
if (uri->fragment.first != NULL) {
|
||||
/* [16/19] append "#" to result; */
|
||||
if (dest != NULL) {
|
||||
if (written + 1 <= maxChars) {
|
||||
memcpy(dest + written, _UT("#"),
|
||||
1 * sizeof(URI_CHAR));
|
||||
written += 1;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += 1;
|
||||
}
|
||||
/* [17/19] append fragment to result; */
|
||||
{
|
||||
const int charsToWrite
|
||||
= (int)(uri->fragment.afterLast - uri->fragment.first);
|
||||
if (dest != NULL) {
|
||||
if (written + charsToWrite <= maxChars) {
|
||||
memcpy(dest + written, uri->fragment.first,
|
||||
charsToWrite * sizeof(URI_CHAR));
|
||||
written += charsToWrite;
|
||||
} else {
|
||||
dest[0] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = 0;
|
||||
}
|
||||
return URI_ERROR_TOSTRING_TOO_LONG;
|
||||
}
|
||||
} else {
|
||||
(*charsRequired) += charsToWrite;
|
||||
}
|
||||
}
|
||||
/* [18/19] endif; */
|
||||
}
|
||||
/* [19/19] return result; */
|
||||
if (dest != NULL) {
|
||||
dest[written++] = _UT('\0');
|
||||
if (charsWritten != NULL) {
|
||||
*charsWritten = written;
|
||||
}
|
||||
}
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
329
ext/uri/uriparser/src/UriResolve.c
Normal file
329
ext/uri/uriparser/src/UriResolve.c
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriResolve.c"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriResolve.c"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_PASS_ANSI
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# include <wchar.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/Uri.h>
|
||||
# include "UriCommon.h"
|
||||
# include "UriMemory.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Appends a relative URI to an absolute. The last path segment of
|
||||
* the absolute URI is replaced. */
|
||||
static URI_INLINE UriBool URI_FUNC(MergePath)(URI_TYPE(Uri) * absWork,
|
||||
const URI_TYPE(Uri) * relAppend, UriMemoryManager * memory) {
|
||||
URI_TYPE(PathSegment) * sourceWalker;
|
||||
URI_TYPE(PathSegment) * destPrev;
|
||||
if (relAppend->pathHead == NULL) {
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
/* Replace last segment ("" if trailing slash) with first of append chain */
|
||||
if (absWork->pathHead == NULL) {
|
||||
URI_TYPE(PathSegment) * const dup = memory->malloc(memory, sizeof(URI_TYPE(PathSegment)));
|
||||
if (dup == NULL) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
dup->next = NULL;
|
||||
absWork->pathHead = dup;
|
||||
absWork->pathTail = dup;
|
||||
}
|
||||
absWork->pathTail->text.first = relAppend->pathHead->text.first;
|
||||
absWork->pathTail->text.afterLast = relAppend->pathHead->text.afterLast;
|
||||
|
||||
/* Append all the others */
|
||||
sourceWalker = relAppend->pathHead->next;
|
||||
if (sourceWalker == NULL) {
|
||||
return URI_TRUE;
|
||||
}
|
||||
destPrev = absWork->pathTail;
|
||||
|
||||
for (;;) {
|
||||
URI_TYPE(PathSegment) * const dup = memory->malloc(memory, sizeof(URI_TYPE(PathSegment)));
|
||||
if (dup == NULL) {
|
||||
destPrev->next = NULL;
|
||||
absWork->pathTail = destPrev;
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
dup->text = sourceWalker->text;
|
||||
destPrev->next = dup;
|
||||
|
||||
if (sourceWalker->next == NULL) {
|
||||
absWork->pathTail = dup;
|
||||
absWork->pathTail->next = NULL;
|
||||
break;
|
||||
}
|
||||
destPrev = dup;
|
||||
sourceWalker = sourceWalker->next;
|
||||
}
|
||||
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static int URI_FUNC(ResolveAbsolutePathFlag)(URI_TYPE(Uri) * absWork,
|
||||
UriMemoryManager * memory) {
|
||||
if (absWork == NULL) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
if (URI_FUNC(IsHostSet)(absWork) && absWork->absolutePath) {
|
||||
/* Empty segment needed, instead? */
|
||||
if (absWork->pathHead == NULL) {
|
||||
URI_TYPE(PathSegment) * const segment = memory->malloc(memory, sizeof(URI_TYPE(PathSegment)));
|
||||
if (segment == NULL) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
segment->text.first = URI_FUNC(SafeToPointTo);
|
||||
segment->text.afterLast = URI_FUNC(SafeToPointTo);
|
||||
segment->next = NULL;
|
||||
|
||||
absWork->pathHead = segment;
|
||||
absWork->pathTail = segment;
|
||||
}
|
||||
|
||||
absWork->absolutePath = URI_FALSE;
|
||||
}
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest,
|
||||
const URI_TYPE(Uri) * relSource,
|
||||
const URI_TYPE(Uri) * absBase,
|
||||
UriResolutionOptions options, UriMemoryManager * memory) {
|
||||
UriBool relSourceHasScheme;
|
||||
|
||||
if (absDest == NULL) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
URI_FUNC(ResetUri)(absDest);
|
||||
|
||||
if ((relSource == NULL) || (absBase == NULL)) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
/* absBase absolute? */
|
||||
if (absBase->scheme.first == NULL) {
|
||||
return URI_ERROR_ADDBASE_REL_BASE;
|
||||
}
|
||||
|
||||
/* [00/32] -- A non-strict parser may ignore a scheme in the reference */
|
||||
/* [00/32] -- if it is identical to the base URI's scheme. */
|
||||
/* [00/32] if ((not strict) and (R.scheme == Base.scheme)) then */
|
||||
relSourceHasScheme = (relSource->scheme.first != NULL) ? URI_TRUE : URI_FALSE;
|
||||
if ((options & URI_RESOLVE_IDENTICAL_SCHEME_COMPAT)
|
||||
&& (absBase->scheme.first != NULL)
|
||||
&& (relSource->scheme.first != NULL)
|
||||
&& (0 == URI_FUNC(CompareRange)(&(absBase->scheme), &(relSource->scheme)))) {
|
||||
/* [00/32] undefine(R.scheme); */
|
||||
relSourceHasScheme = URI_FALSE;
|
||||
/* [00/32] endif; */
|
||||
}
|
||||
|
||||
/* [01/32] if defined(R.scheme) then */
|
||||
if (relSourceHasScheme) {
|
||||
/* [02/32] T.scheme = R.scheme; */
|
||||
absDest->scheme = relSource->scheme;
|
||||
/* [03/32] T.authority = R.authority; */
|
||||
if (!URI_FUNC(CopyAuthority)(absDest, relSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [04/32] T.path = remove_dot_segments(R.path); */
|
||||
if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [05/32] T.query = R.query; */
|
||||
absDest->query = relSource->query;
|
||||
/* [06/32] else */
|
||||
} else {
|
||||
/* [07/32] if defined(R.authority) then */
|
||||
if (URI_FUNC(IsHostSet)(relSource)) {
|
||||
/* [08/32] T.authority = R.authority; */
|
||||
if (!URI_FUNC(CopyAuthority)(absDest, relSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [09/32] T.path = remove_dot_segments(R.path); */
|
||||
if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [10/32] T.query = R.query; */
|
||||
absDest->query = relSource->query;
|
||||
/* [11/32] else */
|
||||
} else {
|
||||
/* [28/32] T.authority = Base.authority; */
|
||||
if (!URI_FUNC(CopyAuthority)(absDest, absBase, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [12/32] if (R.path == "") then */
|
||||
if (relSource->pathHead == NULL && !relSource->absolutePath) {
|
||||
/* [13/32] T.path = Base.path; */
|
||||
if (!URI_FUNC(CopyPath)(absDest, absBase, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [14/32] if defined(R.query) then */
|
||||
if (relSource->query.first != NULL) {
|
||||
/* [15/32] T.query = R.query; */
|
||||
absDest->query = relSource->query;
|
||||
/* [16/32] else */
|
||||
} else {
|
||||
/* [17/32] T.query = Base.query; */
|
||||
absDest->query = absBase->query;
|
||||
/* [18/32] endif; */
|
||||
}
|
||||
/* [19/32] else */
|
||||
} else {
|
||||
/* [20/32] if (R.path starts-with "/") then */
|
||||
if (relSource->absolutePath) {
|
||||
int res;
|
||||
/* [21/32] T.path = remove_dot_segments(R.path); */
|
||||
if (!URI_FUNC(CopyPath)(absDest, relSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
res = URI_FUNC(ResolveAbsolutePathFlag)(absDest, memory);
|
||||
if (res != URI_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [22/32] else */
|
||||
} else {
|
||||
/* [23/32] T.path = merge(Base.path, R.path); */
|
||||
if (!URI_FUNC(CopyPath)(absDest, absBase, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
if (!URI_FUNC(MergePath)(absDest, relSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [24/32] T.path = remove_dot_segments(T.path); */
|
||||
if (!URI_FUNC(RemoveDotSegmentsAbsolute)(absDest, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
if (!URI_FUNC(FixAmbiguity)(absDest, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [25/32] endif; */
|
||||
}
|
||||
/* [26/32] T.query = R.query; */
|
||||
absDest->query = relSource->query;
|
||||
/* [27/32] endif; */
|
||||
}
|
||||
URI_FUNC(FixEmptyTrailSegment)(absDest, memory);
|
||||
/* [29/32] endif; */
|
||||
}
|
||||
/* [30/32] T.scheme = Base.scheme; */
|
||||
absDest->scheme = absBase->scheme;
|
||||
/* [31/32] endif; */
|
||||
}
|
||||
/* [32/32] T.fragment = R.fragment; */
|
||||
absDest->fragment = relSource->fragment;
|
||||
|
||||
return URI_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(AddBaseUri)(URI_TYPE(Uri) * absDest,
|
||||
const URI_TYPE(Uri) * relSource, const URI_TYPE(Uri) * absBase) {
|
||||
const UriResolutionOptions options = URI_RESOLVE_STRICTLY;
|
||||
return URI_FUNC(AddBaseUriEx)(absDest, relSource, absBase, options);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(AddBaseUriEx)(URI_TYPE(Uri) * absDest,
|
||||
const URI_TYPE(Uri) * relSource, const URI_TYPE(Uri) * absBase,
|
||||
UriResolutionOptions options) {
|
||||
return URI_FUNC(AddBaseUriExMm)(absDest, relSource, absBase, options, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(AddBaseUriExMm)(URI_TYPE(Uri) * absDest,
|
||||
const URI_TYPE(Uri) * relSource, const URI_TYPE(Uri) * absBase,
|
||||
UriResolutionOptions options, UriMemoryManager * memory) {
|
||||
int res;
|
||||
|
||||
URI_CHECK_MEMORY_MANAGER(memory); /* may return */
|
||||
|
||||
res = URI_FUNC(AddBaseUriImpl)(absDest, relSource, absBase, options, memory);
|
||||
if ((res != URI_SUCCESS) && (absDest != NULL)) {
|
||||
URI_FUNC(FreeUriMembersMm)(absDest, memory);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
324
ext/uri/uriparser/src/UriShorten.c
Normal file
324
ext/uri/uriparser/src/UriShorten.c
Normal file
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* uriparser - RFC 3986 URI parsing library
|
||||
*
|
||||
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
|
||||
* Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* What encodings are enabled? */
|
||||
#include <uriparser/UriDefsConfig.h>
|
||||
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
|
||||
/* Include SELF twice */
|
||||
# ifdef URI_ENABLE_ANSI
|
||||
# define URI_PASS_ANSI 1
|
||||
# include "UriShorten.c"
|
||||
# undef URI_PASS_ANSI
|
||||
# endif
|
||||
# ifdef URI_ENABLE_UNICODE
|
||||
# define URI_PASS_UNICODE 1
|
||||
# include "UriShorten.c"
|
||||
# undef URI_PASS_UNICODE
|
||||
# endif
|
||||
#else
|
||||
# ifdef URI_PASS_ANSI
|
||||
# include <uriparser/UriDefsAnsi.h>
|
||||
# else
|
||||
# include <uriparser/UriDefsUnicode.h>
|
||||
# include <wchar.h>
|
||||
# endif
|
||||
|
||||
|
||||
|
||||
#ifndef URI_DOXYGEN
|
||||
# include <uriparser/Uri.h>
|
||||
# include "UriCommon.h"
|
||||
# include "UriMemory.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static URI_INLINE UriBool URI_FUNC(AppendSegment)(URI_TYPE(Uri) * uri,
|
||||
const URI_CHAR * first, const URI_CHAR * afterLast,
|
||||
UriMemoryManager * memory) {
|
||||
/* Create segment */
|
||||
URI_TYPE(PathSegment) * segment = memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment)));
|
||||
if (segment == NULL) {
|
||||
return URI_FALSE; /* Raises malloc error */
|
||||
}
|
||||
segment->next = NULL;
|
||||
segment->text.first = first;
|
||||
segment->text.afterLast = afterLast;
|
||||
|
||||
/* Put into chain */
|
||||
if (uri->pathTail == NULL) {
|
||||
uri->pathHead = segment;
|
||||
} else {
|
||||
uri->pathTail->next = segment;
|
||||
}
|
||||
uri->pathTail = segment;
|
||||
|
||||
return URI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static URI_INLINE UriBool URI_FUNC(EqualsAuthority)(const URI_TYPE(Uri) * first,
|
||||
const URI_TYPE(Uri) * second) {
|
||||
/* IPv4 */
|
||||
if (first->hostData.ip4 != NULL) {
|
||||
return ((second->hostData.ip4 != NULL)
|
||||
&& !memcmp(first->hostData.ip4->data,
|
||||
second->hostData.ip4->data, 4)) ? URI_TRUE : URI_FALSE;
|
||||
}
|
||||
|
||||
/* IPv6 */
|
||||
if (first->hostData.ip6 != NULL) {
|
||||
return ((second->hostData.ip6 != NULL)
|
||||
&& !memcmp(first->hostData.ip6->data,
|
||||
second->hostData.ip6->data, 16)) ? URI_TRUE : URI_FALSE;
|
||||
}
|
||||
|
||||
/* IPvFuture */
|
||||
if (first->hostData.ipFuture.first != NULL) {
|
||||
return ((second->hostData.ipFuture.first != NULL)
|
||||
&& !URI_FUNC(CompareRange)(&first->hostData.ipFuture,
|
||||
&second->hostData.ipFuture)) ? URI_TRUE : URI_FALSE;
|
||||
}
|
||||
|
||||
return !URI_FUNC(CompareRange)(&first->hostText, &second->hostText)
|
||||
? URI_TRUE : URI_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,
|
||||
const URI_TYPE(Uri) * absSource,
|
||||
const URI_TYPE(Uri) * absBase,
|
||||
UriBool domainRootMode, UriMemoryManager * memory) {
|
||||
if (dest == NULL) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
URI_FUNC(ResetUri)(dest);
|
||||
|
||||
if ((absSource == NULL) || (absBase == NULL)) {
|
||||
return URI_ERROR_NULL;
|
||||
}
|
||||
|
||||
/* absBase absolute? */
|
||||
if (absBase->scheme.first == NULL) {
|
||||
return URI_ERROR_REMOVEBASE_REL_BASE;
|
||||
}
|
||||
|
||||
/* absSource absolute? */
|
||||
if (absSource->scheme.first == NULL) {
|
||||
return URI_ERROR_REMOVEBASE_REL_SOURCE;
|
||||
}
|
||||
|
||||
/* [01/50] if (A.scheme != Base.scheme) then */
|
||||
if (URI_FUNC(CompareRange)(&absSource->scheme, &absBase->scheme)) {
|
||||
/* [02/50] T.scheme = A.scheme; */
|
||||
dest->scheme = absSource->scheme;
|
||||
/* [03/50] T.authority = A.authority; */
|
||||
if (!URI_FUNC(CopyAuthority)(dest, absSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [04/50] T.path = A.path; */
|
||||
if (!URI_FUNC(CopyPath)(dest, absSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [05/50] else */
|
||||
} else {
|
||||
/* [06/50] undef(T.scheme); */
|
||||
/* NOOP */
|
||||
/* [07/50] if (A.authority != Base.authority) then */
|
||||
if (!URI_FUNC(EqualsAuthority)(absSource, absBase)) {
|
||||
/* [08/50] T.authority = A.authority; */
|
||||
if (!URI_FUNC(CopyAuthority)(dest, absSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [09/50] T.path = A.path; */
|
||||
if (!URI_FUNC(CopyPath)(dest, absSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [10/50] else */
|
||||
} else {
|
||||
/* [11/50] if domainRootMode then */
|
||||
if (domainRootMode == URI_TRUE) {
|
||||
/* [12/50] undef(T.authority); */
|
||||
/* NOOP */
|
||||
/* [13/50] if (first(A.path) == "") then */
|
||||
/* GROUPED */
|
||||
/* [14/50] T.path = "/." + A.path; */
|
||||
/* GROUPED */
|
||||
/* [15/50] else */
|
||||
/* GROUPED */
|
||||
/* [16/50] T.path = A.path; */
|
||||
/* GROUPED */
|
||||
/* [17/50] endif; */
|
||||
if (!URI_FUNC(CopyPath)(dest, absSource, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
dest->absolutePath = URI_TRUE;
|
||||
|
||||
if (!URI_FUNC(FixAmbiguity)(dest, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [18/50] else */
|
||||
} else {
|
||||
const URI_TYPE(PathSegment) * sourceSeg = absSource->pathHead;
|
||||
const URI_TYPE(PathSegment) * baseSeg = absBase->pathHead;
|
||||
/* [19/50] bool pathNaked = true; */
|
||||
UriBool pathNaked = URI_TRUE;
|
||||
/* [20/50] undef(last(Base.path)); */
|
||||
/* NOOP */
|
||||
/* [21/50] T.path = ""; */
|
||||
dest->absolutePath = URI_FALSE;
|
||||
/* [22/50] while (first(A.path) == first(Base.path)) do */
|
||||
while ((sourceSeg != NULL) && (baseSeg != NULL)
|
||||
&& !URI_FUNC(CompareRange)(&sourceSeg->text, &baseSeg->text)
|
||||
&& !((sourceSeg->text.first == sourceSeg->text.afterLast)
|
||||
&& ((sourceSeg->next == NULL) != (baseSeg->next == NULL)))) {
|
||||
/* [23/50] A.path++; */
|
||||
sourceSeg = sourceSeg->next;
|
||||
/* [24/50] Base.path++; */
|
||||
baseSeg = baseSeg->next;
|
||||
/* [25/50] endwhile; */
|
||||
}
|
||||
/* [26/50] while defined(first(Base.path)) do */
|
||||
while ((baseSeg != NULL) && (baseSeg->next != NULL)) {
|
||||
/* [27/50] Base.path++; */
|
||||
baseSeg = baseSeg->next;
|
||||
/* [28/50] T.path += "../"; */
|
||||
if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstParent),
|
||||
URI_FUNC(ConstParent) + 2, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [29/50] pathNaked = false; */
|
||||
pathNaked = URI_FALSE;
|
||||
/* [30/50] endwhile; */
|
||||
}
|
||||
/* [31/50] while defined(first(A.path)) do */
|
||||
while (sourceSeg != NULL) {
|
||||
/* [32/50] if pathNaked then */
|
||||
if (pathNaked == URI_TRUE) {
|
||||
/* [33/50] if (first(A.path) contains ":") then */
|
||||
UriBool containsColon = URI_FALSE;
|
||||
const URI_CHAR * ch = sourceSeg->text.first;
|
||||
for (; ch < sourceSeg->text.afterLast; ch++) {
|
||||
if (*ch == _UT(':')) {
|
||||
containsColon = URI_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (containsColon) {
|
||||
/* [34/50] T.path += "./"; */
|
||||
if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstPwd),
|
||||
URI_FUNC(ConstPwd) + 1, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [35/50] elseif (first(A.path) == "") then */
|
||||
} else if (sourceSeg->text.first == sourceSeg->text.afterLast) {
|
||||
/* [36/50] T.path += "/."; */
|
||||
if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstPwd),
|
||||
URI_FUNC(ConstPwd) + 1, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [37/50] endif; */
|
||||
}
|
||||
/* [38/50] endif; */
|
||||
}
|
||||
/* [39/50] T.path += first(A.path); */
|
||||
if (!URI_FUNC(AppendSegment)(dest, sourceSeg->text.first,
|
||||
sourceSeg->text.afterLast, memory)) {
|
||||
return URI_ERROR_MALLOC;
|
||||
}
|
||||
/* [40/50] pathNaked = false; */
|
||||
pathNaked = URI_FALSE;
|
||||
/* [41/50] A.path++; */
|
||||
sourceSeg = sourceSeg->next;
|
||||
/* [42/50] if defined(first(A.path)) then */
|
||||
/* NOOP */
|
||||
/* [43/50] T.path += + "/"; */
|
||||
/* NOOP */
|
||||
/* [44/50] endif; */
|
||||
/* NOOP */
|
||||
/* [45/50] endwhile; */
|
||||
}
|
||||
/* [46/50] endif; */
|
||||
}
|
||||
/* [47/50] endif; */
|
||||
}
|
||||
/* [48/50] endif; */
|
||||
}
|
||||
/* [49/50] T.query = A.query; */
|
||||
dest->query = absSource->query;
|
||||
/* [50/50] T.fragment = A.fragment; */
|
||||
dest->fragment = absSource->fragment;
|
||||
|
||||
return URI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(RemoveBaseUri)(URI_TYPE(Uri) * dest,
|
||||
const URI_TYPE(Uri) * absSource,
|
||||
const URI_TYPE(Uri) * absBase,
|
||||
UriBool domainRootMode) {
|
||||
return URI_FUNC(RemoveBaseUriMm)(dest, absSource, absBase,
|
||||
domainRootMode, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int URI_FUNC(RemoveBaseUriMm)(URI_TYPE(Uri) * dest,
|
||||
const URI_TYPE(Uri) * absSource,
|
||||
const URI_TYPE(Uri) * absBase,
|
||||
UriBool domainRootMode, UriMemoryManager * memory) {
|
||||
int res;
|
||||
|
||||
URI_CHECK_MEMORY_MANAGER(memory); /* may return */
|
||||
|
||||
res = URI_FUNC(RemoveBaseUriImpl)(dest, absSource,
|
||||
absBase, domainRootMode, memory);
|
||||
if ((res != URI_SUCCESS) && (dest != NULL)) {
|
||||
URI_FUNC(FreeUriMembersMm)(dest, memory);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -24,6 +24,7 @@ $excludes = [
|
|||
// Bundled libraries / files.
|
||||
'ext/date/lib/',
|
||||
'ext/lexbor/lexbor/',
|
||||
'ext/uri/uriparser/',
|
||||
'ext/fileinfo/data_file.c',
|
||||
'ext/fileinfo/libmagic/',
|
||||
'ext/gd/libgd/',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue