uriparser 0.6.4
authorSebastian Pipping <sebastian@pipping.org>
Sun, 2 Mar 2008 22:57:46 +0000 (22:57 +0000)
committerSebastian Pipping <sebastian@pipping.org>
Sun, 2 Mar 2008 22:57:46 +0000 (22:57 +0000)
git-svn-id: https://libspiff.svn.sourceforge.net/svnroot/libspiff/trunk@392 2ecee7ff-471c-0410-b4a6-9273fec9c0b9

16 files changed:
win32/uriparser/Uri.h
win32/uriparser/UriBase.h
win32/uriparser/UriCommon.c
win32/uriparser/UriCommon.h
win32/uriparser/UriCompare.c
win32/uriparser/UriEscape.c
win32/uriparser/UriFile.c
win32/uriparser/UriNormalize.c
win32/uriparser/UriNormalizeBase.c
win32/uriparser/UriNormalizeBase.h
win32/uriparser/UriParse.c
win32/uriparser/UriParseBase.c
win32/uriparser/UriParseBase.h
win32/uriparser/UriRecompose.c
win32/uriparser/UriResolve.c
win32/uriparser/UriShorten.c

index 7a9723f..8f7f1c9 100644 (file)
@@ -91,7 +91,7 @@ extern "C" {
 typedef struct URI_TYPE(TextRangeStruct) {
        const URI_CHAR * first; /**< Pointer to first character */
        const URI_CHAR * afterLast; /**< Pointer to character after the last one still in */
-} URI_TYPE(TextRange);
+} URI_TYPE(TextRange); /**< @copydoc UriTextRangeStructA */
 
 
 
@@ -105,7 +105,7 @@ typedef struct URI_TYPE(PathSegmentStruct) {
        struct URI_TYPE(PathSegmentStruct) * next; /**< Pointer to the next path segment in the list, can be NULL if last already */
 
        void * reserved; /**< Reserved to the parser */
-} URI_TYPE(PathSegment);
+} URI_TYPE(PathSegment); /**< @copydoc UriPathSegmentStructA */
 
 
 
@@ -119,7 +119,7 @@ typedef struct URI_TYPE(HostDataStruct) {
        UriIp4 * ip4; /**< IPv4 address */
        UriIp6 * ip6; /**< IPv6 address */
        URI_TYPE(TextRange) ipFuture; /**< IPvFuture address */
-} URI_TYPE(HostData);
+} URI_TYPE(HostData); /**< @copydoc UriHostDataStructA */
 
 
 
@@ -141,7 +141,7 @@ typedef struct URI_TYPE(UriStruct) {
        UriBool owner; /**< Memory owner flag */
 
        void * reserved; /**< Reserved to the parser */
-} URI_TYPE(Uri);
+} URI_TYPE(Uri); /**< @copydoc UriUriStructA */
 
 
 
@@ -156,7 +156,7 @@ typedef struct URI_TYPE(ParserStateStruct) {
        const URI_CHAR * errorPos; /**< Pointer to position in case of a syntax error */
 
        void * reserved; /**< Reserved to the parser */
-} URI_TYPE(ParserState);
+} URI_TYPE(ParserState); /**< @copydoc UriParserStateStructA */
 
 
 
@@ -387,9 +387,10 @@ int URI_FUNC(NormalizeSyntax)(URI_TYPE(Uri) * uri);
 
 
 /**
- * Converts an absolute Unix filename to a %URI string.
- * The destination buffer must be large enough to hold
- * 7 + 3 * len(filename) + 1 characters.
+ * Converts a Unix filename to a %URI string.
+ * The destination buffer must be large enough to hold 7 + 3 * len(filename) + 1
+ * characters in case of an absolute filename or 3 * len(filename) + 1 in case
+ * of a relative filename.
  *
  * EXAMPLE
  *   Input:  "/bin/bash"
@@ -405,9 +406,10 @@ int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename,
 
 
 /**
- * Converts an absolute Windows filename to a %URI string.
- * The destination buffer must be large enough to hold
- * 8 + 3 * len(filename) + 1 characters.
+ * Converts a Windows filename to a %URI string.
+ * The destination buffer must be large enough to hold 8 + 3 * len(filename) + 1
+ * characters in case of an absolute filename or 3 * len(filename) + 1 in case
+ * of a relative filename.
  *
  * EXAMPLE
  *   Input:  "E:\\Documents and Settings"
@@ -423,9 +425,10 @@ int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename,
 
 
 /**
- * Extracts an absolute Unix filename from a %URI string.
- * The destination buffer must be large enough to hold
- * len(uriString) + 1 - 7 characters.
+ * Extracts a Unix filename from a %URI string.
+ * The destination buffer must be large enough to hold len(uriString) + 1 - 7
+ * characters in case of an absolute %URI or len(uriString) + 1 in case
+ * of a relative %URI.
  *
  * @param uriString    %URI string to convert
  * @param filename     Destination to write filename to
@@ -437,9 +440,10 @@ int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString,
 
 
 /**
- * Extracts an absolute Windows filename from a %URI string.
- * The destination buffer must be large enough to hold
- * len(uriString) + 1 - 8 characters.
+ * Extracts a Windows filename from a %URI string.
+ * The destination buffer must be large enough to hold len(uriString) + 1 - 8
+ * characters in case of an absolute %URI or len(uriString) + 1 in case
+ * of a relative %URI.
  *
  * @param uriString    %URI string to convert
  * @param filename     Destination to write filename to
index b9de026..60f3446 100644 (file)
@@ -54,8 +54,8 @@
 
 /* Version */
 #define URI_VER_MAJOR           0
-#define URI_VER_MINOR           5
-#define URI_VER_RELEASE         2
+#define URI_VER_MINOR           6
+#define URI_VER_RELEASE         4
 #define URI_VER_SUFFIX_ANSI     ""
 #define URI_VER_SUFFIX_UNICODE  URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI)
 
@@ -137,7 +137,7 @@ typedef int UriBool; /**< Boolean type */
  */
 typedef struct UriIp4Struct {
        unsigned char data[4]; /**< Each octet in one byte */
-} UriIp4;
+} UriIp4; /**< @copydoc UriIp4Struct */
 
 
 
@@ -146,7 +146,7 @@ typedef struct UriIp4Struct {
  */
 typedef struct UriIp6Struct {
        unsigned char data[16]; /**< Each quad in two bytes */
-} UriIp6;
+} UriIp6; /**< @copydoc UriIp6Struct */
 
 
 
@@ -154,14 +154,14 @@ typedef struct UriIp6Struct {
  * Specifies a line break conversion mode
  */
 typedef enum UriBreakConversionEnum {
-       URI_BR_TO_LF,
-       URI_BR_TO_CRLF,
-       URI_BR_TO_CR,
-       URI_BR_TO_UNIX = URI_BR_TO_LF,
-       URI_BR_TO_WINDOWS = URI_BR_TO_CRLF,
-       URI_BR_TO_MAC = URI_BR_TO_CR,
-       URI_BR_DONT_TOUCH
-} UriBreakConversion;
+       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 */
 
 
 
@@ -169,14 +169,14 @@ typedef enum UriBreakConversionEnum {
  * Specifies which component of a %URI has to be normalized.
  */
 typedef enum UriNormalizationMaskEnum {
-       URI_NORMALIZED = 0,
-       URI_NORMALIZE_SCHEME = 1 << 0, /* Because of uppercase letters */
-       URI_NORMALIZE_USER_INFO = 1 << 1, /* .. uppercase percent-encodings */
-       URI_NORMALIZE_HOST = 1 << 2, /* .. uppercase letters */
-       URI_NORMALIZE_PATH = 1 << 3, /* .. uppercase percent-encodings or dot segments */
-       URI_NORMALIZE_QUERY = 1 << 4, /* .. uppercase percent-encodings */
-       URI_NORMALIZE_FRAGMENT = 1 << 5 /* .. uppercase percent-encodings */
-} UriNormalizationMask;
+       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 */
 
 
 
index 268dbf3..9fd4d71 100644 (file)
-/*\r
- * uriparser - RFC 3986 URI parsing library\r
- *\r
- * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>\r
- * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>\r
- * All rights reserved.\r
- *\r
- * Redistribution  and use in source and binary forms, with or without\r
- * modification,  are permitted provided that the following conditions\r
- * are met:\r
- *\r
- *     * Redistributions   of  source  code  must  retain  the   above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer.\r
- *\r
- *     * Redistributions  in  binary  form must  reproduce  the  above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer   in  the  documentation  and/or  other  materials\r
- *       provided with the distribution.\r
- *\r
- *     * Neither  the name of the <ORGANIZATION> nor the names of  its\r
- *       contributors  may  be  used to endorse  or  promote  products\r
- *       derived  from  this software without specific  prior  written\r
- *       permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT\r
- * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS\r
- * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE\r
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES\r
- * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-/* What encodings are enabled? */\r
-#include <uriparser/UriDefsConfig.h>\r
-#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))\r
-/* Include SELF twice */\r
-# define URI_PASS_ANSI 1\r
-# include "UriCommon.c"\r
-# undef URI_PASS_ANSI\r
-# define URI_PASS_UNICODE 1\r
-# include "UriCommon.c"\r
-# undef URI_PASS_UNICODE\r
-#else\r
-# ifdef URI_PASS_ANSI\r
-#  include <uriparser/UriDefsAnsi.h>\r
-# else\r
-#  include <uriparser/UriDefsUnicode.h>\r
-#  include <wchar.h>\r
-# endif\r
-\r
-\r
-\r
-#ifndef URI_DOXYGEN\r
-# include <uriparser/Uri.h>\r
-# include "UriCommon.h"\r
-#endif\r
-\r
-\r
-\r
-/*extern*/ const URI_CHAR * const URI_FUNC(SafeToPointTo) = _UT("X");\r
-/*extern*/ const URI_CHAR * const URI_FUNC(ConstPwd) = _UT(".");\r
-/*extern*/ const URI_CHAR * const URI_FUNC(ConstParent) = _UT("..");\r
-\r
-\r
-\r
-void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) {\r
-       memset(uri, 0, sizeof(URI_TYPE(Uri)));\r
-}\r
-\r
-\r
-\r
-/* Properly removes "." and ".." path segments */\r
-UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri) {\r
-       URI_TYPE(PathSegment) * walker;\r
-       if ((uri == NULL) || (uri->pathHead == NULL)) {\r
-               return URI_TRUE;\r
-       }\r
-\r
-       walker = uri->pathHead;\r
-       walker->reserved = NULL; /* Prev pointer */\r
-       do {\r
-               int len = (int)(walker->text.afterLast - walker->text.first);\r
-               switch (len) {\r
-               case 1:\r
-                       if ((walker->text.first)[0] == _UT('.')) {\r
-                               /* Path "." -> remove this segment */\r
-                               URI_TYPE(PathSegment) * const prev = walker->reserved;\r
-                               URI_TYPE(PathSegment) * const nextBackup = walker->next;\r
-\r
-                               /* Last segment? */\r
-                               if (walker->next != NULL) {\r
-                                       /* Not last segment */\r
-                                       walker->next->reserved = prev;\r
-\r
-                                       if (prev == NULL) {\r
-                                               /* First but not last segment */\r
-                                               uri->pathHead = walker->next;\r
-                                       } else {\r
-                                               /* Middle segment */\r
-                                               prev->next = walker->next;\r
-                                       }\r
-\r
-                                       if (uri->owner) {\r
-                                               free((URI_CHAR *)walker->text.first);\r
-                                       }\r
-                                       free(walker);\r
-                               } else {\r
-                                       /* Last segment */\r
-                                       if (prev == NULL) {\r
-                                               /* Last and first */\r
-                                               if (uri->owner) {\r
-                                                       free((URI_CHAR *)walker->text.first);\r
-                                               }\r
-                                               free(walker);\r
-\r
-                                               uri->pathHead = NULL;\r
-                                               uri->pathTail = NULL;\r
-                                       } else {\r
-                                               /* Last but not first, replace "." with empty segment to represent trailing slash */\r
-                                               if (uri->owner) {\r
-                                                       free((URI_CHAR *)walker->text.first);\r
-                                               }\r
-                                               walker->text.first = URI_FUNC(SafeToPointTo);\r
-                                               walker->text.afterLast = URI_FUNC(SafeToPointTo);\r
-                                       }\r
-                               }\r
-\r
-                               walker = nextBackup;\r
-                       } else {\r
-                               if (walker->next != NULL) {\r
-                                       walker->next->reserved = walker;\r
-                               } else {\r
-                                       /* Last segment -> update tail */\r
-                                       uri->pathTail = walker;\r
-                               }\r
-                               walker = walker->next;\r
-                       }\r
-                       break;\r
-\r
-               case 2:\r
-                       if (((walker->text.first)[0] == _UT('.'))\r
-                                       && ((walker->text.first)[1] == _UT('.'))) {\r
-                               /* Path ".." -> remove this and the previous segment */\r
-                               URI_TYPE(PathSegment) * const prev = walker->reserved;\r
-                               URI_TYPE(PathSegment) * prevPrev;\r
-                               URI_TYPE(PathSegment) * const nextBackup = walker->next;\r
-                               if (prev != NULL) {\r
-                                       /* Not first segment */\r
-                                       prevPrev = prev->reserved;\r
-                                       if (prevPrev != NULL) {\r
-                                               /* Not even prev is the first one */\r
-                                               prevPrev->next = walker->next;\r
-                                               if (walker->next != NULL) {\r
-                                                       walker->next->reserved = prevPrev;\r
-                                               } else {\r
-                                                       /* Last segment -> insert "" segment to represent trailing slash, update tail */\r
-                                                       URI_TYPE(PathSegment) * const segment = malloc(1 * sizeof(URI_TYPE(PathSegment)));\r
-                                                       if (segment == NULL) {\r
-                                                               if (uri->owner) {\r
-                                                                       free((URI_CHAR *)walker->text.first);\r
-                                                               }\r
-                                                               free(walker);\r
-\r
-                                                               if (uri->owner) {\r
-                                                                       free((URI_CHAR *)prev->text.first);\r
-                                                               }\r
-                                                               free(prev);\r
-\r
-                                                               return URI_FALSE; /* Raises malloc error */\r
-                                                       }\r
-                                                       memset(segment, 0, sizeof(URI_TYPE(PathSegment)));\r
-                                                       segment->text.first = URI_FUNC(SafeToPointTo);\r
-                                                       segment->text.afterLast = URI_FUNC(SafeToPointTo);\r
-                                                       prevPrev->next = segment;\r
-                                                       uri->pathTail = segment;\r
-                                               }\r
-\r
-                                               if (uri->owner) {\r
-                                                       free((URI_CHAR *)walker->text.first);\r
-                                               }\r
-                                               free(walker);\r
-\r
-                                               if (uri->owner) {\r
-                                                       free((URI_CHAR *)prev->text.first);\r
-                                               }\r
-                                               free(prev);\r
-\r
-                                               walker = nextBackup;\r
-                                       } else {\r
-                                               /* Prev is the first segment */\r
-                                               uri->pathHead = walker->next;\r
-                                               if (walker->next != NULL) {\r
-                                                       walker->next->reserved = NULL;\r
-                                               } else {\r
-                                                       /* Last segment -> update tail */\r
-                                                       uri->pathTail = NULL;\r
-                                               }\r
-\r
-                                               if (uri->owner) {\r
-                                                       free((URI_CHAR *)walker->text.first);\r
-                                               }\r
-                                               free(walker);\r
-\r
-                                               if (uri->owner) {\r
-                                                       free((URI_CHAR *)prev->text.first);\r
-                                               }\r
-                                               free(prev);\r
-\r
-                                               walker = nextBackup;\r
-                                       }\r
-                               } else {\r
-                                       URI_TYPE(PathSegment) * const nextBackup = walker->next;\r
-                                       /* First segment -> update head pointer */\r
-                                       uri->pathHead = walker->next;\r
-                                       if (walker->next != NULL) {\r
-                                               walker->next->reserved = NULL;\r
-                                       } else {\r
-                                               /* Last segment -> update tail */\r
-                                               uri->pathTail = NULL;\r
-                                       }\r
-\r
-                                       if (uri->owner) {\r
-                                               free((URI_CHAR *)walker->text.first);\r
-                                       }\r
-                                       free(walker);\r
-\r
-                                       walker = nextBackup;\r
-                               }\r
-                       } else {\r
-                               if (walker->next != NULL) {\r
-                                       walker->next->reserved = walker;\r
-                               } else {\r
-                                       /* Last segment -> update tail */\r
-                                       uri->pathTail = walker;\r
-                               }\r
-                               walker = walker->next;\r
-                       }\r
-                       break;\r
-\r
-               default:\r
-                       if (walker->next != NULL) {\r
-                               walker->next->reserved = walker;\r
-                       } else {\r
-                               /* Last segment -> update tail */\r
-                               uri->pathTail = walker;\r
-                       }\r
-                       walker = walker->next;\r
-                       break;\r
-\r
-               }\r
-       } while (walker != NULL);\r
-\r
-       /* Fix path if only one empty segment */\r
-       if ((uri->pathHead != NULL)\r
-                       && (uri->pathHead->next == NULL)\r
-                       && (uri->pathHead->text.first == uri->pathHead->text.afterLast)) {\r
-               free(uri->pathHead);\r
-               uri->pathHead = NULL;\r
-               uri->pathTail = NULL;\r
-       }\r
-\r
-       return URI_TRUE;\r
-}\r
-\r
-\r
-\r
-unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig) {\r
-       switch (hexdig) {\r
-       case _UT('0'):\r
-       case _UT('1'):\r
-       case _UT('2'):\r
-       case _UT('3'):\r
-       case _UT('4'):\r
-       case _UT('5'):\r
-       case _UT('6'):\r
-       case _UT('7'):\r
-       case _UT('8'):\r
-       case _UT('9'):\r
-               return (unsigned char)(9 + hexdig - _UT('9'));\r
-\r
-       case _UT('a'):\r
-       case _UT('b'):\r
-       case _UT('c'):\r
-       case _UT('d'):\r
-       case _UT('e'):\r
-       case _UT('f'):\r
-               return (unsigned char)(15 + hexdig - _UT('f'));\r
-\r
-       case _UT('A'):\r
-       case _UT('B'):\r
-       case _UT('C'):\r
-       case _UT('D'):\r
-       case _UT('E'):\r
-       case _UT('F'):\r
-               return (unsigned char)(15 + hexdig - _UT('F'));\r
-\r
-       default:\r
-               return 0;\r
-       }\r
-}\r
-\r
-\r
-\r
-URI_CHAR URI_FUNC(HexToLetter)(unsigned int value) {\r
-       switch (value) {\r
-       case  0: return _UT('0');\r
-       case  1: return _UT('1');\r
-       case  2: return _UT('2');\r
-       case  3: return _UT('3');\r
-       case  4: return _UT('4');\r
-       case  5: return _UT('5');\r
-       case  6: return _UT('6');\r
-       case  7: return _UT('7');\r
-       case  8: return _UT('8');\r
-       case  9: return _UT('9');\r
-\r
-       /* Uppercase recommended in section 2.1. of RFC 3986 *\r
-        * http://tools.ietf.org/html/rfc3986#section-2.1    */\r
-       case 10: return _UT('A');\r
-       case 11: return _UT('B');\r
-       case 12: return _UT('C');\r
-       case 13: return _UT('D');\r
-       case 14: return _UT('E');\r
-       default: return _UT('F');\r
-       }\r
-}\r
-\r
-\r
-\r
-/* Checks if a URI has the host component set. */\r
-UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri) {\r
-       return (uri != NULL)\r
-                       && ((uri->hostText.first != NULL)\r
-                               || (uri->hostData.ip4 != NULL)\r
-                               || (uri->hostData.ip6 != NULL)\r
-                               || (uri->hostData.ipFuture.first != NULL)\r
-                       );\r
-}\r
-\r
-\r
-\r
-/* Copies the path segment list from one URI to another. */\r
-UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest,\r
-               const URI_TYPE(Uri) * source) {\r
-       if (source->pathHead == NULL) {\r
-               /* No path component */\r
-               dest->pathHead = NULL;\r
-               dest->pathTail = NULL;\r
-       } else {\r
-               /* Copy list but not the text contained */\r
-               URI_TYPE(PathSegment) * sourceWalker = source->pathHead;\r
-               URI_TYPE(PathSegment) * destPrev = NULL;\r
-               do {\r
-                       URI_TYPE(PathSegment) * cur = malloc(sizeof(URI_TYPE(PathSegment)));\r
-                       if (cur == NULL) {\r
-                               /* Fix broken list */\r
-                               if (destPrev != NULL) {\r
-                                       destPrev->next = NULL;\r
-                               }\r
-                               return URI_FALSE; /* Raises malloc error */\r
-                       }\r
-\r
-                       /* From this functions usage we know that *\r
-                        * the dest URI cannot be uri->owner      */\r
-                       cur->text = sourceWalker->text;\r
-                       if (destPrev == NULL) {\r
-                               /* First segment ever */\r
-                               dest->pathHead = cur;\r
-                       } else {\r
-                               destPrev->next = cur;\r
-                       }\r
-                       destPrev = cur;\r
-                       sourceWalker = sourceWalker->next;\r
-               } while (sourceWalker != NULL);\r
-               dest->pathTail = destPrev;\r
-               dest->pathTail->next = NULL;\r
-       }\r
-\r
-       dest->absolutePath = source->absolutePath;\r
-       return URI_TRUE;\r
-}\r
-\r
-\r
-\r
-/* Copies the authority part of an URI over to another. */\r
-UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest,\r
-               const URI_TYPE(Uri) * source) {\r
-       /* From this functions usage we know that *\r
-        * the dest URI cannot be uri->owner      */\r
-\r
-       /* Copy userInfo */\r
-       dest->userInfo = source->userInfo;\r
-\r
-       /* Copy hostText */\r
-       dest->hostText = source->hostText;\r
-\r
-       /* Copy hostData */\r
-       if (source->hostData.ip4 != NULL) {\r
-               dest->hostData.ip4 = malloc(sizeof(UriIp4));\r
-               if (dest->hostData.ip4 == NULL) {\r
-                       return URI_FALSE; /* Raises malloc error */\r
-               }\r
-               *(dest->hostData.ip4) = *(source->hostData.ip4);\r
-               dest->hostData.ip6 = NULL;\r
-               dest->hostData.ipFuture.first = NULL;\r
-               dest->hostData.ipFuture.afterLast = NULL;\r
-       } else if (source->hostData.ip6 != NULL) {\r
-               dest->hostData.ip4 = NULL;\r
-               dest->hostData.ip6 = malloc(sizeof(UriIp6));\r
-               if (dest->hostData.ip6 == NULL) {\r
-                       return URI_FALSE; /* Raises malloc error */\r
-               }\r
-               *(dest->hostData.ip6) = *(source->hostData.ip6);\r
-               dest->hostData.ipFuture.first = NULL;\r
-               dest->hostData.ipFuture.afterLast = NULL;\r
-       } else {\r
-               dest->hostData.ip4 = NULL;\r
-               dest->hostData.ip6 = NULL;\r
-               dest->hostData.ipFuture = source->hostData.ipFuture;\r
-       }\r
-\r
-       /* Copy portText */\r
-       dest->portText = source->portText;\r
-\r
-       return URI_TRUE;\r
-}\r
-\r
-\r
-\r
-UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri) {\r
-       URI_TYPE(PathSegment) * segment;\r
-\r
-       if (    /* Case 1: absolute path, empty first segment */\r
-                       (uri->absolutePath\r
-                       && (uri->pathHead != NULL)\r
-                       && (uri->pathHead->text.afterLast == uri->pathHead->text.first))\r
-\r
-                       /* Case 2: relative path, empty first and second segment */\r
-                       || (!uri->absolutePath\r
-                       && (uri->pathHead != NULL)\r
-                       && (uri->pathHead->next != NULL)\r
-                       && (uri->pathHead->text.afterLast == uri->pathHead->text.first)\r
-                       && (uri->pathHead->next->text.afterLast == uri->pathHead->next->text.first))) {\r
-               /* NOOP */\r
-       } else {\r
-               return URI_TRUE;\r
-       }\r
-\r
-       segment = malloc(1 * sizeof(URI_TYPE(PathSegment)));\r
-       if (segment == NULL) {\r
-               return URI_FALSE; /* Raises malloc error */\r
-       }\r
-\r
-       /* Insert "." segment in front */\r
-       segment->next = uri->pathHead;\r
-       segment->text.first = URI_FUNC(ConstPwd);\r
-       segment->text.afterLast = URI_FUNC(ConstPwd) + 1;\r
-       uri->pathHead = segment;\r
-       return URI_TRUE;\r
-}\r
-\r
-\r
-\r
-#endif\r
+/*
+ * uriparser - RFC 3986 URI parsing library
+ *
+ * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
+ * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.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:
+ *
+ *     * Redistributions   of  source  code  must  retain  the   above
+ *       copyright  notice, this list of conditions and the  following
+ *       disclaimer.
+ *
+ *     * 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.
+ *
+ *     * Neither  the name of the <ORGANIZATION> 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 OWNER 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 */
+# define URI_PASS_ANSI 1
+# include "UriCommon.c"
+# undef URI_PASS_ANSI
+# define URI_PASS_UNICODE 1
+# include "UriCommon.c"
+# undef URI_PASS_UNICODE
+#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) {
+       memset(uri, 0, sizeof(URI_TYPE(Uri)));
+}
+
+
+
+/* Properly removes "." and ".." path segments */
+UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri,
+               UriBool relative) {
+       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? */
+                               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) {
+                                       /* Last segment? */
+                                       if (walker->next != NULL) {
+                                               /* Not last segment */
+                                               walker->next->reserved = prev;
+
+                                               if (prev == NULL) {
+                                                       /* First but not last segment */
+                                                       uri->pathHead = walker->next;
+                                               } else {
+                                                       /* Middle segment */
+                                                       prev->next = walker->next;
+                                               }
+
+                                               if (uri->owner && (walker->text.first != walker->text.afterLast)) {
+                                                       free((URI_CHAR *)walker->text.first);
+                                               }
+                                               free(walker);
+                                       } else {
+                                               /* Last segment */
+                                               if (prev == NULL) {
+                                                       /* Last and first */
+                                                       if (uri->owner && (walker->text.first != walker->text.afterLast)) {
+                                                               free((URI_CHAR *)walker->text.first);
+                                                       }
+                                                       free(walker);
+
+                                                       uri->pathHead = NULL;
+                                                       uri->pathTail = NULL;
+                                               } else {
+                                                       /* Last but not first, replace "." with empty segment to represent trailing slash */
+                                                       if (uri->owner && (walker->text.first != walker->text.afterLast)) {
+                                                               free((URI_CHAR *)walker->text.first);
+                                                       }
+                                                       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) {
+                                               removeSegment = URI_FALSE;
+                                       } else if ((prev != NULL)
+                                                       && ((prev->text.afterLast - prev->text.first) == 2)
+                                                       && ((prev->text.first)[0] == _UT('.'))
+                                                       && ((prev->text.first)[1] == _UT('.'))) {
+                                               removeSegment = URI_FALSE;
+                                       }
+                               }
+
+                               if (removeSegment) {
+                                       if (prev != NULL) {
+                                               /* Not first segment */
+                                               prevPrev = prev->reserved;
+                                               if (prevPrev != NULL) {
+                                                       /* Not even prev is the first one */
+                                                       prevPrev->next = walker->next;
+                                                       if (walker->next != NULL) {
+                                                               walker->next->reserved = prevPrev;
+                                                       } else {
+                                                               /* Last segment -> insert "" segment to represent trailing slash, update tail */
+                                                               URI_TYPE(PathSegment) * const segment = malloc(1 * sizeof(URI_TYPE(PathSegment)));
+                                                               if (segment == NULL) {
+                                                                       if (uri->owner && (walker->text.first != walker->text.afterLast)) {
+                                                                               free((URI_CHAR *)walker->text.first);
+                                                                       }
+                                                                       free(walker);
+
+                                                                       if (uri->owner && (prev->text.first != prev->text.afterLast)) {
+                                                                               free((URI_CHAR *)prev->text.first);
+                                                                       }
+                                                                       free(prev);
+
+                                                                       return URI_FALSE; /* Raises malloc error */
+                                                               }
+                                                               memset(segment, 0, sizeof(URI_TYPE(PathSegment)));
+                                                               segment->text.first = URI_FUNC(SafeToPointTo);
+                                                               segment->text.afterLast = URI_FUNC(SafeToPointTo);
+                                                               prevPrev->next = segment;
+                                                               uri->pathTail = segment;
+                                                       }
+
+                                                       if (uri->owner && (walker->text.first != walker->text.afterLast)) {
+                                                               free((URI_CHAR *)walker->text.first);
+                                                       }
+                                                       free(walker);
+
+                                                       if (uri->owner && (prev->text.first != prev->text.afterLast)) {
+                                                               free((URI_CHAR *)prev->text.first);
+                                                       }
+                                                       free(prev);
+
+                                                       walker = nextBackup;
+                                               } else {
+                                                       /* Prev is the first segment */
+                                                       uri->pathHead = walker->next;
+                                                       if (walker->next != NULL) {
+                                                               walker->next->reserved = NULL;
+                                                       } else {
+                                                               /* Last segment -> update tail */
+                                                               uri->pathTail = NULL;
+                                                       }
+
+                                                       if (uri->owner && (walker->text.first != walker->text.afterLast)) {
+                                                               free((URI_CHAR *)walker->text.first);
+                                                       }
+                                                       free(walker);
+
+                                                       if (uri->owner && (prev->text.first != prev->text.afterLast)) {
+                                                               free((URI_CHAR *)prev->text.first);
+                                                       }
+                                                       free(prev);
+
+                                                       walker = nextBackup;
+                                               }
+                                       } else {
+                                               URI_TYPE(PathSegment) * const nextBackup = walker->next;
+                                               /* First segment -> update head pointer */
+                                               uri->pathHead = walker->next;
+                                               if (walker->next != NULL) {
+                                                       walker->next->reserved = NULL;
+                                               } else {
+                                                       /* Last segment -> update tail */
+                                                       uri->pathTail = NULL;
+                                               }
+
+                                               if (uri->owner && (walker->text.first != walker->text.afterLast)) {
+                                                       free((URI_CHAR *)walker->text.first);
+                                               }
+                                               free(walker);
+
+                                               walker = nextBackup;
+                                       }
+                               }
+                       }
+                       break;
+
+               }
+
+               if (!removeSegment) {
+                       if (walker->next != NULL) {
+                               walker->next->reserved = walker;
+                       } else {
+                               /* Last segment -> update tail */
+                               uri->pathTail = walker;
+                       }
+                       walker = walker->next;
+               }
+       } while (walker != NULL);
+
+       /* Fix path if only one empty segment */
+       if ((uri->pathHead != NULL)
+                       && (uri->pathHead->next == NULL)
+                       && (uri->pathHead->text.first == uri->pathHead->text.afterLast)) {
+               free(uri->pathHead);
+               uri->pathHead = NULL;
+               uri->pathTail = NULL;
+       }
+
+       return URI_TRUE;
+}
+
+
+
+/* Properly removes "." and ".." path segments */
+UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri) {
+       const UriBool ABSOLUTE = URI_FALSE;
+       return URI_FUNC(RemoveDotSegments)(uri, ABSOLUTE);
+}
+
+
+
+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) {
+       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');
+
+       /* Uppercase recommended in section 2.1. of RFC 3986 *
+        * http://tools.ietf.org/html/rfc3986#section-2.1    */
+       case 10: return _UT('A');
+       case 11: return _UT('B');
+       case 12: return _UT('C');
+       case 13: return _UT('D');
+       case 14: return _UT('E');
+       default: return _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) {
+       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 = malloc(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) {
+       /* 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 = malloc(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 = malloc(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) {
+       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 = malloc(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;
+}
+
+
+
+#endif
index b33a4c9..2d51ba2 100644 (file)
@@ -1,92 +1,93 @@
-/*\r
- * uriparser - RFC 3986 URI parsing library\r
- *\r
- * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>\r
- * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>\r
- * All rights reserved.\r
- *\r
- * Redistribution  and use in source and binary forms, with or without\r
- * modification,  are permitted provided that the following conditions\r
- * are met:\r
- *\r
- *     * Redistributions   of  source  code  must  retain  the   above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer.\r
- *\r
- *     * Redistributions  in  binary  form must  reproduce  the  above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer   in  the  documentation  and/or  other  materials\r
- *       provided with the distribution.\r
- *\r
- *     * Neither  the name of the <ORGANIZATION> nor the names of  its\r
- *       contributors  may  be  used to endorse  or  promote  products\r
- *       derived  from  this software without specific  prior  written\r
- *       permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT\r
- * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS\r
- * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE\r
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES\r
- * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-#if (defined(URI_PASS_ANSI) && !defined(URI_COMMON_H_ANSI)) \\r
-       || (defined(URI_PASS_UNICODE) && !defined(URI_COMMON_H_UNICODE)) \\r
-       || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))\r
-/* What encodings are enabled? */\r
-#include <uriparser/UriDefsConfig.h>\r
-#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))\r
-/* Include SELF twice */\r
-# define URI_PASS_ANSI 1\r
-# include "UriCommon.h"\r
-# undef URI_PASS_ANSI\r
-# define URI_PASS_UNICODE 1\r
-# include "UriCommon.h"\r
-# undef URI_PASS_UNICODE\r
-/* Only one pass for each encoding */\r
-#elif (defined(URI_PASS_ANSI) && !defined(URI_COMMON_H_ANSI) \\r
-       && defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \\r
-       && !defined(URI_COMMON_H_UNICODE) && defined(URI_ENABLE_UNICODE))\r
-# ifdef URI_PASS_ANSI\r
-#  define URI_COMMON_H_ANSI 1\r
-#  include <uriparser/UriDefsAnsi.h>\r
-# else\r
-#  define URI_COMMON_H_UNICODE 1\r
-#  include <uriparser/UriDefsUnicode.h>\r
-# endif\r
-\r
-\r
-\r
-/* Used to point to from empty path segments.\r
- * X.first and X.afterLast must be the same non-NULL value then. */\r
-extern const URI_CHAR * const URI_FUNC(SafeToPointTo);\r
-extern const URI_CHAR * const URI_FUNC(ConstPwd);\r
-extern const URI_CHAR * const URI_FUNC(ConstParent);\r
-\r
-\r
-\r
-void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri);\r
-\r
-UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri);\r
-\r
-unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig);\r
-URI_CHAR URI_FUNC(HexToLetter)(unsigned int value);\r
-\r
-UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri);\r
-\r
-UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source);\r
-UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source);\r
-\r
-UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri);\r
-\r
-\r
-\r
-#endif\r
-#endif\r
+/*
+ * uriparser - RFC 3986 URI parsing library
+ *
+ * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
+ * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.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:
+ *
+ *     * Redistributions   of  source  code  must  retain  the   above
+ *       copyright  notice, this list of conditions and the  following
+ *       disclaimer.
+ *
+ *     * 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.
+ *
+ *     * Neither  the name of the <ORGANIZATION> 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 OWNER 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 */
+# define URI_PASS_ANSI 1
+# include "UriCommon.h"
+# undef URI_PASS_ANSI
+# define URI_PASS_UNICODE 1
+# include "UriCommon.h"
+# undef URI_PASS_UNICODE
+/* 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);
+
+UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri);
+UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri, UriBool relative);
+
+unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig);
+URI_CHAR URI_FUNC(HexToLetter)(unsigned int value);
+
+UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri);
+
+UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source);
+UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source);
+
+UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri);
+
+
+
+#endif
+#endif
index 2c8644a..3755fdd 100644 (file)
-/*\r
- * uriparser - RFC 3986 URI parsing library\r
- *\r
- * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>\r
- * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>\r
- * All rights reserved.\r
- *\r
- * Redistribution  and use in source and binary forms, with or without\r
- * modification,  are permitted provided that the following conditions\r
- * are met:\r
- *\r
- *     * Redistributions   of  source  code  must  retain  the   above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer.\r
- *\r
- *     * Redistributions  in  binary  form must  reproduce  the  above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer   in  the  documentation  and/or  other  materials\r
- *       provided with the distribution.\r
- *\r
- *     * Neither  the name of the <ORGANIZATION> nor the names of  its\r
- *       contributors  may  be  used to endorse  or  promote  products\r
- *       derived  from  this software without specific  prior  written\r
- *       permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT\r
- * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS\r
- * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE\r
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES\r
- * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-/* What encodings are enabled? */\r
-#include <uriparser/UriDefsConfig.h>\r
-#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))\r
-/* Include SELF twice */\r
-# define URI_PASS_ANSI 1\r
-# include "UriCompare.c"\r
-# undef URI_PASS_ANSI\r
-# define URI_PASS_UNICODE 1\r
-# include "UriCompare.c"\r
-# undef URI_PASS_UNICODE\r
-#else\r
-# ifdef URI_PASS_ANSI\r
-#  include <uriparser/UriDefsAnsi.h>\r
-# else\r
-#  include <uriparser/UriDefsUnicode.h>\r
-#  include <wchar.h>\r
-# endif\r
-\r
-\r
-\r
-#ifndef URI_DOXYGEN\r
-# include <uriparser/Uri.h>\r
-# include <uriparser/UriIp4.h>\r
-# include "UriCommon.h"\r
-#endif\r
-\r
-\r
-\r
-static int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a,\r
-               const URI_TYPE(TextRange) * b);\r
-\r
-\r
-\r
-/* Compares two text ranges for equal text content */\r
-static URI_INLINE int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a,\r
-               const URI_TYPE(TextRange) * b) {\r
-       int diff;\r
-\r
-       /* NOTE: Both NULL means equal! */\r
-       if ((a == NULL) || (b == NULL)) {\r
-               return ((a == NULL) && (b == NULL)) ? URI_TRUE : URI_FALSE;\r
-       }\r
-\r
-       diff = ((int)(a->afterLast - a->first) - (int)(b->afterLast - b->first));\r
-       if (diff > 0) {\r
-               return 1;\r
-       } else if (diff < 0) {\r
-               return -1;\r
-       }\r
-\r
-       return URI_STRNCMP(a->first, b->first, (a->afterLast - a->first));\r
-}\r
-\r
-\r
-\r
-UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a,\r
-               const URI_TYPE(Uri) * b) {\r
-       /* NOTE: Both NULL means equal! */\r
-       if ((a == NULL) || (b == NULL)) {\r
-               return ((a == NULL) && (b == NULL)) ? URI_TRUE : URI_FALSE;\r
-       }\r
-\r
-       /* scheme */\r
-       if (URI_FUNC(CompareRange)(&(a->scheme), &(b->scheme))) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       /* absolutePath */\r
-       if ((a->scheme.first == NULL)&& (a->absolutePath != b->absolutePath)) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       /* userInfo */\r
-       if (URI_FUNC(CompareRange)(&(a->userInfo), &(b->userInfo))) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       /* Host */\r
-       if (((a->hostData.ip4 == NULL) != (b->hostData.ip4 == NULL))\r
-                       || ((a->hostData.ip6 == NULL) != (b->hostData.ip6 == NULL))\r
-                       || ((a->hostData.ipFuture.first == NULL)\r
-                               != (b->hostData.ipFuture.first == NULL))) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       if (a->hostData.ip4 != NULL) {\r
-               if (memcmp(a->hostData.ip4->data, b->hostData.ip4->data, 4)) {\r
-                       return URI_FALSE;\r
-               }\r
-       }\r
-\r
-       if (a->hostData.ip6 != NULL) {\r
-               if (memcmp(a->hostData.ip6->data, b->hostData.ip6->data, 16)) {\r
-                       return URI_FALSE;\r
-               }\r
-       }\r
-\r
-       if (a->hostData.ipFuture.first != NULL) {\r
-               if (URI_FUNC(CompareRange)(&(a->hostData.ipFuture), &(b->hostData.ipFuture))) {\r
-                       return URI_FALSE;\r
-               }\r
-       }\r
-\r
-       if ((a->hostData.ip4 == NULL)\r
-                       && (a->hostData.ip6 == NULL)\r
-                       && (a->hostData.ipFuture.first == NULL)) {\r
-               if (URI_FUNC(CompareRange)(&(a->hostText), &(b->hostText))) {\r
-                       return URI_FALSE;\r
-               }\r
-       }\r
-\r
-       /* portText */\r
-       if (URI_FUNC(CompareRange)(&(a->portText), &(b->portText))) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       /* Path */\r
-       if ((a->pathHead == NULL) != (b->pathHead == NULL)) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       if (a->pathHead != NULL) {\r
-               URI_TYPE(PathSegment) * walkA = a->pathHead;\r
-               URI_TYPE(PathSegment) * walkB = b->pathHead;\r
-               do {\r
-                       if (URI_FUNC(CompareRange)(&(walkA->text), &(walkB->text))) {\r
-                               return URI_FALSE;\r
-                       }\r
-                       if ((walkA->next == NULL) != (walkB->next == NULL)) {\r
-                               return URI_FALSE;\r
-                       }\r
-                       walkA = walkA->next;\r
-                       walkB = walkB->next;\r
-               } while (walkA != NULL);\r
-       }\r
-\r
-       /* query */\r
-       if (URI_FUNC(CompareRange)(&(a->query), &(b->query))) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       /* fragment */\r
-       if (URI_FUNC(CompareRange)(&(a->fragment), &(b->fragment))) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       return URI_TRUE; /* Equal*/\r
-}\r
-\r
-\r
-\r
-#endif\r
+/*
+ * uriparser - RFC 3986 URI parsing library
+ *
+ * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
+ * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.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:
+ *
+ *     * Redistributions   of  source  code  must  retain  the   above
+ *       copyright  notice, this list of conditions and the  following
+ *       disclaimer.
+ *
+ *     * 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.
+ *
+ *     * Neither  the name of the <ORGANIZATION> 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 OWNER 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 */
+# define URI_PASS_ANSI 1
+# include "UriCompare.c"
+# undef URI_PASS_ANSI
+# define URI_PASS_UNICODE 1
+# include "UriCompare.c"
+# undef URI_PASS_UNICODE
+#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
+
+
+
+static int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a,
+               const URI_TYPE(TextRange) * b);
+
+
+
+/* Compares two text ranges for equal text content */
+static URI_INLINE 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) && (b == NULL)) ? URI_TRUE : URI_FALSE;
+       }
+
+       diff = ((int)(a->afterLast - a->first) - (int)(b->afterLast - b->first));
+       if (diff > 0) {
+               return 1;
+       } else if (diff < 0) {
+               return -1;
+       }
+
+       return URI_STRNCMP(a->first, b->first, (a->afterLast - a->first));
+}
+
+
+
+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
index be5f74d..4141b4a 100644 (file)
-/*\r
- * uriparser - RFC 3986 URI parsing library\r
- *\r
- * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>\r
- * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>\r
- * All rights reserved.\r
- *\r
- * Redistribution  and use in source and binary forms, with or without\r
- * modification,  are permitted provided that the following conditions\r
- * are met:\r
- *\r
- *     * Redistributions   of  source  code  must  retain  the   above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer.\r
- *\r
- *     * Redistributions  in  binary  form must  reproduce  the  above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer   in  the  documentation  and/or  other  materials\r
- *       provided with the distribution.\r
- *\r
- *     * Neither  the name of the <ORGANIZATION> nor the names of  its\r
- *       contributors  may  be  used to endorse  or  promote  products\r
- *       derived  from  this software without specific  prior  written\r
- *       permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT\r
- * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS\r
- * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE\r
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES\r
- * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-/* What encodings are enabled? */\r
-#include <uriparser/UriDefsConfig.h>\r
-#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))\r
-/* Include SELF twice */\r
-# define URI_PASS_ANSI 1\r
-# include "UriEscape.c"\r
-# undef URI_PASS_ANSI\r
-# define URI_PASS_UNICODE 1\r
-# include "UriEscape.c"\r
-# undef URI_PASS_UNICODE\r
-#else\r
-# ifdef URI_PASS_ANSI\r
-#  include <uriparser/UriDefsAnsi.h>\r
-# else\r
-#  include <uriparser/UriDefsUnicode.h>\r
-#  include <wchar.h>\r
-# endif\r
-\r
-\r
-\r
-#ifndef URI_DOXYGEN\r
-# include <uriparser/Uri.h>\r
-# include "UriCommon.h"\r
-#endif\r
-\r
-\r
-\r
-URI_CHAR * URI_FUNC(Escape)(const URI_CHAR * in, URI_CHAR * out,\r
-               UriBool spaceToPlus, UriBool normalizeBreaks) {\r
-       return URI_FUNC(EscapeEx)(in, NULL, out, spaceToPlus, normalizeBreaks);\r
-}\r
-\r
-\r
-\r
-URI_CHAR * URI_FUNC(EscapeEx)(const URI_CHAR * inFirst,\r
-               const URI_CHAR * inAfterLast, URI_CHAR * out,\r
-               UriBool spaceToPlus, UriBool normalizeBreaks) {\r
-       const URI_CHAR * read = inFirst;\r
-       URI_CHAR * write = out;\r
-       UriBool prevWasCr = URI_FALSE;\r
-       if ((out == NULL) || (inFirst == out)) {\r
-               return NULL;\r
-       } else if (inFirst == NULL) {\r
-               if (out != NULL) {\r
-                       out[0] = _UT('\0');\r
-               }\r
-               return out;\r
-       }\r
-\r
-       for (;;) {\r
-               if ((inAfterLast != NULL) && (read >= inAfterLast)) {\r
-                       write[0] = _UT('\0');\r
-                       return write;\r
-               }\r
-\r
-               switch (read[0]) {\r
-               case _UT('\0'):\r
-                       write[0] = _UT('\0');\r
-                       return write;\r
-\r
-               case _UT(' '):\r
-                       if (spaceToPlus) {\r
-                               write[0] = _UT('+');\r
-                               write++;\r
-                       } else {\r
-                               write[0] = _UT('%');\r
-                               write[1] = _UT('2');\r
-                               write[2] = _UT('0');\r
-                               write += 3;\r
-                       }\r
-                       prevWasCr = URI_FALSE;\r
-                       break;\r
-\r
-               case _UT('a'): /* ALPHA */\r
-               case _UT('A'):\r
-               case _UT('b'):\r
-               case _UT('B'):\r
-               case _UT('c'):\r
-               case _UT('C'):\r
-               case _UT('d'):\r
-               case _UT('D'):\r
-               case _UT('e'):\r
-               case _UT('E'):\r
-               case _UT('f'):\r
-               case _UT('F'):\r
-               case _UT('g'):\r
-               case _UT('G'):\r
-               case _UT('h'):\r
-               case _UT('H'):\r
-               case _UT('i'):\r
-               case _UT('I'):\r
-               case _UT('j'):\r
-               case _UT('J'):\r
-               case _UT('k'):\r
-               case _UT('K'):\r
-               case _UT('l'):\r
-               case _UT('L'):\r
-               case _UT('m'):\r
-               case _UT('M'):\r
-               case _UT('n'):\r
-               case _UT('N'):\r
-               case _UT('o'):\r
-               case _UT('O'):\r
-               case _UT('p'):\r
-               case _UT('P'):\r
-               case _UT('q'):\r
-               case _UT('Q'):\r
-               case _UT('r'):\r
-               case _UT('R'):\r
-               case _UT('s'):\r
-               case _UT('S'):\r
-               case _UT('t'):\r
-               case _UT('T'):\r
-               case _UT('u'):\r
-               case _UT('U'):\r
-               case _UT('v'):\r
-               case _UT('V'):\r
-               case _UT('w'):\r
-               case _UT('W'):\r
-               case _UT('x'):\r
-               case _UT('X'):\r
-               case _UT('y'):\r
-               case _UT('Y'):\r
-               case _UT('z'):\r
-               case _UT('Z'):\r
-               case _UT('0'): /* DIGIT */\r
-               case _UT('1'):\r
-               case _UT('2'):\r
-               case _UT('3'):\r
-               case _UT('4'):\r
-               case _UT('5'):\r
-               case _UT('6'):\r
-               case _UT('7'):\r
-               case _UT('8'):\r
-               case _UT('9'):\r
-               case _UT('-'): /* "-" / "." / "_" / "~" */\r
-               case _UT('.'):\r
-               case _UT('_'):\r
-               case _UT('~'):\r
-                       /* Copy unmodified */\r
-                       write[0] = read[0];\r
-                       write++;\r
-\r
-                       prevWasCr = URI_FALSE;\r
-                       break;\r
-\r
-               case _UT('\x0a'):\r
-                       if (normalizeBreaks) {\r
-                               if (!prevWasCr) {\r
-                                       write[0] = _UT('%');\r
-                                       write[1] = _UT('0');\r
-                                       write[2] = _UT('D');\r
-                                       write[3] = _UT('%');\r
-                                       write[4] = _UT('0');\r
-                                       write[5] = _UT('A');\r
-                                       write += 6;\r
-                               }\r
-                       } else {\r
-                               write[0] = _UT('%');\r
-                               write[1] = _UT('0');\r
-                               write[2] = _UT('A');\r
-                               write += 3;\r
-                       }\r
-                       prevWasCr = URI_FALSE;\r
-                       break;\r
-\r
-               case _UT('\x0d'):\r
-                       if (normalizeBreaks) {\r
-                               write[0] = _UT('%');\r
-                               write[1] = _UT('0');\r
-                               write[2] = _UT('D');\r
-                               write[3] = _UT('%');\r
-                               write[4] = _UT('0');\r
-                               write[5] = _UT('A');\r
-                               write += 6;\r
-                       } else {\r
-                               write[0] = _UT('%');\r
-                               write[1] = _UT('0');\r
-                               write[2] = _UT('D');\r
-                               write += 3;\r
-                       }\r
-                       prevWasCr = URI_TRUE;\r
-                       break;\r
-\r
-               default:\r
-                       /* Percent encode */\r
-                       {\r
-                               const unsigned char code = (unsigned char)read[0];\r
-                               write[0] = _UT('%');\r
-                               write[1] = URI_FUNC(HexToLetter)(code >> 4);\r
-                               write[2] = URI_FUNC(HexToLetter)(code & 0x0f);\r
-                               write += 3;\r
-                       }\r
-                       prevWasCr = URI_FALSE;\r
-                       break;\r
-               }\r
-\r
-               read++;\r
-       }\r
-}\r
-\r
-\r
-\r
-const URI_CHAR * URI_FUNC(UnescapeInPlace)(URI_CHAR * inout) {\r
-       return URI_FUNC(UnescapeInPlaceEx)(inout, URI_FALSE, URI_BR_DONT_TOUCH);\r
-}\r
-\r
-\r
-\r
-const URI_CHAR * URI_FUNC(UnescapeInPlaceEx)(URI_CHAR * inout,\r
-               UriBool plusToSpace, UriBreakConversion breakConversion) {\r
-       URI_CHAR * read = inout;\r
-       URI_CHAR * write = inout;\r
-       UriBool prevWasCr = URI_FALSE;\r
-\r
-       if (inout == NULL) {\r
-               return NULL;\r
-       }\r
-\r
-       for (;;) {\r
-               switch (read[0]) {\r
-               case _UT('\0'):\r
-                       if (read > write) {\r
-                               write[0] = _UT('\0');\r
-                       }\r
-                       return write;\r
-\r
-               case _UT('%'):\r
-                       switch (read[1]) {\r
-                       case _UT('0'):\r
-                       case _UT('1'):\r
-                       case _UT('2'):\r
-                       case _UT('3'):\r
-                       case _UT('4'):\r
-                       case _UT('5'):\r
-                       case _UT('6'):\r
-                       case _UT('7'):\r
-                       case _UT('8'):\r
-                       case _UT('9'):\r
-                       case _UT('a'):\r
-                       case _UT('b'):\r
-                       case _UT('c'):\r
-                       case _UT('d'):\r
-                       case _UT('e'):\r
-                       case _UT('f'):\r
-                       case _UT('A'):\r
-                       case _UT('B'):\r
-                       case _UT('C'):\r
-                       case _UT('D'):\r
-                       case _UT('E'):\r
-                       case _UT('F'):\r
-                               switch (read[2]) {\r
-                               case _UT('0'):\r
-                               case _UT('1'):\r
-                               case _UT('2'):\r
-                               case _UT('3'):\r
-                               case _UT('4'):\r
-                               case _UT('5'):\r
-                               case _UT('6'):\r
-                               case _UT('7'):\r
-                               case _UT('8'):\r
-                               case _UT('9'):\r
-                               case _UT('a'):\r
-                               case _UT('b'):\r
-                               case _UT('c'):\r
-                               case _UT('d'):\r
-                               case _UT('e'):\r
-                               case _UT('f'):\r
-                               case _UT('A'):\r
-                               case _UT('B'):\r
-                               case _UT('C'):\r
-                               case _UT('D'):\r
-                               case _UT('E'):\r
-                               case _UT('F'):\r
-                                       {\r
-                                               /* Percent group found */\r
-                                               const unsigned char left = URI_FUNC(HexdigToInt)(read[1]);\r
-                                               const unsigned char right = URI_FUNC(HexdigToInt)(read[2]);\r
-                                               const int code = 16 * left + right;\r
-                                               switch (code) {\r
-                                               case 10:\r
-                                                       switch (breakConversion) {\r
-                                                       case URI_BR_TO_LF:\r
-                                                               if (!prevWasCr) {\r
-                                                                       write[0] = (URI_CHAR)10;\r
-                                                                       write++;\r
-                                                               }\r
-                                                               break;\r
-\r
-                                                       case URI_BR_TO_CRLF:\r
-                                                               if (!prevWasCr) {\r
-                                                                       write[0] = (URI_CHAR)13;\r
-                                                                       write[1] = (URI_CHAR)10;\r
-                                                                       write += 2;\r
-                                                               }\r
-                                                               break;\r
-\r
-                                                       case URI_BR_TO_CR:\r
-                                                               if (!prevWasCr) {\r
-                                                                       write[0] = (URI_CHAR)13;\r
-                                                                       write++;\r
-                                                               }\r
-                                                               break;\r
-\r
-                                                       case URI_BR_DONT_TOUCH:\r
-                                                       default:\r
-                                                               write[0] = (URI_CHAR)10;\r
-                                                               write++;\r
-\r
-                                                       }\r
-                                                       prevWasCr = URI_FALSE;\r
-                                                       break;\r
-\r
-                                               case 13:\r
-                                                       switch (breakConversion) {\r
-                                                       case URI_BR_TO_LF:\r
-                                                               write[0] = (URI_CHAR)10;\r
-                                                               write++;\r
-                                                               break;\r
-\r
-                                                       case URI_BR_TO_CRLF:\r
-                                                               write[0] = (URI_CHAR)13;\r
-                                                               write[1] = (URI_CHAR)10;\r
-                                                               write += 2;\r
-                                                               break;\r
-\r
-                                                       case URI_BR_TO_CR:\r
-                                                               write[0] = (URI_CHAR)13;\r
-                                                               write++;\r
-                                                               break;\r
-\r
-                                                       case URI_BR_DONT_TOUCH:\r
-                                                       default:\r
-                                                               write[0] = (URI_CHAR)13;\r
-                                                               write++;\r
-\r
-                                                       }\r
-                                                       prevWasCr = URI_TRUE;\r
-                                                       break;\r
-\r
-                                               default:\r
-                                                       write[0] = (URI_CHAR)(code);\r
-                                                       write++;\r
-\r
-                                                       prevWasCr = URI_FALSE;\r
-\r
-                                               }\r
-                                               read += 3;\r
-                                       }\r
-                                       break;\r
-\r
-                               default:\r
-                                       /* Copy two chars unmodified and */\r
-                                       /* look at this char again */\r
-                                       if (read > write) {\r
-                                               write[0] = read[0];\r
-                                               write[1] = read[1];\r
-                                       }\r
-                                       read += 2;\r
-                                       write += 2;\r
-\r
-                                       prevWasCr = URI_FALSE;\r
-                               }\r
-                               break;\r
-\r
-                       default:\r
-                               /* Copy one char unmodified and */\r
-                               /* look at this char again */\r
-                               if (read > write) {\r
-                                       write[0] = read[0];\r
-                               }\r
-                               read++;\r
-                               write++;\r
-\r
-                               prevWasCr = URI_FALSE;\r
-                       }\r
-                       break;\r
-\r
-               case _UT('+'):\r
-                       if (plusToSpace) {\r
-                               /* Convert '+' to ' ' */\r
-                               write[0] = _UT(' ');\r
-                       } else {\r
-                               /* Copy one char unmodified */\r
-                               if (read > write) {\r
-                                       write[0] = read[0];\r
-                               }\r
-                       }\r
-                       read++;\r
-                       write++;\r
-\r
-                       prevWasCr = URI_FALSE;\r
-                       break;\r
-\r
-               default:\r
-                       /* Copy one char unmodified */\r
-                       if (read > write) {\r
-                               write[0] = read[0];\r
-                       }\r
-                       read++;\r
-                       write++;\r
-\r
-                       prevWasCr = URI_FALSE;\r
-               }\r
-       }\r
-}\r
-\r
-\r
-\r
-#endif\r
+/*
+ * uriparser - RFC 3986 URI parsing library
+ *
+ * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
+ * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.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:
+ *
+ *     * Redistributions   of  source  code  must  retain  the   above
+ *       copyright  notice, this list of conditions and the  following
+ *       disclaimer.
+ *
+ *     * 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.
+ *
+ *     * Neither  the name of the <ORGANIZATION> 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 OWNER 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 */
+# define URI_PASS_ANSI 1
+# include "UriEscape.c"
+# undef URI_PASS_ANSI
+# define URI_PASS_UNICODE 1
+# include "UriEscape.c"
+# undef URI_PASS_UNICODE
+#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
index 66549b2..783a78a 100644 (file)
-/*\r
- * uriparser - RFC 3986 URI parsing library\r
- *\r
- * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>\r
- * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>\r
- * All rights reserved.\r
- *\r
- * Redistribution  and use in source and binary forms, with or without\r
- * modification,  are permitted provided that the following conditions\r
- * are met:\r
- *\r
- *     * Redistributions   of  source  code  must  retain  the   above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer.\r
- *\r
- *     * Redistributions  in  binary  form must  reproduce  the  above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer   in  the  documentation  and/or  other  materials\r
- *       provided with the distribution.\r
- *\r
- *     * Neither  the name of the <ORGANIZATION> nor the names of  its\r
- *       contributors  may  be  used to endorse  or  promote  products\r
- *       derived  from  this software without specific  prior  written\r
- *       permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT\r
- * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS\r
- * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE\r
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES\r
- * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-/* What encodings are enabled? */\r
-#include <uriparser/UriDefsConfig.h>\r
-#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))\r
-/* Include SELF twice */\r
-# define URI_PASS_ANSI 1\r
-# include "UriFile.c"\r
-# undef URI_PASS_ANSI\r
-# define URI_PASS_UNICODE 1\r
-# include "UriFile.c"\r
-# undef URI_PASS_UNICODE\r
-#else\r
-# ifdef URI_PASS_ANSI\r
-#  include <uriparser/UriDefsAnsi.h>\r
-# else\r
-#  include <uriparser/UriDefsUnicode.h>\r
-#  include <wchar.h>\r
-# endif\r
-\r
-\r
-\r
-#ifndef URI_DOXYGEN\r
-# include <uriparser/Uri.h>\r
-#endif\r
-\r
-
-\r
-static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename,\r
-               URI_CHAR * uriString, UriBool fromUnix) {\r
-       const URI_CHAR * const prefix = fromUnix ? _UT("file://") : _UT("file:///");\r
-       const int prefixLen = fromUnix ? 7 : 8;\r
-\r
-       const URI_CHAR * input = filename;\r
-       URI_CHAR * output = uriString + prefixLen;\r
-       const URI_CHAR * lastSep = input - 1;\r
-       UriBool firstSegment = URI_TRUE;\r
-\r
-       /* Copy prefix */\r
-       memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR));\r
-\r
-       /* Copy and escape on the fly */\r
-       for (;;) {\r
-               if ((input[0] == _UT('\0'))\r
-                               || (fromUnix && input[0] == _UT('/'))\r
-                               || (!fromUnix && input[0] == _UT('\\'))) {\r
-                       /* Copy text after last seperator */\r
-                       if (lastSep + 1 < input) {\r
-                               if (!fromUnix && (firstSegment == URI_TRUE)) {\r
-                                       /* Quick hack to not convert "C:" to "C%3A" */\r
-                                       const int charsToCopy = (int)(input - (lastSep + 1));\r
-                                       memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR));\r
-                                       output += charsToCopy;\r
-                               } else {\r
-                                       output = URI_FUNC(EscapeEx)(lastSep + 1, input, output,\r
-                                                       URI_FALSE, URI_FALSE);\r
-                               }\r
-                       }\r
-                       firstSegment = URI_FALSE;\r
-               }\r
-\r
-               if (input[0] == _UT('\0')) {\r
-                       output[0] = _UT('\0');\r
-                       break;\r
-               } else if (fromUnix && (input[0] == _UT('/'))) {\r
-                       /* Copy separators unmodified */\r
-                       output[0] = _UT('/');\r
-                       output++;\r
-                       lastSep = input;\r
-               } else if (!fromUnix && (input[0] == _UT('\\'))) {\r
-                       /* Convert backslashes to forward slashes */\r
-                       output[0] = _UT('/');\r
-                       output++;\r
-                       lastSep = input;\r
-               }\r
-               input++;\r
-       }\r
-\r
-       return URI_SUCCESS;\r
-}\r
-\r
-\r
-\r
-static URI_INLINE int URI_FUNC(UriStringToFilename)(const URI_CHAR * uriString,\r
-               URI_CHAR * filename, UriBool toUnix) {\r
-       const URI_CHAR * const prefix = toUnix ? _UT("file://") : _UT("file:///");\r
-       const int prefixLen = toUnix ? 7 : 8;\r
-       URI_CHAR * walker = filename;\r
-       size_t charsToCopy;\r
-\r
-       if (URI_STRNCMP(uriString, prefix, prefixLen)) {\r
-               return URI_ERROR_SYNTAX;\r
-       }\r
-       charsToCopy = URI_STRLEN(uriString + prefixLen) + 1;\r
-       memcpy(filename, uriString + prefixLen, charsToCopy * sizeof(URI_CHAR));\r
-       URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH);\r
-\r
-       /* Convert forward slashes to backslashes */\r
-       if (!toUnix) {\r
-               while (walker[0] != _UT('\0')) {\r
-                       if (walker[0] == _UT('/')) {\r
-                               walker[0] = _UT('\\');\r
-                       }\r
-                       walker++;\r
-               }\r
-       }\r
-\r
-       return URI_SUCCESS;\r
-}\r
-\r
-\r
-\r
-int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) {\r
-       return URI_FUNC(FilenameToUriString)(filename, uriString, URI_TRUE);\r
-}\r
-\r
-\r
-\r
-int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) {\r
-       return URI_FUNC(FilenameToUriString)(filename, uriString, URI_FALSE);\r
-}\r
-\r
-\r
-\r
-int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, URI_CHAR * filename) {\r
-       return URI_FUNC(UriStringToFilename)(uriString, filename, URI_TRUE);\r
-}\r
-\r
-\r
-\r
-int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, URI_CHAR * filename) {\r
-       return URI_FUNC(UriStringToFilename)(uriString, filename, URI_FALSE);\r
-}\r
-\r
-\r
-\r
-#endif\r
+/*
+ * uriparser - RFC 3986 URI parsing library
+ *
+ * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
+ * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.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:
+ *
+ *     * Redistributions   of  source  code  must  retain  the   above
+ *       copyright  notice, this list of conditions and the  following
+ *       disclaimer.
+ *
+ *     * 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.
+ *
+ *     * Neither  the name of the <ORGANIZATION> 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 OWNER 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 */
+# define URI_PASS_ANSI 1
+# include "UriFile.c"
+# undef URI_PASS_ANSI
+# define URI_PASS_UNICODE 1
+# include "UriFile.c"
+# undef URI_PASS_UNICODE
+#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
+
+
+
+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;
+       const UriBool absolute = (filename != NULL) && ((fromUnix && (filename[0] == _UT('/')))
+                       || (!fromUnix && (filename[0] != _UT('\0')) && (filename[1] == _UT(':'))));
+
+       if ((filename == NULL) || (uriString == NULL)) {
+               return URI_ERROR_NULL;
+       }
+
+       if (absolute) {
+               const URI_CHAR * const prefix = fromUnix ? _UT("file://") : _UT("file:///");
+               const int prefixLen = fromUnix ? 7 : 8;
+
+               /* 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 seperator */
+                       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) {
+       const URI_CHAR * const prefix = toUnix ? _UT("file://") : _UT("file:///");
+       const int prefixLen = toUnix ? 7 : 8;
+       URI_CHAR * walker = filename;
+       size_t charsToCopy;
+       const UriBool absolute = (URI_STRNCMP(uriString, prefix, prefixLen) == 0);
+       const int charsToSkip = (absolute ? prefixLen : 0);
+
+       charsToCopy = URI_STRLEN(uriString + charsToSkip) + 1;
+       memcpy(filename, uriString + charsToSkip, charsToCopy * sizeof(URI_CHAR));
+       URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH);
+
+       /* Convert forward slashes to backslashes */
+       if (!toUnix) {
+               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
index e93fb8d..db2dce9 100644 (file)
-/*\r
- * uriparser - RFC 3986 URI parsing library\r
- *\r
- * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>\r
- * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>\r
- * All rights reserved.\r
- *\r
- * Redistribution  and use in source and binary forms, with or without\r
- * modification,  are permitted provided that the following conditions\r
- * are met:\r
- *\r
- *     * Redistributions   of  source  code  must  retain  the   above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer.\r
- *\r
- *     * Redistributions  in  binary  form must  reproduce  the  above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer   in  the  documentation  and/or  other  materials\r
- *       provided with the distribution.\r
- *\r
- *     * Neither  the name of the <ORGANIZATION> nor the names of  its\r
- *       contributors  may  be  used to endorse  or  promote  products\r
- *       derived  from  this software without specific  prior  written\r
- *       permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT\r
- * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS\r
- * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE\r
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES\r
- * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-/**\r
- * @file UriNormalize.c\r
- * Holds the RFC 3986 %URI normalization implementation.\r
- * NOTE: This source file includes itself twice.\r
- */\r
-\r
-/* What encodings are enabled? */\r
-#include <uriparser/UriDefsConfig.h>\r
-#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))\r
-/* Include SELF twice */\r
-# define URI_PASS_ANSI 1\r
-# include "UriNormalize.c"\r
-# undef URI_PASS_ANSI\r
-# define URI_PASS_UNICODE 1\r
-# include "UriNormalize.c"\r
-# undef URI_PASS_UNICODE\r
-#else\r
-# ifdef URI_PASS_ANSI\r
-#  include <uriparser/UriDefsAnsi.h>\r
-# else\r
-#  include <uriparser/UriDefsUnicode.h>\r
-#  include <wchar.h>\r
-# endif\r
-\r
-\r
-\r
-#ifndef URI_DOXYGEN\r
-# include <uriparser/Uri.h>\r
-# include "UriNormalizeBase.h"\r
-# include "UriCommon.h"\r
-#endif\r
-\r
-\r
-\r
-static int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask,\r
-               unsigned int * outMask);\r
-\r
-static UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask,\r
-               unsigned int maskTest, URI_TYPE(TextRange) * range);\r
-static UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri,\r
-               unsigned int * doneMask);\r
-\r
-static void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * first,\r
-               const URI_CHAR ** afterLast);\r
-static UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first,\r
-               const URI_CHAR ** afterLast);\r
-static void URI_FUNC(FixPercentEncodingEngine)(\r
-               const URI_CHAR * inFirst, const URI_CHAR * inAfterLast,\r
-               const URI_CHAR * outFirst, const URI_CHAR ** outAfterLast);\r
-\r
-static UriBool URI_FUNC(ContainsUppercaseLetters)(const URI_CHAR * first,\r
-               const URI_CHAR * afterLast);\r
-static UriBool URI_FUNC(ContainsUglyPercentEncoding)(const URI_CHAR * first,\r
-               const URI_CHAR * afterLast);\r
-\r
-static void URI_FUNC(LowercaseInplace)(const URI_CHAR * first,\r
-               const URI_CHAR * afterLast);\r
-static UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first,\r
-               const URI_CHAR ** afterLast);\r
-\r
-static void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,\r
-               unsigned int revertMask);\r
-\r
-\r
-\r
-static URI_INLINE void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,\r
-               unsigned int revertMask) {\r
-       if (revertMask & URI_NORMALIZE_SCHEME) {\r
-               free((URI_CHAR *)uri->scheme.first);\r
-               uri->scheme.first = NULL;\r
-               uri->scheme.afterLast = NULL;\r
-       }\r
-\r
-       if (revertMask & URI_NORMALIZE_USER_INFO) {\r
-               free((URI_CHAR *)uri->userInfo.first);\r
-               uri->userInfo.first = NULL;\r
-               uri->userInfo.afterLast = NULL;\r
-       }\r
-\r
-       if (revertMask & URI_NORMALIZE_HOST) {\r
-               if (uri->hostData.ipFuture.first != NULL) {\r
-                       /* IPvFuture */\r
-                       free((URI_CHAR *)uri->hostData.ipFuture.first);\r
-                       uri->hostData.ipFuture.first = NULL;\r
-                       uri->hostData.ipFuture.afterLast = NULL;\r
-                       uri->hostText.first = NULL;\r
-                       uri->hostText.afterLast = NULL;\r
-               } else if ((uri->hostText.first != NULL)\r
-                               && (uri->hostData.ip4 == NULL)\r
-                               && (uri->hostData.ip6 == NULL)) {\r
-                       /* Regname */\r
-                       free((URI_CHAR *)uri->hostText.first);\r
-                       uri->hostText.first = NULL;\r
-                       uri->hostText.afterLast = NULL;\r
-               }\r
-       }\r
-\r
-       /* NOTE: Port cannot happen! */\r
-\r
-       if (revertMask & URI_NORMALIZE_PATH) {\r
-               URI_TYPE(PathSegment) * walker = uri->pathHead;\r
-               while (walker != NULL) {\r
-                       URI_TYPE(PathSegment) * const next = walker->next;\r
-                       if (walker->text.afterLast > walker->text.first) {\r
-                               free((URI_CHAR *)walker->text.first);\r
-                       }\r
-                       free(walker);\r
-                       walker = next;\r
-               }\r
-               uri->pathHead = NULL;\r
-               uri->pathTail = NULL;\r
-       }\r
-\r
-       if (revertMask & URI_NORMALIZE_QUERY) {\r
-               free((URI_CHAR *)uri->query.first);\r
-               uri->query.first = NULL;\r
-               uri->query.afterLast = NULL;\r
-       }\r
-\r
-       if (revertMask & URI_NORMALIZE_FRAGMENT) {\r
-               free((URI_CHAR *)uri->fragment.first);\r
-               uri->fragment.first = NULL;\r
-               uri->fragment.afterLast = NULL;\r
-       }\r
-}\r
-\r
-\r
-\r
-static URI_INLINE UriBool URI_FUNC(ContainsUppercaseLetters)(const URI_CHAR * first,\r
-               const URI_CHAR * afterLast) {\r
-       if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {\r
-               const URI_CHAR * i = first;\r
-               for (; i < afterLast; i++) {\r
-                       /* 6.2.2.1 Case Normalization: uppercase letters in scheme or host */\r
-                       if ((*i >= _UT('A')) && (*i <= _UT('Z'))) {\r
-                               return URI_TRUE;\r
-                       }\r
-               }\r
-       }\r
-       return URI_FALSE;\r
-}\r
-\r
-\r
-\r
-static URI_INLINE UriBool URI_FUNC(ContainsUglyPercentEncoding)(const URI_CHAR * first,\r
-               const URI_CHAR * afterLast) {\r
-       if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {\r
-               const URI_CHAR * i = first;\r
-               for (; i + 2 < afterLast; i++) {\r
-                       if (i[0] == _UT('%')) {\r
-                               /* 6.2.2.1 Case Normalization: *\r
-                                * lowercase percent-encodings */\r
-                               if (((i[1] >= _UT('a')) && (i[1] <= _UT('f')))\r
-                                               || ((i[2] >= _UT('a')) && (i[2] <= _UT('f')))) {\r
-                                       return URI_TRUE;\r
-                               } else {\r
-                                       /* 6.2.2.2 Percent-Encoding Normalization: *\r
-                                        * percent-encoded unreserved characters   */\r
-                                       const unsigned char left = URI_FUNC(HexdigToInt)(i[1]);\r
-                                       const unsigned char right = URI_FUNC(HexdigToInt)(i[2]);\r
-                                       const int code = 16 * left + right;\r
-                                       if (uriIsUnreserved(code)) {\r
-                                               return URI_TRUE;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       return URI_FALSE;\r
-}\r
-\r
-\r
-\r
-static URI_INLINE void URI_FUNC(LowercaseInplace)(const URI_CHAR * first,\r
-               const URI_CHAR * afterLast) {\r
-       if ((first != NULL) && (afterLast != NULL) && (afterLast > first)) {\r
-               URI_CHAR * i = (URI_CHAR *)first;\r
-               const int lowerUpperDiff = (_UT('a') - _UT('A'));\r
-               for (; i < afterLast; i++) {\r
-                       if ((*i >= _UT('A')) && (*i <=_UT('Z'))) {\r
-                               *i = (URI_CHAR)(*i + lowerUpperDiff);\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-\r
-\r
-static URI_INLINE UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first,\r
-               const URI_CHAR ** afterLast) {\r
-       int lenInChars;\r
-       const int lowerUpperDiff = (_UT('a') - _UT('A'));\r
-       URI_CHAR * buffer;\r
-       int i = 0;\r
-\r
-       if ((first == NULL) || (afterLast == NULL) || (*first == NULL)\r
-                       || (*afterLast == NULL)) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       lenInChars = (int)(*afterLast - *first);\r
-       if (lenInChars == 0) {\r
-               return URI_TRUE;\r
-       } else if (lenInChars < 0) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       buffer = malloc(lenInChars * sizeof(URI_CHAR));\r
-       if (buffer == NULL) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       for (; i < lenInChars; i++) {\r
-               if (((*first)[i] >= _UT('A')) && ((*first)[i] <=_UT('Z'))) {\r
-                       buffer[i] = (URI_CHAR)((*first)[i] + lowerUpperDiff);\r
-               } else {\r
-                       buffer[i] = (*first)[i];\r
-               }\r
-       }\r
-\r
-       *first = buffer;\r
-       *afterLast = buffer + lenInChars;\r
-       return URI_TRUE;\r
-}\r
-\r
-\r
-\r
-/* NOTE: Implementation must stay inplace-compatible */\r
-static URI_INLINE void URI_FUNC(FixPercentEncodingEngine)(\r
-               const URI_CHAR * inFirst, const URI_CHAR * inAfterLast,\r
-               const URI_CHAR * outFirst, const URI_CHAR ** outAfterLast) {\r
-       URI_CHAR * write = (URI_CHAR *)outFirst;\r
-       const int lenInChars = (int)(inAfterLast - inFirst);\r
-       int i = 0;\r
-\r
-       /* All but last two */\r
-       for (; i + 2 < lenInChars; i++) {\r
-               if (inFirst[i] != _UT('%')) {\r
-                       write[0] = inFirst[i];\r
-                       write++;\r
-               } else {\r
-                       /* 6.2.2.2 Percent-Encoding Normalization: *\r
-                        * percent-encoded unreserved characters   */\r
-                       const URI_CHAR one = inFirst[i + 1];\r
-                       const URI_CHAR two = inFirst[i + 2];\r
-                       const unsigned char left = URI_FUNC(HexdigToInt)(one);\r
-                       const unsigned char right = URI_FUNC(HexdigToInt)(two);\r
-                       const int code = 16 * left + right;\r
-                       if (uriIsUnreserved(code)) {\r
-                               write[0] = (URI_CHAR)(code);\r
-                               write++;\r
-                       } else {\r
-                               /* 6.2.2.1 Case Normalization: *\r
-                                * lowercase percent-encodings */\r
-                               write[0] = _UT('%');\r
-                               write[1] = URI_FUNC(HexToLetter)(left);\r
-                               write[2] = URI_FUNC(HexToLetter)(right);\r
-                               write += 3;\r
-                       }\r
-\r
-                       i += 2; /* For the two chars of the percent group we just ate */\r
-               }\r
-       }\r
-\r
-       /* Last two */\r
-       for (; i < lenInChars; i++) {\r
-               write[0] = inFirst[i];\r
-               write++;\r
-       }\r
-\r
-       *outAfterLast = write;\r
-}\r
-\r
-\r
-\r
-static URI_INLINE void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * first,\r
-               const URI_CHAR ** afterLast) {\r
-       /* Death checks */\r
-       if ((first == NULL) || (afterLast == NULL) || (*afterLast == NULL)) {\r
-               return;\r
-       }\r
-\r
-       /* Fix inplace */\r
-       URI_FUNC(FixPercentEncodingEngine)(first, *afterLast, first, afterLast);\r
-}\r
-\r
-\r
-\r
-static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first,\r
-               const URI_CHAR ** afterLast) {\r
-       int lenInChars;\r
-       URI_CHAR * buffer;\r
-\r
-       /* Death checks */\r
-       if ((first == NULL) || (afterLast == NULL) || (*first == NULL)\r
-               || (*afterLast == NULL)) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       /* Old text length */\r
-       lenInChars = (int)(*afterLast - *first);\r
-       if (lenInChars == 0) {\r
-               return URI_TRUE;\r
-       } else if (lenInChars < 0) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       /* New buffer */\r
-       buffer = malloc(lenInChars * sizeof(URI_CHAR));\r
-       if (buffer == NULL) {\r
-               return URI_FALSE;\r
-       }\r
-\r
-       /* Fix on copy */\r
-       URI_FUNC(FixPercentEncodingEngine)(*first, *afterLast, buffer, afterLast);\r
-       *first = buffer;\r
-       return URI_TRUE;\r
-}\r
-\r
-\r
-\r
-static URI_INLINE UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask,\r
-               unsigned int maskTest, URI_TYPE(TextRange) * range) {\r
-       if (((*doneMask & maskTest) == 0)\r
-                       && (range->first != NULL)\r
-                       && (range->afterLast != NULL)\r
-                       && (range->afterLast > range->first)) {\r
-               const int lenInChars = (int)(range->afterLast - range->first);\r
-               const int lenInBytes = lenInChars * sizeof(URI_CHAR);\r
-               URI_CHAR * dup = malloc(lenInBytes);\r
-               if (dup == NULL) {\r
-                       return URI_FALSE; /* Raises malloc error */\r
-               }\r
-               memcpy(dup, range->afterLast, lenInBytes);\r
-               range->first = dup;\r
-               range->afterLast = dup + lenInChars;\r
-               *doneMask |= maskTest;\r
-       }\r
-       return URI_TRUE;\r
-}\r
-\r
-\r
-\r
-static URI_INLINE UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri,\r
-               unsigned int * doneMask) {\r
-       URI_TYPE(PathSegment) * walker = uri->pathHead;\r
-       if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_SCHEME,\r
-                               &(uri->scheme))\r
-                       || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_USER_INFO,\r
-                               &(uri->userInfo))\r
-                       || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_QUERY,\r
-                               &(uri->query))\r
-                       || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_FRAGMENT,\r
-                               &(uri->fragment))) {\r
-               return URI_FALSE; /* Raises malloc error */\r
-       }\r
-\r
-       /* Host */\r
-       if ((*doneMask & URI_NORMALIZE_HOST) == 0) {\r
-               if ((uri->hostData.ip4 == NULL)\r
-                               && (uri->hostData.ip6 == NULL)) {\r
-                       if (uri->hostData.ipFuture.first != NULL) {\r
-                               /* IPvFuture */\r
-                               if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST,\r
-                                               &(uri->hostData.ipFuture))) {\r
-                                       return URI_FALSE; /* Raises malloc error */\r
-                               }\r
-                               uri->hostText.first = uri->hostData.ipFuture.first;\r
-                               uri->hostText.afterLast = uri->hostData.ipFuture.afterLast;\r
-                       } else if (uri->hostText.first != NULL) {\r
-                               /* Regname */\r
-                               if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST,\r
-                                               &(uri->hostText))) {\r
-                                       return URI_FALSE; /* Raises malloc error */\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* Path */\r
-       if ((*doneMask & URI_NORMALIZE_PATH) == 0) {\r
-               while (walker != NULL) {\r
-                       if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(walker->text))) {\r
-                               /* Kill path to one before walker */\r
-                               URI_TYPE(PathSegment) * ranger = uri->pathHead;\r
-                               while (ranger->next != walker) {\r
-                                       URI_TYPE(PathSegment) * const next = ranger->next;\r
-                                       if ((ranger->text.first != NULL)\r
-                                                       && (ranger->text.afterLast != NULL)\r
-                                                       && (ranger->text.afterLast > ranger->text.first)) {\r
-                                               free((URI_CHAR *)ranger->text.first);\r
-                                               free(ranger);\r
-                                       }\r
-                                       ranger = next;\r
-                               }\r
-\r
-                               /* Kill path from walker */\r
-                               while (walker != NULL) {\r
-                                       URI_TYPE(PathSegment) * const next = walker->next;\r
-                                       free(walker);\r
-                                       walker = next;\r
-                               }\r
-\r
-                               uri->pathHead = NULL;\r
-                               uri->pathTail = NULL;\r
-                               return URI_FALSE; /* Raises malloc error */\r
-                       }\r
-                       walker = walker->next;\r
-               }\r
-               *doneMask |= URI_NORMALIZE_PATH;\r
-       }\r
-\r
-       /* Port text, must come last so we don't have to undo that one if it fails. *\r
-        * Otherwise we would need and extra enum flag for it althoug the port      *\r
-        * cannot go unnormalized...                                                */\r
-       if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(uri->userInfo))) {\r
-               return URI_FALSE; /* Raises malloc error */\r
-       }\r
-\r
-       return URI_TRUE;\r
-}\r
-\r
-\r
-\r
-unsigned int URI_FUNC(NormalizeSyntaxMaskRequired)(const URI_TYPE(Uri) * uri) {\r
-       unsigned int res;\r
-       URI_FUNC(NormalizeSyntaxEngine)((URI_TYPE(Uri) *)uri, 0, &res);\r
-       return res;\r
-}\r
-\r
-\r
-\r
-int URI_FUNC(NormalizeSyntaxEx)(URI_TYPE(Uri) * uri, unsigned int mask) {\r
-       return URI_FUNC(NormalizeSyntaxEngine)(uri, mask, NULL);\r
-}\r
-\r
-\r
-\r
-int URI_FUNC(NormalizeSyntax)(URI_TYPE(Uri) * uri) {\r
-       return URI_FUNC(NormalizeSyntaxEx)(uri, (unsigned int)-1);\r
-}\r
-\r
-\r
-\r
-static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask, unsigned int * outMask) {\r
-       unsigned int doneMask = URI_NORMALIZED;\r
-       if (uri == NULL) {\r
-               if (outMask != NULL) {\r
-                       *outMask = URI_NORMALIZED;\r
-                       return URI_SUCCESS;\r
-               } else {\r
-                       return URI_ERROR_NULL;\r
-               }\r
-       }\r
-\r
-       if (outMask != NULL) {\r
-               /* Reset mask */\r
-               *outMask = URI_NORMALIZED;\r
-       } else if (inMask == URI_NORMALIZED) {\r
-               /* Nothing to do */\r
-               return URI_SUCCESS;\r
-       } else if ((uri->scheme.first == NULL) && !uri->absolutePath) {\r
-               /* Normalization only fone for absolute paths */\r
-               return URI_SUCCESS;\r
-       }\r
-\r
-       /* Scheme, host */\r
-       if (outMask != NULL) {\r
-               const UriBool normalizeScheme = URI_FUNC(ContainsUppercaseLetters)(\r
-                               uri->scheme.first, uri->scheme.afterLast);\r
-               const UriBool normalizeHost = URI_FUNC(ContainsUppercaseLetters)(\r
-                       uri->hostText.first, uri->hostText.afterLast);\r
-               if (normalizeScheme) {\r
-                       *outMask |= URI_NORMALIZE_SCHEME;\r
-               }\r
-\r
-               if (normalizeHost) {\r
-                       *outMask |= URI_NORMALIZE_HOST;\r
-               }\r
-       } else {\r
-               /* Scheme */\r
-               if ((inMask & URI_NORMALIZE_SCHEME) && (uri->scheme.first != NULL)) {\r
-                       if (uri->owner) {\r
-                               URI_FUNC(LowercaseInplace)(uri->scheme.first, uri->scheme.afterLast);\r
-                       } else {\r
-                               if (!URI_FUNC(LowercaseMalloc)(&(uri->scheme.first), &(uri->scheme.afterLast))) {\r
-                                       URI_FUNC(PreventLeakage)(uri, doneMask);\r
-                                       return URI_ERROR_MALLOC;\r
-                               }\r
-                               doneMask |= URI_NORMALIZE_SCHEME;\r
-                       }\r
-               }\r
-\r
-               /* Host */\r
-               if (inMask & URI_NORMALIZE_HOST) {\r
-                       if (uri->hostData.ipFuture.first != NULL) {\r
-                               /* IPvFuture */\r
-                               if (uri->owner) {\r
-                                       URI_FUNC(LowercaseInplace)(uri->hostData.ipFuture.first,\r
-                                                       uri->hostData.ipFuture.afterLast);\r
-                               } else {\r
-                                       if (!URI_FUNC(LowercaseMalloc)(&(uri->hostData.ipFuture.first),\r
-                                                       &(uri->hostData.ipFuture.afterLast))) {\r
-                                               URI_FUNC(PreventLeakage)(uri, doneMask);\r
-                                               return URI_ERROR_MALLOC;\r
-                                       }\r
-                                       doneMask |= URI_NORMALIZE_HOST;\r
-                               }\r
-                               uri->hostText.first = uri->hostData.ipFuture.first;\r
-                               uri->hostText.afterLast = uri->hostData.ipFuture.afterLast;\r
-                       } else if ((uri->hostText.first != NULL)\r
-                                       && (uri->hostData.ip4 == NULL)\r
-                                       && (uri->hostData.ip6 == NULL)) {\r
-                               /* Regname */\r
-                               if (uri->owner) {\r
-                                       URI_FUNC(LowercaseInplace)(uri->hostText.first,\r
-                                                       uri->hostText.afterLast);\r
-                               } else {\r
-                                       if (!URI_FUNC(LowercaseMalloc)(&(uri->hostText.first),\r
-                                                       &(uri->hostText.afterLast))) {\r
-                                               URI_FUNC(PreventLeakage)(uri, doneMask);\r
-                                               return URI_ERROR_MALLOC;\r
-                                       }\r
-                                       doneMask |= URI_NORMALIZE_HOST;\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* User info */\r
-       if (outMask != NULL) {\r
-               const UriBool normalizeUserInfo = URI_FUNC(ContainsUglyPercentEncoding)(\r
-                       uri->userInfo.first, uri->userInfo.afterLast);\r
-               if (normalizeUserInfo) {\r
-                       *outMask |= URI_NORMALIZE_USER_INFO;\r
-               }\r
-       } else {\r
-               if ((inMask & URI_NORMALIZE_USER_INFO) && (uri->userInfo.first != NULL)) {\r
-                       if (uri->owner) {\r
-                               URI_FUNC(FixPercentEncodingInplace)(uri->userInfo.first, &(uri->userInfo.afterLast));\r
-                       } else {\r
-                               if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->userInfo.first),\r
-                                               &(uri->userInfo.afterLast))) {\r
-                                       URI_FUNC(PreventLeakage)(uri, doneMask);\r
-                                       return URI_ERROR_MALLOC;\r
-                               }\r
-                               doneMask |= URI_NORMALIZE_USER_INFO;\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* Path */\r
-       if (outMask != NULL) {\r
-               const URI_TYPE(PathSegment) * walker = uri->pathHead;\r
-               while (walker != NULL) {\r
-                       const URI_CHAR * const first = walker->text.first;\r
-                       const URI_CHAR * const afterLast = walker->text.afterLast;\r
-                       if ((first != NULL)\r
-                                       && (afterLast != NULL)\r
-                                       && (afterLast > first)\r
-                                       && (\r
-                                               (((afterLast - first) == 1)\r
-                                                       && (first[0] == _UT('.')))\r
-                                               ||\r
-                                               (((afterLast - first) == 2)\r
-                                                       && (first[0] == _UT('.'))\r
-                                                       && (first[1] == _UT('.')))\r
-                                               ||\r
-                                               URI_FUNC(ContainsUglyPercentEncoding)(first, afterLast)\r
-                                       )) {\r
-                               *outMask |= URI_NORMALIZE_PATH;\r
-                               break;\r
-                       }\r
-                       walker = walker->next;\r
-               }\r
-       } else {\r
-               const URI_TYPE(PathSegment) * walker;\r
-\r
-               /* 6.2.2.3 Path Segment Normalization */\r
-               if (!URI_FUNC(RemoveDotSegments)(uri)) {\r
-                       URI_FUNC(PreventLeakage)(uri, doneMask);\r
-                       return URI_ERROR_MALLOC;\r
-               }\r
-\r
-               /* Fix percent-encoding for each segment */\r
-               walker = uri->pathHead;\r
-               if (uri->owner) {\r
-                       while (walker != NULL) {\r
-                               URI_FUNC(FixPercentEncodingInplace)(walker->text.first, &(walker->text.afterLast));\r
-                               walker = walker->next;\r
-                       }\r
-               } else {\r
-                       while (walker != NULL) {\r
-                               if (!URI_FUNC(FixPercentEncodingMalloc)(&(walker->text.first),\r
-                                               &(walker->text.afterLast))) {\r
-                                       URI_FUNC(PreventLeakage)(uri, doneMask);\r
-                                       return URI_ERROR_MALLOC;\r
-                               }\r
-                               walker = walker->next;\r
-                       }\r
-                       doneMask |= URI_NORMALIZE_PATH;\r
-               }\r
-       }\r
-\r
-       /* Query, fragment */\r
-       if (outMask != NULL) {\r
-               const UriBool normalizeQuery = URI_FUNC(ContainsUglyPercentEncoding)(\r
-                               uri->query.first, uri->query.afterLast);\r
-               const UriBool normalizeFragment = URI_FUNC(ContainsUglyPercentEncoding)(\r
-                               uri->fragment.first, uri->fragment.afterLast);\r
-               if (normalizeQuery) {\r
-                       *outMask |= URI_NORMALIZE_QUERY;\r
-               }\r
-\r
-               if (normalizeFragment) {\r
-                       *outMask |= URI_NORMALIZE_FRAGMENT;\r
-               }\r
-       } else {\r
-               /* Query */\r
-               if ((inMask & URI_NORMALIZE_QUERY) && (uri->query.first != NULL)) {\r
-                       if (uri->owner) {\r
-                               URI_FUNC(FixPercentEncodingInplace)(uri->query.first, &(uri->query.afterLast));\r
-                       } else {\r
-                               if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->query.first),\r
-                                               &(uri->query.afterLast))) {\r
-                                       URI_FUNC(PreventLeakage)(uri, doneMask);\r
-                                       return URI_ERROR_MALLOC;\r
-                               }\r
-                               doneMask |= URI_NORMALIZE_QUERY;\r
-                       }\r
-               }\r
-\r
-               /* Fragment */\r
-               if ((inMask & URI_NORMALIZE_FRAGMENT) && (uri->fragment.first != NULL)) {\r
-                       if (uri->owner) {\r
-                               URI_FUNC(FixPercentEncodingInplace)(uri->fragment.first, &(uri->fragment.afterLast));\r
-                       } else {\r
-                               if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->fragment.first),\r
-                                               &(uri->fragment.afterLast))) {\r
-                                       URI_FUNC(PreventLeakage)(uri, doneMask);\r
-                                       return URI_ERROR_MALLOC;\r
-                               }\r
-                               doneMask |= URI_NORMALIZE_FRAGMENT;\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* Dup all not duped yet */\r
-       if ((outMask == NULL) && !uri->owner) {\r
-               if (!URI_FUNC(MakeOwner)(uri, &doneMask)) {\r
-                       URI_FUNC(PreventLeakage)(uri, doneMask);\r
-                       return URI_ERROR_MALLOC;\r
-               }\r
-               uri->owner = URI_TRUE;\r
-       }\r
-\r
-       return URI_SUCCESS;\r
-}\r
-\r
-\r
-\r
-#endif\r
+/*
+ * uriparser - RFC 3986 URI parsing library
+ *
+ * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
+ * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.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:
+ *
+ *     * Redistributions   of  source  code  must  retain  the   above
+ *       copyright  notice, this list of conditions and the  following
+ *       disclaimer.
+ *
+ *     * 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.
+ *
+ *     * Neither  the name of the <ORGANIZATION> 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 OWNER 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 */
+# define URI_PASS_ANSI 1
+# include "UriNormalize.c"
+# undef URI_PASS_ANSI
+# define URI_PASS_UNICODE 1
+# include "UriNormalize.c"
+# undef URI_PASS_UNICODE
+#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"
+#endif
+
+
+
+static int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask,
+               unsigned int * outMask);
+
+static UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask,
+               unsigned int maskTest, URI_TYPE(TextRange) * range);
+static UriBool URI_FUNC(MakeOwner)(URI_TYPE(Uri) * uri,
+               unsigned int * doneMask);
+
+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);
+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 UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first,
+               const URI_CHAR ** afterLast);
+
+static void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,
+               unsigned int revertMask);
+
+
+
+static URI_INLINE void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri,
+               unsigned int revertMask) {
+       if (revertMask & URI_NORMALIZE_SCHEME) {
+               free((URI_CHAR *)uri->scheme.first);
+               uri->scheme.first = NULL;
+               uri->scheme.afterLast = NULL;
+       }
+
+       if (revertMask & URI_NORMALIZE_USER_INFO) {
+               free((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 */
+                       free((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)
+                               && (uri->hostData.ip4 == NULL)
+                               && (uri->hostData.ip6 == NULL)) {
+                       /* Regname */
+                       free((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) {
+                               free((URI_CHAR *)walker->text.first);
+                       }
+                       free(walker);
+                       walker = next;
+               }
+               uri->pathHead = NULL;
+               uri->pathTail = NULL;
+       }
+
+       if (revertMask & URI_NORMALIZE_QUERY) {
+               free((URI_CHAR *)uri->query.first);
+               uri->query.first = NULL;
+               uri->query.afterLast = NULL;
+       }
+
+       if (revertMask & URI_NORMALIZE_FRAGMENT) {
+               free((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 UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first,
+               const URI_CHAR ** afterLast) {
+       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 = malloc(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) {
+       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 = malloc(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) {
+       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 = malloc(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(MakeOwner)(URI_TYPE(Uri) * uri,
+               unsigned int * doneMask) {
+       URI_TYPE(PathSegment) * walker = uri->pathHead;
+       if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_SCHEME,
+                               &(uri->scheme))
+                       || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_USER_INFO,
+                               &(uri->userInfo))
+                       || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_QUERY,
+                               &(uri->query))
+                       || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_FRAGMENT,
+                               &(uri->fragment))) {
+               return URI_FALSE; /* Raises malloc error */
+       }
+
+       /* Host */
+       if ((*doneMask & URI_NORMALIZE_HOST) == 0) {
+               if ((uri->hostData.ip4 == NULL)
+                               && (uri->hostData.ip6 == NULL)) {
+                       if (uri->hostData.ipFuture.first != NULL) {
+                               /* IPvFuture */
+                               if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST,
+                                               &(uri->hostData.ipFuture))) {
+                                       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))) {
+                                       return URI_FALSE; /* Raises malloc error */
+                               }
+                       }
+               }
+       }
+
+       /* Path */
+       if ((*doneMask & URI_NORMALIZE_PATH) == 0) {
+               while (walker != NULL) {
+                       if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(walker->text))) {
+                               /* Kill path to one before walker */
+                               URI_TYPE(PathSegment) * ranger = uri->pathHead;
+                               while (ranger->next != walker) {
+                                       URI_TYPE(PathSegment) * const next = ranger->next;
+                                       if ((ranger->text.first != NULL)
+                                                       && (ranger->text.afterLast != NULL)
+                                                       && (ranger->text.afterLast > ranger->text.first)) {
+                                               free((URI_CHAR *)ranger->text.first);
+                                               free(ranger);
+                                       }
+                                       ranger = next;
+                               }
+
+                               /* Kill path from walker */
+                               while (walker != NULL) {
+                                       URI_TYPE(PathSegment) * const next = walker->next;
+                                       free(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))) {
+               return URI_FALSE; /* Raises malloc error */
+       }
+
+       return URI_TRUE;
+}
+
+
+
+unsigned int URI_FUNC(NormalizeSyntaxMaskRequired)(const URI_TYPE(Uri) * uri) {
+       unsigned int res;
+#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;
+       memcpy(&writeableClone, uri, 1 * sizeof(URI_TYPE(Uri)));
+       URI_FUNC(NormalizeSyntaxEngine)(&writeableClone, 0, &res);
+#else
+       URI_FUNC(NormalizeSyntaxEngine)((URI_TYPE(Uri) *)uri, 0, &res);
+#endif
+       return res;
+}
+
+
+
+int URI_FUNC(NormalizeSyntaxEx)(URI_TYPE(Uri) * uri, unsigned int mask) {
+       return URI_FUNC(NormalizeSyntaxEngine)(uri, mask, NULL);
+}
+
+
+
+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) {
+       unsigned int doneMask = URI_NORMALIZED;
+       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))) {
+                                       URI_FUNC(PreventLeakage)(uri, doneMask);
+                                       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))) {
+                                               URI_FUNC(PreventLeakage)(uri, doneMask);
+                                               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)
+                                       && (uri->hostData.ip6 == NULL)) {
+                               /* Regname */
+                               if (uri->owner) {
+                                       URI_FUNC(FixPercentEncodingInplace)(uri->hostText.first,
+                                                       &(uri->hostText.afterLast));
+                               } else {
+                                       if (!URI_FUNC(FixPercentEncodingMalloc)(
+                                                       &(uri->hostText.first),
+                                                       &(uri->hostText.afterLast))) {
+                                               URI_FUNC(PreventLeakage)(uri, doneMask);
+                                               return URI_ERROR_MALLOC;
+                                       }
+                                       doneMask |= URI_NORMALIZE_HOST;
+                               }
+
+                               URI_FUNC(LowercaseInplace)(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))) {
+                                       URI_FUNC(PreventLeakage)(uri, doneMask);
+                                       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))) {
+                                       URI_FUNC(PreventLeakage)(uri, doneMask);
+                                       return URI_ERROR_MALLOC;
+                               }
+                               walker = walker->next;
+                       }
+                       doneMask |= URI_NORMALIZE_PATH;
+               }
+
+               /* 6.2.2.3 Path Segment Normalization */
+               if (!URI_FUNC(RemoveDotSegments)(uri, relative)) {
+                       URI_FUNC(PreventLeakage)(uri, doneMask);
+                       return URI_ERROR_MALLOC;
+               }
+       }
+
+       /* 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))) {
+                                       URI_FUNC(PreventLeakage)(uri, doneMask);
+                                       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))) {
+                                       URI_FUNC(PreventLeakage)(uri, doneMask);
+                                       return URI_ERROR_MALLOC;
+                               }
+                               doneMask |= URI_NORMALIZE_FRAGMENT;
+                       }
+               }
+       }
+
+       /* Dup all not duped yet */
+       if ((outMask == NULL) && !uri->owner) {
+               if (!URI_FUNC(MakeOwner)(uri, &doneMask)) {
+                       URI_FUNC(PreventLeakage)(uri, doneMask);
+                       return URI_ERROR_MALLOC;
+               }
+               uri->owner = URI_TRUE;
+       }
+
+       return URI_SUCCESS;
+}
+
+
+
+#endif
index a871826..bac5888 100644 (file)
-/*\r
- * uriparser - RFC 3986 URI parsing library\r
- *\r
- * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>\r
- * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>\r
- * All rights reserved.\r
- *\r
- * Redistribution  and use in source and binary forms, with or without\r
- * modification,  are permitted provided that the following conditions\r
- * are met:\r
- *\r
- *     * Redistributions   of  source  code  must  retain  the   above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer.\r
- *\r
- *     * Redistributions  in  binary  form must  reproduce  the  above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer   in  the  documentation  and/or  other  materials\r
- *       provided with the distribution.\r
- *\r
- *     * Neither  the name of the <ORGANIZATION> nor the names of  its\r
- *       contributors  may  be  used to endorse  or  promote  products\r
- *       derived  from  this software without specific  prior  written\r
- *       permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT\r
- * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS\r
- * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE\r
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES\r
- * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-#ifndef URI_DOXYGEN\r
-# include "UriNormalizeBase.h"\r
-#endif\r
-\r
-\r
-\r
-UriBool uriIsUnreserved(int code) {\r
-       switch (code) {\r
-       case L'a': /* ALPHA */\r
-       case L'A':\r
-       case L'b':\r
-       case L'B':\r
-       case L'c':\r
-       case L'C':\r
-       case L'd':\r
-       case L'D':\r
-       case L'e':\r
-       case L'E':\r
-       case L'f':\r
-       case L'F':\r
-       case L'g':\r
-       case L'G':\r
-       case L'h':\r
-       case L'H':\r
-       case L'i':\r
-       case L'I':\r
-       case L'j':\r
-       case L'J':\r
-       case L'k':\r
-       case L'K':\r
-       case L'l':\r
-       case L'L':\r
-       case L'm':\r
-       case L'M':\r
-       case L'n':\r
-       case L'N':\r
-       case L'o':\r
-       case L'O':\r
-       case L'p':\r
-       case L'P':\r
-       case L'q':\r
-       case L'Q':\r
-       case L'r':\r
-       case L'R':\r
-       case L's':\r
-       case L'S':\r
-       case L't':\r
-       case L'T':\r
-       case L'u':\r
-       case L'U':\r
-       case L'v':\r
-       case L'V':\r
-       case L'w':\r
-       case L'W':\r
-       case L'x':\r
-       case L'X':\r
-       case L'y':\r
-       case L'Y':\r
-       case L'z':\r
-       case L'Z':\r
-       case L'0': /* DIGIT */\r
-       case L'1':\r
-       case L'2':\r
-       case L'3':\r
-       case L'4':\r
-       case L'5':\r
-       case L'6':\r
-       case L'7':\r
-       case L'8':\r
-       case L'9':\r
-       case L'-': /* "-" / "." / "_" / "~" */\r
-       case L'.':\r
-       case L'_':\r
-       case L'~':\r
-               return URI_TRUE;\r
-\r
-       default:\r
-               return URI_FALSE;\r
-       }\r
-}\r
+/*
+ * uriparser - RFC 3986 URI parsing library
+ *
+ * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
+ * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.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:
+ *
+ *     * Redistributions   of  source  code  must  retain  the   above
+ *       copyright  notice, this list of conditions and the  following
+ *       disclaimer.
+ *
+ *     * 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.
+ *
+ *     * Neither  the name of the <ORGANIZATION> 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 OWNER 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;
+       }
+}
index b39bc31..9f3abd5 100644 (file)
@@ -1,53 +1,53 @@
-/*\r
- * uriparser - RFC 3986 URI parsing library\r
- *\r
- * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>\r
- * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>\r
- * All rights reserved.\r
- *\r
- * Redistribution  and use in source and binary forms, with or without\r
- * modification,  are permitted provided that the following conditions\r
- * are met:\r
- *\r
- *     * Redistributions   of  source  code  must  retain  the   above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer.\r
- *\r
- *     * Redistributions  in  binary  form must  reproduce  the  above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer   in  the  documentation  and/or  other  materials\r
- *       provided with the distribution.\r
- *\r
- *     * Neither  the name of the <ORGANIZATION> nor the names of  its\r
- *       contributors  may  be  used to endorse  or  promote  products\r
- *       derived  from  this software without specific  prior  written\r
- *       permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT\r
- * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS\r
- * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE\r
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES\r
- * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-#ifndef URI_NORMALIZE_BASE_H\r
-#define URI_NORMALIZE_BASE_H 1\r
-\r
-\r
-\r
-#include <uriparser/UriBase.h>\r
-\r
-\r
-\r
-UriBool uriIsUnreserved(int code);\r
-\r
-\r
-\r
-#endif /* URI_NORMALIZE_BASE_H */\r
+/*
+ * uriparser - RFC 3986 URI parsing library
+ *
+ * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
+ * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.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:
+ *
+ *     * Redistributions   of  source  code  must  retain  the   above
+ *       copyright  notice, this list of conditions and the  following
+ *       disclaimer.
+ *
+ *     * 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.
+ *
+ *     * Neither  the name of the <ORGANIZATION> 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 OWNER 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 */
index 6ec9190..28aa8ec 100644 (file)
-/*\r
- * uriparser - RFC 3986 URI parsing library\r
- *\r
- * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>\r
- * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>\r
- * All rights reserved.\r
- *\r
- * Redistribution  and use in source and binary forms, with or without\r
- * modification,  are permitted provided that the following conditions\r
- * are met:\r
- *\r
- *     * Redistributions   of  source  code  must  retain  the   above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer.\r
- *\r
- *     * Redistributions  in  binary  form must  reproduce  the  above\r
- *       copyright  notice, this list of conditions and the  following\r
- *       disclaimer   in  the  documentation  and/or  other  materials\r
- *       provided with the distribution.\r
- *\r
- *     * Neither  the name of the <ORGANIZATION> nor the names of  its\r
- *       contributors  may  be  used to endorse  or  promote  products\r
- *       derived  from  this software without specific  prior  written\r
- *       permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT\r
- * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS\r
- * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE\r
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES\r
- * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-/**\r
- * @file UriParse.c\r
- * Holds the RFC 3986 %URI parsing implementation.\r
- * NOTE: This source file includes itself twice.\r
- */\r
-\r
-/* What encodings are enabled? */\r
-#include <uriparser/UriDefsConfig.h>\r
-#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))\r
-/* Include SELF twice */\r
-# define URI_PASS_ANSI 1\r
-# include "UriParse.c"\r
-# undef URI_PASS_ANSI\r
-# define URI_PASS_UNICODE 1\r
-# include "UriParse.c"\r
-# undef URI_PASS_UNICODE\r
-#else\r
-# ifdef URI_PASS_ANSI\r
-#  include <uriparser/UriDefsAnsi.h>\r
-# else\r
-#  include <uriparser/UriDefsUnicode.h>\r
-#  include <wchar.h>\r
-# endif\r
-\r
-\r
-\r
-#ifndef URI_DOXYGEN\r
-# include <uriparser/Uri.h>\r
-# include <uriparser/UriIp4.h>\r
-# include "UriCommon.h"\r
-# include "UriParseBase.h"\r
-#endif\r
-\r
-\r
-\r
-#define URI_SET_DIGIT \\r
-            _UT('0'): \\r
-       case _UT('1'): \\r
-       case _UT('2'): \\r
-       case _UT('3'): \\r
-       case _UT('4'): \\r
-       case _UT('5'): \\r
-       case _UT('6'): \\r
-       case _UT('7'): \\r
-       case _UT('8'): \\r
-       case _UT('9')\r
-\r
-#define URI_SET_HEX_LETTER_UPPER \\r
-            _UT('A'): \\r
-       case _UT('B'): \\r
-       case _UT('C'): \\r
-       case _UT('D'): \\r
-       case _UT('E'): \\r
-       case _UT('F')\r
-\r
-#define URI_SET_HEX_LETTER_LOWER \\r
-            _UT('a'): \\r
-       case _UT('b'): \\r
-       case _UT('c'): \\r
-       case _UT('d'): \\r
-       case _UT('e'): \\r
-       case _UT('f')\r
-\r
-#define URI_SET_HEXDIG \\r
-       URI_SET_DIGIT: \\r
-       case URI_SET_HEX_LETTER_UPPER: \\r
-       case URI_SET_HEX_LETTER_LOWER\r
-\r
-#define URI_SET_ALPHA \\r
-       URI_SET_HEX_LETTER_UPPER: \\r
-       case URI_SET_HEX_LETTER_LOWER: \\r
-       case _UT('g'): \\r
-       case _UT('G'): \\r
-       case _UT('h'): \\r
-       case _UT('H'): \\r
-       case _UT('i'): \\r
-       case _UT('I'): \\r
-       case _UT('j'): \\r
-       case _UT('J'): \\r
-       case _UT('k'): \\r
-       case _UT('K'): \\r
-       case _UT('l'): \\r
-       case _UT('L'): \\r
-       case _UT('m'): \\r
-       case _UT('M'): \\r
-       case _UT('n'): \\r
-       case _UT('N'): \\r
-       case _UT('o'): \\r
-       case _UT('O'): \\r
-       case _UT('p'): \\r
-       case _UT('P'): \\r
-       case _UT('q'): \\r
-       case _UT('Q'): \\r
-       case _UT('r'): \\r
-       case _UT('R'): \\r
-       case _UT('s'): \\r
-       case _UT('S'): \\r
-       case _UT('t'): \\r
-       case _UT('T'): \\r
-       case _UT('u'): \\r
-       case _UT('U'): \\r
-       case _UT('v'): \\r
-       case _UT('V'): \\r
-       case _UT('w'): \\r
-       case _UT('W'): \\r
-       case _UT('x'): \\r
-       case _UT('X'): \\r
-       case _UT('y'): \\r
-       case _UT('Y'): \\r
-       case _UT('z'): \\r
-       case _UT('Z')\r
-\r
-\r
-\r
-static const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParsePathRootless)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseSegmentNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-\r
-static UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first);\r
-static UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first);\r
-static UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first);\r
-static UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first);\r
-static void URI_FUNC(OnExitPartHelperTwo)(URI_TYPE(ParserState) * state);\r
-\r
-static void URI_FUNC(ResetParserState)(URI_TYPE(ParserState) * state);\r
-\r
-static UriBool URI_FUNC(PushPathSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);\r
-\r
-static void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state, const URI_CHAR * errorPos);\r
-static void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state);\r
-\r
-\r
-\r
-static URI_INLINE void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state,\r
-               const URI_CHAR * errorPos) {\r
-       URI_FUNC(FreeUriMembers)(state->uri);\r
-       state->errorPos = errorPos;\r
-       state->errorCode = URI_ERROR_SYNTAX;\r
-}\r
-\r
-\r
-\r
-static URI_INLINE void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state) {\r
-       URI_FUNC(FreeUriMembers)(state->uri);\r
-       state->errorPos = NULL;\r
-       state->errorCode = URI_ERROR_MALLOC;\r
-}\r
-\r
-\r
-\r
-/*\r
- * [authority]-><[>[ipLit2][authorityTwo]\r
- * [authority]->[ownHostUserInfoNz]\r
- * [authority]-><NULL>\r
- */\r
-static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               /* "" regname host */\r
-               state->uri->hostText.first = URI_FUNC(SafeToPointTo);\r
-               state->uri->hostText.afterLast = URI_FUNC(SafeToPointTo);\r
-               return afterLast;\r
-       }\r
-\r
-       switch (*first) {\r
-       case _UT('['):\r
-               {\r
-                       const URI_CHAR * const afterIpLit2\r
-                                       = URI_FUNC(ParseIpLit2)(state, first + 1, afterLast);\r
-                       if (afterIpLit2 == NULL) {\r
-                               return NULL;\r
-                       }\r
-                       state->uri->hostText.first = first + 1; /* HOST BEGIN */\r
-                       return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast);\r
-               }\r
-\r
-       case _UT('!'):\r
-       case _UT('$'):\r
-       case _UT('%'):\r
-       case _UT('&'):\r
-       case _UT('('):\r
-       case _UT(')'):\r
-       case _UT('-'):\r
-       case _UT('*'):\r
-       case _UT(','):\r
-       case _UT('.'):\r
-       case _UT(':'):\r
-       case _UT(';'):\r
-       case _UT('@'):\r
-       case _UT('\''):\r
-       case _UT('_'):\r
-       case _UT('~'):\r
-       case _UT('+'):\r
-       case _UT('='):\r
-       case URI_SET_DIGIT:\r
-       case URI_SET_ALPHA:\r
-               state->uri->userInfo.first = first; /* USERINFO BEGIN */\r
-               return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast);\r
-\r
-       default:\r
-               /* "" regname host */\r
-               state->uri->hostText.first = URI_FUNC(SafeToPointTo);\r
-               state->uri->hostText.afterLast = URI_FUNC(SafeToPointTo);\r
-               return first;\r
-       }\r
-}\r
-\r
-\r
-\r
-/*\r
- * [authorityTwo]-><:>[port]\r
- * [authorityTwo]-><NULL>\r
- */\r
-static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               return afterLast;\r
-       }\r
-\r
-       switch (*first) {\r
-       case _UT(':'):\r
-               {\r
-                       const URI_CHAR * const afterPort = URI_FUNC(ParsePort)(state, first + 1, afterLast);\r
-                       if (afterPort == NULL) {\r
-                               return NULL;\r
-                       }\r
-                       state->uri->portText.first = first + 1; /* PORT BEGIN */\r
-                       state->uri->portText.afterLast = afterPort; /* PORT END */\r
-                       return afterPort;\r
-               }\r
-\r
-       default:\r
-               return first;\r
-       }\r
-}\r
-\r
-\r
-\r
-/*\r
- * [hexZero]->[HEXDIG][hexZero]\r
- * [hexZero]-><NULL>\r
- */\r
-static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               return afterLast;\r
-       }\r
-\r
-       switch (*first) {\r
-       case URI_SET_HEXDIG:\r
-               return URI_FUNC(ParseHexZero)(state, first + 1, afterLast);\r
-\r
-       default:\r
-               return first;\r
-       }\r
-}\r
-\r
-\r
-\r
-/*\r
- * [hierPart]->[pathRootless]\r
- * [hierPart]-></>[partHelperTwo]\r
- * [hierPart]-><NULL>\r
- */\r
-static URI_INLINE const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               return afterLast;\r
-       }\r
-\r
-       switch (*first) {\r
-       case _UT('!'):\r
-       case _UT('$'):\r
-       case _UT('%'):\r
-       case _UT('&'):\r
-       case _UT('('):\r
-       case _UT(')'):\r
-       case _UT('-'):\r
-       case _UT('*'):\r
-       case _UT(','):\r
-       case _UT('.'):\r
-       case _UT(':'):\r
-       case _UT(';'):\r
-       case _UT('@'):\r
-       case _UT('\''):\r
-       case _UT('_'):\r
-       case _UT('~'):\r
-       case _UT('+'):\r
-       case _UT('='):\r
-       case URI_SET_DIGIT:\r
-       case URI_SET_ALPHA:\r
-               return URI_FUNC(ParsePathRootless)(state, first, afterLast);\r
-\r
-       case _UT('/'):\r
-               return URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast);\r
-\r
-       default:\r
-               return first;\r
-       }\r
-}\r
-\r
-\r
-\r
-/*\r
- * [ipFutLoop]->[subDelims][ipFutStopGo]\r
- * [ipFutLoop]->[unreserved][ipFutStopGo]\r
- * [ipFutLoop]-><:>[ipFutStopGo]\r
- */\r
-static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               URI_FUNC(StopSyntax)(state, first);\r
-               return NULL;\r
-       }\r
-\r
-       switch (*first) {\r
-       case _UT('!'):\r
-       case _UT('$'):\r
-       case _UT('&'):\r
-       case _UT('('):\r
-       case _UT(')'):\r
-       case _UT('-'):\r
-       case _UT('*'):\r
-       case _UT(','):\r
-       case _UT('.'):\r
-       case _UT(':'):\r
-       case _UT(';'):\r
-       case _UT('\''):\r
-       case _UT('_'):\r
-       case _UT('~'):\r
-       case _UT('+'):\r
-       case _UT('='):\r
-       case URI_SET_DIGIT:\r
-       case URI_SET_ALPHA:\r
-               return URI_FUNC(ParseIpFutStopGo)(state, first + 1, afterLast);\r
-\r
-       default:\r
-               URI_FUNC(StopSyntax)(state, first);\r
-               return NULL;\r
-       }\r
-}\r
-\r
-\r
-\r
-/*\r
- * [ipFutStopGo]->[ipFutLoop]\r
- * [ipFutStopGo]-><NULL>\r
- */\r
-static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               return afterLast;\r
-       }\r
-\r
-       switch (*first) {\r
-       case _UT('!'):\r
-       case _UT('$'):\r
-       case _UT('&'):\r
-       case _UT('('):\r
-       case _UT(')'):\r
-       case _UT('-'):\r
-       case _UT('*'):\r
-       case _UT(','):\r
-       case _UT('.'):\r
-       case _UT(':'):\r
-       case _UT(';'):\r
-       case _UT('\''):\r
-       case _UT('_'):\r
-       case _UT('~'):\r
-       case _UT('+'):\r
-       case _UT('='):\r
-       case URI_SET_DIGIT:\r
-       case URI_SET_ALPHA:\r
-               return URI_FUNC(ParseIpFutLoop)(state, first, afterLast);\r
-\r
-       default:\r
-               return first;\r
-       }\r
-}\r
-\r
-\r
-\r
-/*\r
- * [ipFuture]-><v>[HEXDIG][hexZero]<.>[ipFutLoop]\r
- */\r
-static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               URI_FUNC(StopSyntax)(state, first);\r
-               return NULL;\r
-       }\r
-\r
-       /*\r
-       First character has already been\r
-       checked before entering this rule.\r
-\r
-       switch (*first) {\r
-       case _UT('v'):\r
-       */\r
-               if (first + 1 >= afterLast) {\r
-                       URI_FUNC(StopSyntax)(state, first + 1);\r
-                       return NULL;\r
-               }\r
-\r
-               switch (first[1]) {\r
-               case URI_SET_HEXDIG:\r
-                       {\r
-                               const URI_CHAR * afterIpFutLoop;\r
-                               const URI_CHAR * const afterHexZero\r
-                                               = URI_FUNC(ParseHexZero)(state, first + 2, afterLast);\r
-                               if (afterHexZero == NULL) {\r
-                                       return NULL;\r
-                               }\r
-                               if ((afterHexZero >= afterLast)\r
-                                               || (*afterHexZero != _UT('.'))) {\r
-                                       URI_FUNC(StopSyntax)(state, afterHexZero);\r
-                                       return NULL;\r
-                               }\r
-                               state->uri->hostText.first = first; /* HOST BEGIN */\r
-                               state->uri->hostData.ipFuture.first = first; /* IPFUTURE BEGIN */\r
-                               afterIpFutLoop = URI_FUNC(ParseIpFutLoop)(state, afterHexZero + 1, afterLast);\r
-                               if (afterIpFutLoop == NULL) {\r
-                                       return NULL;\r
-                               }\r
-                               state->uri->hostText.afterLast = afterIpFutLoop; /* HOST END */\r
-                               state->uri->hostData.ipFuture.afterLast = afterIpFutLoop; /* IPFUTURE END */\r
-                               return afterIpFutLoop;\r
-                       }\r
-\r
-               default:\r
-                       URI_FUNC(StopSyntax)(state, first + 1);\r
-                       return NULL;\r
-               }\r
-\r
-       /*\r
-       default:\r
-               URI_FUNC(StopSyntax)(state, first);\r
-               return NULL;\r
-       }\r
-       */\r
-}\r
-\r
-\r
-\r
-/*\r
- * [ipLit2]->[ipFuture]<]>\r
- * [ipLit2]->[IPv6address2]\r
- */\r
-static URI_INLINE const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               URI_FUNC(StopSyntax)(state, first);\r
-               return NULL;\r
-       }\r
-\r
-       switch (*first) {\r
-       case _UT('v'):\r
-               {\r
-                       const URI_CHAR * const afterIpFuture\r
-                                       = URI_FUNC(ParseIpFuture)(state, first, afterLast);\r
-                       if (afterIpFuture == NULL) {\r
-                               return NULL;\r
-                       }\r
-                       if ((afterIpFuture >= afterLast)\r
-                                       || (*afterIpFuture != _UT(']'))) {\r
-                               URI_FUNC(StopSyntax)(state, first);\r
-                               return NULL;\r
-                       }\r
-                       return afterIpFuture + 1;\r
-               }\r
-\r
-       case _UT(':'):\r
-       case _UT(']'):\r
-       case URI_SET_HEXDIG:\r
-               state->uri->hostData.ip6 = malloc(1 * sizeof(UriIp6)); /* Freed when stopping on parse error */\r
-               if (state->uri->hostData.ip6 == NULL) {\r
-                       URI_FUNC(StopMalloc)(state);\r
-                       return NULL;\r
-               }\r
-               return URI_FUNC(ParseIPv6address2)(state, first, afterLast);\r
-\r
-       default:\r
-               URI_FUNC(StopSyntax)(state, first);\r
-               return NULL;\r
-       }\r
-}\r
-\r
-\r
-\r
-/*\r
- * [IPv6address2]->..<]>\r
- */\r
-static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       int zipperEver = 0;\r
-       int quadsDone = 0;\r
-       int digitCount = 0;\r
-       unsigned char digitHistory[4];\r
-       int ip4OctetsDone = 0;\r
-\r
-       unsigned char quadsAfterZipper[14];\r
-       int quadsAfterZipperCount = 0;\r
-\r
-\r
-       for (;;) {\r
-               if (first >= afterLast) {\r
-                       URI_FUNC(StopSyntax)(state, first);\r
-                       return NULL;\r
-               }\r
-\r
-               /* Inside IPv4 part? */\r
-               if (ip4OctetsDone > 0) {\r
-                       /* Eat rest of IPv4 address */\r
-                       for (;;) {\r
-                               switch (*first) {\r
-                               case URI_SET_DIGIT:\r
-                                       if (digitCount == 4) {\r
-                                               URI_FUNC(StopSyntax)(state, first);\r
-                                               return NULL;\r
-                                       }\r
-                                       digitHistory[digitCount++] = (unsigned char)(9 + *first - _UT('9'));\r
-                                       break;\r
-\r
-                               case _UT('.'):\r
-                                       if ((ip4OctetsDone == 4) /* NOTE! */\r
-                                                       || (digitCount == 0)\r
-                                                       || (digitCount == 4)) {\r
-                                               /* Invalid digit or octet count */\r
-                                               URI_FUNC(StopSyntax)(state, first);\r
-                                               return NULL;\r
-                                       } else if ((digitCount > 1)\r
-                                                       && (digitHistory[0] == 0)) {\r
-                                               /* Leading zero */\r
-                                               URI_FUNC(StopSyntax)(state, first - digitCount);\r
-                                               return NULL;\r
-                                       } else if ((digitCount > 2)\r
-                                                       && (digitHistory[1] == 0)) {\r
-                                               /* Leading zero */\r
-                                               URI_FUNC(StopSyntax)(state, first - digitCount + 1);\r
-                                               return NULL;\r
-                                       } else if ((digitCount == 3)\r
-                                                       && (100 * digitHistory[0]\r
-                                                               + 10 * digitHistory[1]\r
-                                                               + digitHistory[2] > 255)) {\r
-                                               /* Octet value too large */\r
-                                               if (digitHistory[0] > 2) {\r
-                                                       URI_FUNC(StopSyntax)(state, first - 3);\r
-                                               } else if (digitHistory[1] > 5) {\r
-                                                       URI_FUNC(StopSyntax)(state, first - 2);\r
-                                               } else {\r
-                                                       URI_FUNC(StopSyntax)(state, first - 1);\r
-                                               }\r
-                                               return NULL;\r
-                                       }\r
-\r
-                                       /* Copy IPv4 octet */\r
-                                       state->uri->hostData.ip6->data[16 - 4 + ip4OctetsDone] = uriGetOctetValue(digitHistory, digitCount);\r
-                                       digitCount = 0;\r
-                                       ip4OctetsDone++;\r
-                                       break;\r
-\r
-                               case _UT(']'):\r
-                                       if ((ip4OctetsDone != 3) /* NOTE! */\r
-                                                       || (digitCount == 0)\r
-                                                       || (digitCount == 4)) {\r
-                                               /* Invalid digit or octet count */\r
-                                               URI_FUNC(StopSyntax)(state, first);\r
-                                               return NULL;\r
-                                       } else if ((digitCount > 1)\r
-                                                       && (digitHistory[0] == 0)) {\r
-                                               /* Leading zero */\r
-                                               URI_FUNC(StopSyntax)(state, first - digitCount);\r
-                                               return NULL;\r
-                                       } else if ((digitCount > 2)\r
-                                                       && (digitHistory[1] == 0)) {\r
-                                               /* Leading zero */\r
-                                               URI_FUNC(StopSyntax)(state, first - digitCount + 1);\r
-                                               return NULL;\r
-                                       } else if ((digitCount == 3)\r
-                                                       && (100 * digitHistory[0]\r
-                                                               + 10 * digitHistory[1]\r
-                                                               + digitHistory[2] > 255)) {\r
-                                               /* Octet value too large */\r
-                                               if (digitHistory[0] > 2) {\r
-                                                       URI_FUNC(StopSyntax)(state, first - 3);\r
-                                               } else if (digitHistory[1] > 5) {\r
-                                                       URI_FUNC(StopSyntax)(state, first - 2);\r
-                                               } else {\r
-                                                       URI_FUNC(StopSyntax)(state, first - 1);\r
-                                               }\r
-                                               return NULL;\r
-                                       }\r
-\r
-                                       state->uri->hostText.afterLast = first; /* HOST END */\r
-\r
-                                       /* Copy missing quads right before IPv4 */\r
-                                       memcpy(state->uri->hostData.ip6->data + 16 - 4 - 2 * quadsAfterZipperCount,\r
-                                                               quadsAfterZipper, 2 * quadsAfterZipperCount);\r
-\r
-                                       /* Copy last IPv4 octet */\r
-                                       state->uri->hostData.ip6->data[16 - 4 + 3] = uriGetOctetValue(digitHistory, digitCount);\r
-\r
-                                       return first + 1;\r
-\r
-                               default:\r
-                                       URI_FUNC(StopSyntax)(state, first);\r
-                                       return NULL;\r
-                               }\r
-                               first++;\r
-                       }\r
-               } else {\r
-                       /* Eat while no dot in sight */\r
-                       int letterAmong = 0;\r
-                       int walking = 1;\r
-                       do {\r
-                               switch (*first) {\r
-                               case URI_SET_HEX_LETTER_LOWER:\r
-                                       letterAmong = 1;\r
-                                       if (digitCount == 4) {\r
-                                               URI_FUNC(StopSyntax)(state, first);\r
-                                               return NULL;\r
-                                       }\r
-                                       digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('f'));\r
-                                       digitCount++;\r
-                                       break;\r
-\r
-                               case URI_SET_HEX_LETTER_UPPER:\r
-                                       letterAmong = 1;\r
-                                       if (digitCount == 4) {\r
-                                               URI_FUNC(StopSyntax)(state, first);\r
-                                               return NULL;\r
-                                       }\r
-                                       digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('F'));\r
-                                       digitCount++;\r
-                                       break;\r
-\r
-                               case URI_SET_DIGIT:\r
-                                       if (digitCount == 4) {\r
-                                               URI_FUNC(StopSyntax)(state, first);\r
-                                               return NULL;\r
-                                       }\r
-                                       digitHistory[digitCount] = (unsigned char)(9 + *first - _UT('9'));\r
-                                       digitCount++;\r
-                                       break;\r
-\r
-                               case _UT(':'):\r
-                                       {\r
-                                               int setZipper = 0;\r
-\r
-                                               /* Too many quads? */\r
-                                               if (quadsDone > 8 - zipperEver) {\r
-                                                       URI_FUNC(StopSyntax)(state, first);\r
-                                                       return NULL;\r
-                                               }\r
-\r
-                                               /* "::"? */\r
-                                               if (first + 1 >= afterLast) {\r
-                                                       URI_FUNC(StopSyntax)(state, first + 1);\r
-                                                       return NULL;\r
-                                               }\r
-                                               if (first[1] == _UT(':')) {\r
-                                                       const int resetOffset = 2 * (quadsDone + (digitCount > 0));\r
-\r
-                                                       first++;\r
-                                                       if (zipperEver) {\r
-                                                               URI_FUNC(StopSyntax)(state, first);\r
-                                                               return NULL; /* "::.+::" */\r
-                                                       }\r
-\r
-                                                       /* Zero everything after zipper */\r
-                                                       memset(state->uri->hostData.ip6->data + resetOffset, 0, 16 - resetOffset);\r
-                                                       setZipper = 1;\r
-\r
-                                                       /* ":::+"? */\r
-                                                       if (first + 1 >= afterLast) {\r
-                                                               URI_FUNC(StopSyntax)(state, first + 1);\r
-                                                               return NULL; /* No ']' yet */\r
-                                                       }\r
-                                                       if (first[1] == _UT(':')) {\r
-                                                               URI_FUNC(StopSyntax)(state, first + 1);\r
-                                                               return NULL; /* ":::+ "*/\r
-                                                       }\r
-                                               }\r
-                                               if (digitCount > 0) {\r
-                                                       if (zipperEver) {\r
-                                                               uriWriteQuadToDoubleByte(digitHistory, digitCount, quadsAfterZipper + 2 * quadsAfterZipperCount);\r
-                                                               quadsAfterZipperCount++;\r
-                                                       } else {\r
-                                                               uriWriteQuadToDoubleByte(digitHistory, digitCount, state->uri->hostData.ip6->data + 2 * quadsDone);\r
-                                                       }\r
-                                                       quadsDone++;\r
-                                                       digitCount = 0;\r
-                                               }\r
-                                               letterAmong = 0;\r
-\r
-                                               if (setZipper) {\r
-                                                       zipperEver = 1;\r
-                                               }\r
-                                       }\r
-                                       break;\r
-\r
-                               case _UT('.'):\r
-                                       if ((quadsDone > 6) /* NOTE */\r
-                                                       || (!zipperEver && (quadsDone < 6))\r
-                                                       || letterAmong\r
-                                                       || (digitCount == 0)\r
-                                                       || (digitCount == 4)) {\r
-                                               /* Invalid octet before */\r
-                                               URI_FUNC(StopSyntax)(state, first);\r
-                                               return NULL;\r
-                                       } else if ((digitCount > 1)\r
-                                                       && (digitHistory[0] == 0)) {\r
-                                               /* Leading zero */\r
-                                               URI_FUNC(StopSyntax)(state, first - digitCount);\r
-                                               return NULL;\r
-                                       } else if ((digitCount > 2)\r
-                                                       && (digitHistory[1] == 0)) {\r
-                                               /* Leading zero */\r
-                                               URI_FUNC(StopSyntax)(state, first - digitCount + 1);\r
-                                               return NULL;\r
-                                       } else if ((digitCount == 3)\r
-                                                       && (100 * digitHistory[0]\r
-                                                               + 10 * digitHistory[1]\r
-                                                               + digitHistory[2] > 255)) {\r
-                                               /* Octet value too large */\r
-                                               if (digitHistory[0] > 2) {\r
-                                                       URI_FUNC(StopSyntax)(state, first - 3);\r
-                                               } else if (digitHistory[1] > 5) {\r
-                                                       URI_FUNC(StopSyntax)(state, first - 2);\r
-                                               } else {\r
-                                                       URI_FUNC(StopSyntax)(state, first - 1);\r
-                                               }\r
-                                               return NULL;\r
-                                       }\r
-\r
-                                       /* Copy first IPv4 octet */\r
-                                       state->uri->hostData.ip6->data[16 - 4] = uriGetOctetValue(digitHistory, digitCount);\r
-                                       digitCount = 0;\r
-\r
-                                       /* Switch over to IPv4 loop */\r
-                                       ip4OctetsDone = 1;\r
-                                       walking = 0;\r
-                                       break;\r
-\r
-                               case _UT(']'):\r
-                                       /* Too little quads? */\r
-                                       if (!zipperEver && !((quadsDone == 7) && (digitCount > 0))) {\r
-                                               URI_FUNC(StopSyntax)(state, first);\r
-                                               return NULL;\r
-                                       }\r
-\r
-                                       if (digitCount > 0) {\r
-                                               if (zipperEver) {\r
-                                                       uriWriteQuadToDoubleByte(digitHistory, digitCount, quadsAfterZipper + 2 * quadsAfterZipperCount);\r
-                                                       quadsAfterZipperCount++;\r
-                                               } else {\r
-                                                       uriWriteQuadToDoubleByte(digitHistory, digitCount, state->uri->hostData.ip6->data + 2 * quadsDone);\r
-                                               }\r
-                                               /*\r
-                                               quadsDone++;\r
-                                               digitCount = 0;\r
-                                               */\r
-                                       }\r
-\r
-                                       /* Copy missing quads to the end */\r
-                                       memcpy(state->uri->hostData.ip6->data + 16 - 2 * quadsAfterZipperCount,\r
-                                                               quadsAfterZipper, 2 * quadsAfterZipperCount);\r
-\r
-                                       state->uri->hostText.afterLast = first; /* HOST END */\r
-                                       return first + 1; /* Fine */\r
-\r
-                               default:\r
-                                       URI_FUNC(StopSyntax)(state, first);\r
-                                       return NULL;\r
-                               }\r
-                               first++;\r
-\r
-                               if (first >= afterLast) {\r
-                                       URI_FUNC(StopSyntax)(state, first);\r
-                                       return NULL; /* No ']' yet */\r
-                               }\r
-                       } while (walking);\r
-               }\r
-       }\r
-}\r
-\r
-\r
-\r
-/*\r
- * [mustBeSegmentNzNc]->[pctEncoded][mustBeSegmentNzNc]\r
- * [mustBeSegmentNzNc]->[subDelims][mustBeSegmentNzNc]\r
- * [mustBeSegmentNzNc]->[unreserved][mustBeSegmentNzNc]\r
- * [mustBeSegmentNzNc]->[uriTail] // can take <NULL>\r
- * [mustBeSegmentNzNc]-></>[segment][zeroMoreSlashSegs][uriTail]\r
- * [mustBeSegmentNzNc]-><@>[mustBeSegmentNzNc]\r
- */\r
-static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */\r
-                       URI_FUNC(StopMalloc)(state);\r
-                       return NULL;\r
-               }\r
-               state->uri->scheme.first = NULL; /* Not a scheme, reset */\r
-               return afterLast;\r
-       }\r
-\r
-       switch (*first) {\r
-       case _UT('%'):\r
-               {\r
-                       const URI_CHAR * const afterPctEncoded\r
-                                       = URI_FUNC(ParsePctEncoded)(state, first, afterLast);\r
-                       if (afterPctEncoded == NULL) {\r
-                               return NULL;\r
-                       }\r
-                       return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast);\r
-               }\r
-\r
-       case _UT('@'):\r
-       case _UT('!'):\r
-       case _UT('$'):\r
-       case _UT('&'):\r
-       case _UT('('):\r
-       case _UT(')'):\r
-       case _UT('*'):\r
-       case _UT(','):\r
-       case _UT(';'):\r
-       case _UT('\''):\r
-       case _UT('+'):\r
-       case _UT('='):\r
-       case _UT('-'):\r
-       case _UT('.'):\r
-       case _UT('_'):\r
-       case _UT('~'):\r
-       case URI_SET_DIGIT:\r
-       case URI_SET_ALPHA:\r
-               return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast);\r
-\r
-       case _UT('/'):\r
-               {\r
-                       const URI_CHAR * afterZeroMoreSlashSegs;\r
-                       const URI_CHAR * afterSegment;\r
-                       if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */\r
-                               URI_FUNC(StopMalloc)(state);\r
-                               return NULL;\r
-                       }\r
-                       state->uri->scheme.first = NULL; /* Not a scheme, reset */\r
-                       afterSegment = URI_FUNC(ParseSegment)(state, first + 1, afterLast);\r
-                       if (afterSegment == NULL) {\r
-                               return NULL;\r
-                       }\r
-                       if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */\r
-                               URI_FUNC(StopMalloc)(state);\r
-                               return NULL;\r
-                       }\r
-                       afterZeroMoreSlashSegs\r
-                                       = URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast);\r
-                       if (afterZeroMoreSlashSegs == NULL) {\r
-                               return NULL;\r
-                       }\r
-                       return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast);\r
-               }\r
-\r
-       default:\r
-               if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */\r
-                       URI_FUNC(StopMalloc)(state);\r
-                       return NULL;\r
-               }\r
-               state->uri->scheme.first = NULL; /* Not a scheme, reset */\r
-               return URI_FUNC(ParseUriTail)(state, first, afterLast);\r
-       }\r
-}\r
-\r
-\r
-\r
-/*\r
- * [ownHost]-><[>[ipLit2][authorityTwo]\r
- * [ownHost]->[ownHost2] // can take <NULL>\r
- */\r
-static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               return afterLast;\r
-       }\r
-\r
-       switch (*first) {\r
-       case _UT('['):\r
-               {\r
-                       const URI_CHAR * const afterIpLit2\r
-                                       = URI_FUNC(ParseIpLit2)(state, first + 1, afterLast);\r
-                       if (afterIpLit2 == NULL) {\r
-                               return NULL;\r
-                       }\r
-                       state->uri->hostText.first = first + 1; /* HOST BEGIN */\r
-                       return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast);\r
-               }\r
-\r
-       default:\r
-               return URI_FUNC(ParseOwnHost2)(state, first, afterLast);\r
-       }\r
-}\r
-\r
-\r
-\r
-static URI_INLINE UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first) {\r
-       state->uri->hostText.afterLast = first; /* HOST END */\r
-\r
-       /* Valid IPv4 or just a regname? */\r
-       state->uri->hostData.ip4 = malloc(1 * sizeof(UriIp4)); /* Freed when stopping on parse error */\r
-       if (state->uri->hostData.ip4 == NULL) {\r
-               return URI_FALSE; /* Raises malloc error */\r
-       }\r
-       if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,\r
-                       state->uri->hostText.first, state->uri->hostText.afterLast)) {\r
-               /* Not IPv4 */\r
-               free(state->uri->hostData.ip4);\r
-               state->uri->hostData.ip4 = NULL;\r
-       }\r
-       return URI_TRUE; /* Success */\r
-}\r
-\r
-\r
-\r
-/*\r
- * [ownHost2]->[authorityTwo] // can take <NULL>\r
- * [ownHost2]->[pctSubUnres][ownHost2]\r
- */\r
-static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {\r
-       if (first >= afterLast) {\r
-               if (!URI_FUNC(OnExitOwnHost2)(state, first)) {\r
-                       URI_FUNC(StopMalloc)(state);\r
-                       return NULL;\r
-               }\r
-               return afterLast;\r
-       }\r
-\r
-       switch (*first) {\r
-       case _UT('!'):\r
-       case _UT('$'):\r
-       case _UT('%'):\r
-       case _UT('&'):\r
-       case _UT('('):\r
-       case _UT(')'):\r
-       case _UT('-'):\r
-       case _UT('*'):\r
-       case _UT(','):\r
-       case _UT('.'):\r
-       case _UT(';'):\r
-       case _UT('\''):\r
-       case _UT('_'):\r
-       case _UT('~'):\r
-       case _UT('+'):\r
-       case _UT('='):\r
-       case URI_SET_DIGIT:\r
-       case URI_SET_ALPHA:\r
-               {\r
-                       const URI_CHAR * const afterPctSubUnres\r
-                                       = URI_FUNC(ParsePctSubUnres)(state, first, afterLast);\r
-                       if (afterPctSubUnres == NULL) {\r
-                               return NULL;\r
-                       }\r
-                       return URI_FUNC(ParseOwnHost2)(state, afterPctSubUnres, afterLast);\r
-               }\r
-\r
-       default:\r
-               if (!URI_FUNC(OnExitOwnHost2)(state, first)) {\r
-                       URI_FUNC(StopMalloc)(state);\r
-                       return NULL;\r
-               }\r
-               return URI_FUNC(ParseAuthorityTwo)(state, first, afterLast);\r
-       }\r
-}\r
-\r
-\r
-\r
-static URI_INLINE UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first) {\r
-       state->uri->hostText.first = state->uri->userInfo.first; /* Host instead of userInfo, update */\r
-       state->uri->userInfo.first = NULL; /* Not a userInfo, reset */\r
-       state->uri->hostText.afterLast = first; /* HOST END */\r
-\r
-       /* Valid IPv4 or just a regname? */\r
-       state->uri->hostData.ip4 = malloc(1 * sizeof(UriIp4)); /* Freed when stopping on parse error */\r
-       if (state->uri->hostData.ip4 == NULL) {\r
-               return URI_FALSE; /* Raises malloc error */\r
-       }\r
-       if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,\r
-                       state->uri->hostText.first, state->uri->hostText.afterLast)) {\r
-               /* Not IPv4 */\r
-               free(state->uri->hostData.ip4);\r
-               state->uri->hostData.ip4 = NULL;\r
-       }\r
-       return URI_TRUE; /* Success */\r
-}\r
-\r
-\r
-\r
-/*\r
- * [ownHostUserInfo]->[ownHostUserInfoNz]\r