libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

mhd_str.c (65768B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2015-2024 Karlson2k (Evgeny Grin)
      4 
      5   This library is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU Lesser General Public
      7   License as published by the Free Software Foundation; either
      8   version 2.1 of the License, or (at your option) any later version.
      9 
     10   This library is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13   Lesser General Public License for more details.
     14 
     15   You should have received a copy of the GNU Lesser General Public
     16   License along with this library; if not, write to the Free Software
     17   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     18 */
     19 
     20 /**
     21  * @file microhttpd/mhd_str.c
     22  * @brief  Functions implementations for string manipulating
     23  * @author Karlson2k (Evgeny Grin)
     24  */
     25 
     26 #include "mhd_str.h"
     27 
     28 #ifdef HAVE_STDBOOL_H
     29 #include <stdbool.h>
     30 #endif /* HAVE_STDBOOL_H */
     31 #include <string.h>
     32 
     33 #include "mhd_assert.h"
     34 #include "mhd_limits.h"
     35 #include "mhd_assert.h"
     36 
     37 #ifdef MHD_FAVOR_SMALL_CODE
     38 #ifdef _MHD_static_inline
     39 #undef _MHD_static_inline
     40 #endif /* _MHD_static_inline */
     41 /* Do not force inlining and do not use macro functions, use normal static
     42    functions instead.
     43    This may give more flexibility for size optimizations. */
     44 #define _MHD_static_inline static
     45 #ifndef HAVE_INLINE_FUNCS
     46 #define HAVE_INLINE_FUNCS 1
     47 #endif /* !INLINE_FUNC */
     48 #endif /* MHD_FAVOR_SMALL_CODE */
     49 
     50 /*
     51  * Block of functions/macros that use US-ASCII charset as required by HTTP
     52  * standards. Not affected by current locale settings.
     53  */
     54 
     55 #ifdef HAVE_INLINE_FUNCS
     56 
     57 #if 0 /* Disable unused functions. */
     58 /**
     59  * Check whether character is lower case letter in US-ASCII
     60  *
     61  * @param c character to check
     62  * @return non-zero if character is lower case letter, zero otherwise
     63  */
     64 _MHD_static_inline bool
     65 isasciilower (char c)
     66 {
     67   return (c >= 'a') && (c <= 'z');
     68 }
     69 
     70 
     71 #endif /* Disable unused functions. */
     72 
     73 
     74 /**
     75  * Check whether character is upper case letter in US-ASCII
     76  *
     77  * @param c character to check
     78  * @return non-zero if character is upper case letter, zero otherwise
     79  */
     80 _MHD_static_inline bool
     81 isasciiupper (char c)
     82 {
     83   return (c >= 'A') && (c <= 'Z');
     84 }
     85 
     86 
     87 #if 0 /* Disable unused functions. */
     88 /**
     89  * Check whether character is letter in US-ASCII
     90  *
     91  * @param c character to check
     92  * @return non-zero if character is letter in US-ASCII, zero otherwise
     93  */
     94 _MHD_static_inline bool
     95 isasciialpha (char c)
     96 {
     97   return isasciilower (c) || isasciiupper (c);
     98 }
     99 
    100 
    101 #endif /* Disable unused functions. */
    102 
    103 
    104 /**
    105  * Check whether character is decimal digit in US-ASCII
    106  *
    107  * @param c character to check
    108  * @return non-zero if character is decimal digit, zero otherwise
    109  */
    110 _MHD_static_inline bool
    111 isasciidigit (char c)
    112 {
    113   return (c >= '0') && (c <= '9');
    114 }
    115 
    116 
    117 #if 0 /* Disable unused functions. */
    118 /**
    119  * Check whether character is hexadecimal digit in US-ASCII
    120  *
    121  * @param c character to check
    122  * @return non-zero if character is decimal digit, zero otherwise
    123  */
    124 _MHD_static_inline bool
    125 isasciixdigit (char c)
    126 {
    127   return isasciidigit (c) ||
    128          ( (c >= 'A') && (c <= 'F') ) ||
    129          ( (c >= 'a') && (c <= 'f') );
    130 }
    131 
    132 
    133 /**
    134  * Check whether character is decimal digit or letter in US-ASCII
    135  *
    136  * @param c character to check
    137  * @return non-zero if character is decimal digit or letter, zero otherwise
    138  */
    139 _MHD_static_inline bool
    140 isasciialnum (char c)
    141 {
    142   return isasciialpha (c) || isasciidigit (c);
    143 }
    144 
    145 
    146 #endif /* Disable unused functions. */
    147 
    148 
    149 #if 0 /* Disable unused functions. */
    150 /**
    151  * Convert US-ASCII character to lower case.
    152  * If character is upper case letter in US-ASCII than it's converted to lower
    153  * case analog. If character is NOT upper case letter than it's returned
    154  * unmodified.
    155  *
    156  * @param c character to convert
    157  * @return converted to lower case character
    158  */
    159 _MHD_static_inline char
    160 toasciilower (char c)
    161 {
    162   return isasciiupper (c) ? (c - 'A' + 'a') : c;
    163 }
    164 
    165 
    166 /**
    167  * Convert US-ASCII character to upper case.
    168  * If character is lower case letter in US-ASCII than it's converted to upper
    169  * case analog. If character is NOT lower case letter than it's returned
    170  * unmodified.
    171  *
    172  * @param c character to convert
    173  * @return converted to upper case character
    174  */
    175 _MHD_static_inline char
    176 toasciiupper (char c)
    177 {
    178   return isasciilower (c) ? (c - 'a' + 'A') : c;
    179 }
    180 
    181 
    182 #endif /* Disable unused functions. */
    183 
    184 
    185 #if defined(MHD_FAVOR_SMALL_CODE) /* Used only in MHD_str_to_uvalue_n_() */
    186 /**
    187  * Convert US-ASCII decimal digit to its value.
    188  *
    189  * @param c character to convert
    190  * @return value of decimal digit or -1 if @ c is not decimal digit
    191  */
    192 _MHD_static_inline int
    193 todigitvalue (char c)
    194 {
    195   if (isasciidigit (c))
    196     return (unsigned char) (c - '0');
    197 
    198   return -1;
    199 }
    200 
    201 
    202 #endif /* MHD_FAVOR_SMALL_CODE */
    203 
    204 
    205 /**
    206  * Convert US-ASCII hexadecimal digit to its value.
    207  *
    208  * @param c character to convert
    209  * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit
    210  */
    211 _MHD_static_inline int
    212 toxdigitvalue (char c)
    213 {
    214 #if ! defined(MHD_FAVOR_SMALL_CODE)
    215   switch ((unsigned char) c)
    216   {
    217 #if 0 /* Disabled to give the compiler a hint about low probability */
    218   case 0x00U:    /* NUL */
    219   case 0x01U:    /* SOH */
    220   case 0x02U:    /* STX */
    221   case 0x03U:    /* ETX */
    222   case 0x04U:    /* EOT */
    223   case 0x05U:    /* ENQ */
    224   case 0x06U:    /* ACK */
    225   case 0x07U:    /* BEL */
    226   case 0x08U:    /* BS */
    227   case 0x09U:    /* HT */
    228   case 0x0AU:    /* LF */
    229   case 0x0BU:    /* VT */
    230   case 0x0CU:    /* FF */
    231   case 0x0DU:    /* CR */
    232   case 0x0EU:    /* SO */
    233   case 0x0FU:    /* SI */
    234   case 0x10U:    /* DLE */
    235   case 0x11U:    /* DC1 */
    236   case 0x12U:    /* DC2 */
    237   case 0x13U:    /* DC3 */
    238   case 0x14U:    /* DC4 */
    239   case 0x15U:    /* NAK */
    240   case 0x16U:    /* SYN */
    241   case 0x17U:    /* ETB */
    242   case 0x18U:    /* CAN */
    243   case 0x19U:    /* EM */
    244   case 0x1AU:    /* SUB */
    245   case 0x1BU:    /* ESC */
    246   case 0x1CU:    /* FS */
    247   case 0x1DU:    /* GS */
    248   case 0x1EU:    /* RS */
    249   case 0x1FU:    /* US */
    250   case 0x20U:    /* ' ' */
    251   case 0x21U:    /* '!' */
    252   case 0x22U:    /* '"' */
    253   case 0x23U:    /* '#' */
    254   case 0x24U:    /* '$' */
    255   case 0x25U:    /* '%' */
    256   case 0x26U:    /* '&' */
    257   case 0x27U:    /* '\'' */
    258   case 0x28U:    /* '(' */
    259   case 0x29U:    /* ')' */
    260   case 0x2AU:    /* '*' */
    261   case 0x2BU:    /* '+' */
    262   case 0x2CU:    /* ',' */
    263   case 0x2DU:    /* '-' */
    264   case 0x2EU:    /* '.' */
    265   case 0x2FU:    /* '/' */
    266     return -1;
    267 #endif
    268   case 0x30U: /* '0' */
    269     return 0;
    270   case 0x31U: /* '1' */
    271     return 1;
    272   case 0x32U: /* '2' */
    273     return 2;
    274   case 0x33U: /* '3' */
    275     return 3;
    276   case 0x34U: /* '4' */
    277     return 4;
    278   case 0x35U: /* '5' */
    279     return 5;
    280   case 0x36U: /* '6' */
    281     return 6;
    282   case 0x37U: /* '7' */
    283     return 7;
    284   case 0x38U: /* '8' */
    285     return 8;
    286   case 0x39U: /* '9' */
    287     return 9;
    288 #if 0         /* Disabled to give the compiler a hint about low probability */
    289   case 0x3AU: /* ':' */
    290   case 0x3BU: /* ';' */
    291   case 0x3CU: /* '<' */
    292   case 0x3DU: /* '=' */
    293   case 0x3EU: /* '>' */
    294   case 0x3FU: /* '?' */
    295   case 0x40U: /* '@' */
    296     return -1;
    297 #endif
    298   case 0x41U: /* 'A' */
    299     return 0xAU;
    300   case 0x42U: /* 'B' */
    301     return 0xBU;
    302   case 0x43U: /* 'C' */
    303     return 0xCU;
    304   case 0x44U: /* 'D' */
    305     return 0xDU;
    306   case 0x45U: /* 'E' */
    307     return 0xEU;
    308   case 0x46U: /* 'F' */
    309     return 0xFU;
    310 #if 0         /* Disabled to give the compiler a hint about low probability */
    311   case 0x47U: /* 'G' */
    312   case 0x48U: /* 'H' */
    313   case 0x49U: /* 'I' */
    314   case 0x4AU: /* 'J' */
    315   case 0x4BU: /* 'K' */
    316   case 0x4CU: /* 'L' */
    317   case 0x4DU: /* 'M' */
    318   case 0x4EU: /* 'N' */
    319   case 0x4FU: /* 'O' */
    320   case 0x50U: /* 'P' */
    321   case 0x51U: /* 'Q' */
    322   case 0x52U: /* 'R' */
    323   case 0x53U: /* 'S' */
    324   case 0x54U: /* 'T' */
    325   case 0x55U: /* 'U' */
    326   case 0x56U: /* 'V' */
    327   case 0x57U: /* 'W' */
    328   case 0x58U: /* 'X' */
    329   case 0x59U: /* 'Y' */
    330   case 0x5AU: /* 'Z' */
    331   case 0x5BU: /* '[' */
    332   case 0x5CU: /* '\' */
    333   case 0x5DU: /* ']' */
    334   case 0x5EU: /* '^' */
    335   case 0x5FU: /* '_' */
    336   case 0x60U: /* '`' */
    337     return -1;
    338 #endif
    339   case 0x61U: /* 'a' */
    340     return 0xAU;
    341   case 0x62U: /* 'b' */
    342     return 0xBU;
    343   case 0x63U: /* 'c' */
    344     return 0xCU;
    345   case 0x64U: /* 'd' */
    346     return 0xDU;
    347   case 0x65U: /* 'e' */
    348     return 0xEU;
    349   case 0x66U: /* 'f' */
    350     return 0xFU;
    351 #if 0         /* Disabled to give the compiler a hint about low probability */
    352   case 0x67U: /* 'g' */
    353   case 0x68U: /* 'h' */
    354   case 0x69U: /* 'i' */
    355   case 0x6AU: /* 'j' */
    356   case 0x6BU: /* 'k' */
    357   case 0x6CU: /* 'l' */
    358   case 0x6DU: /* 'm' */
    359   case 0x6EU: /* 'n' */
    360   case 0x6FU: /* 'o' */
    361   case 0x70U: /* 'p' */
    362   case 0x71U: /* 'q' */
    363   case 0x72U: /* 'r' */
    364   case 0x73U: /* 's' */
    365   case 0x74U: /* 't' */
    366   case 0x75U: /* 'u' */
    367   case 0x76U: /* 'v' */
    368   case 0x77U: /* 'w' */
    369   case 0x78U: /* 'x' */
    370   case 0x79U: /* 'y' */
    371   case 0x7AU: /* 'z' */
    372   case 0x7BU: /* '{' */
    373   case 0x7CU: /* '|' */
    374   case 0x7DU: /* '}' */
    375   case 0x7EU: /* '~' */
    376   case 0x7FU: /* DEL */
    377   case 0x80U: /* EXT */
    378   case 0x81U: /* EXT */
    379   case 0x82U: /* EXT */
    380   case 0x83U: /* EXT */
    381   case 0x84U: /* EXT */
    382   case 0x85U: /* EXT */
    383   case 0x86U: /* EXT */
    384   case 0x87U: /* EXT */
    385   case 0x88U: /* EXT */
    386   case 0x89U: /* EXT */
    387   case 0x8AU: /* EXT */
    388   case 0x8BU: /* EXT */
    389   case 0x8CU: /* EXT */
    390   case 0x8DU: /* EXT */
    391   case 0x8EU: /* EXT */
    392   case 0x8FU: /* EXT */
    393   case 0x90U: /* EXT */
    394   case 0x91U: /* EXT */
    395   case 0x92U: /* EXT */
    396   case 0x93U: /* EXT */
    397   case 0x94U: /* EXT */
    398   case 0x95U: /* EXT */
    399   case 0x96U: /* EXT */
    400   case 0x97U: /* EXT */
    401   case 0x98U: /* EXT */
    402   case 0x99U: /* EXT */
    403   case 0x9AU: /* EXT */
    404   case 0x9BU: /* EXT */
    405   case 0x9CU: /* EXT */
    406   case 0x9DU: /* EXT */
    407   case 0x9EU: /* EXT */
    408   case 0x9FU: /* EXT */
    409   case 0xA0U: /* EXT */
    410   case 0xA1U: /* EXT */
    411   case 0xA2U: /* EXT */
    412   case 0xA3U: /* EXT */
    413   case 0xA4U: /* EXT */
    414   case 0xA5U: /* EXT */
    415   case 0xA6U: /* EXT */
    416   case 0xA7U: /* EXT */
    417   case 0xA8U: /* EXT */
    418   case 0xA9U: /* EXT */
    419   case 0xAAU: /* EXT */
    420   case 0xABU: /* EXT */
    421   case 0xACU: /* EXT */
    422   case 0xADU: /* EXT */
    423   case 0xAEU: /* EXT */
    424   case 0xAFU: /* EXT */
    425   case 0xB0U: /* EXT */
    426   case 0xB1U: /* EXT */
    427   case 0xB2U: /* EXT */
    428   case 0xB3U: /* EXT */
    429   case 0xB4U: /* EXT */
    430   case 0xB5U: /* EXT */
    431   case 0xB6U: /* EXT */
    432   case 0xB7U: /* EXT */
    433   case 0xB8U: /* EXT */
    434   case 0xB9U: /* EXT */
    435   case 0xBAU: /* EXT */
    436   case 0xBBU: /* EXT */
    437   case 0xBCU: /* EXT */
    438   case 0xBDU: /* EXT */
    439   case 0xBEU: /* EXT */
    440   case 0xBFU: /* EXT */
    441   case 0xC0U: /* EXT */
    442   case 0xC1U: /* EXT */
    443   case 0xC2U: /* EXT */
    444   case 0xC3U: /* EXT */
    445   case 0xC4U: /* EXT */
    446   case 0xC5U: /* EXT */
    447   case 0xC6U: /* EXT */
    448   case 0xC7U: /* EXT */
    449   case 0xC8U: /* EXT */
    450   case 0xC9U: /* EXT */
    451   case 0xCAU: /* EXT */
    452   case 0xCBU: /* EXT */
    453   case 0xCCU: /* EXT */
    454   case 0xCDU: /* EXT */
    455   case 0xCEU: /* EXT */
    456   case 0xCFU: /* EXT */
    457   case 0xD0U: /* EXT */
    458   case 0xD1U: /* EXT */
    459   case 0xD2U: /* EXT */
    460   case 0xD3U: /* EXT */
    461   case 0xD4U: /* EXT */
    462   case 0xD5U: /* EXT */
    463   case 0xD6U: /* EXT */
    464   case 0xD7U: /* EXT */
    465   case 0xD8U: /* EXT */
    466   case 0xD9U: /* EXT */
    467   case 0xDAU: /* EXT */
    468   case 0xDBU: /* EXT */
    469   case 0xDCU: /* EXT */
    470   case 0xDDU: /* EXT */
    471   case 0xDEU: /* EXT */
    472   case 0xDFU: /* EXT */
    473   case 0xE0U: /* EXT */
    474   case 0xE1U: /* EXT */
    475   case 0xE2U: /* EXT */
    476   case 0xE3U: /* EXT */
    477   case 0xE4U: /* EXT */
    478   case 0xE5U: /* EXT */
    479   case 0xE6U: /* EXT */
    480   case 0xE7U: /* EXT */
    481   case 0xE8U: /* EXT */
    482   case 0xE9U: /* EXT */
    483   case 0xEAU: /* EXT */
    484   case 0xEBU: /* EXT */
    485   case 0xECU: /* EXT */
    486   case 0xEDU: /* EXT */
    487   case 0xEEU: /* EXT */
    488   case 0xEFU: /* EXT */
    489   case 0xF0U: /* EXT */
    490   case 0xF1U: /* EXT */
    491   case 0xF2U: /* EXT */
    492   case 0xF3U: /* EXT */
    493   case 0xF4U: /* EXT */
    494   case 0xF5U: /* EXT */
    495   case 0xF6U: /* EXT */
    496   case 0xF7U: /* EXT */
    497   case 0xF8U: /* EXT */
    498   case 0xF9U: /* EXT */
    499   case 0xFAU: /* EXT */
    500   case 0xFBU: /* EXT */
    501   case 0xFCU: /* EXT */
    502   case 0xFDU: /* EXT */
    503   case 0xFEU: /* EXT */
    504   case 0xFFU: /* EXT */
    505     return -1;
    506   default:
    507     mhd_assert (0);
    508     break;  /* Should be unreachable */
    509 #else
    510   default:
    511     break;
    512 #endif
    513   }
    514   return -1;
    515 #else  /* MHD_FAVOR_SMALL_CODE */
    516   if (isasciidigit (c))
    517     return (unsigned char) (c - '0');
    518   if ( (c >= 'A') && (c <= 'F') )
    519     return (unsigned char) (c - 'A' + 10);
    520   if ( (c >= 'a') && (c <= 'f') )
    521     return (unsigned char) (c - 'a' + 10);
    522 
    523   return -1;
    524 #endif /* MHD_FAVOR_SMALL_CODE */
    525 }
    526 
    527 
    528 /**
    529  * Caseless compare two characters.
    530  *
    531  * @param c1 the first char to compare
    532  * @param c2 the second char to compare
    533  * @return boolean 'true' if chars are caseless equal, false otherwise
    534  */
    535 _MHD_static_inline bool
    536 charsequalcaseless (const char c1, const char c2)
    537 {
    538   return ( (c1 == c2) ||
    539            (isasciiupper (c1) ?
    540             ((c1 - 'A' + 'a') == c2) :
    541             ((c1 == (c2 - 'A' + 'a')) && isasciiupper (c2))) );
    542 }
    543 
    544 
    545 #else  /* !INLINE_FUNC */
    546 
    547 
    548 /**
    549  * Checks whether character is lower case letter in US-ASCII
    550  *
    551  * @param c character to check
    552  * @return boolean true if character is lower case letter,
    553  *         boolean false otherwise
    554  */
    555 #define isasciilower(c) (((char) (c)) >= 'a' && ((char) (c)) <= 'z')
    556 
    557 
    558 /**
    559  * Checks whether character is upper case letter in US-ASCII
    560  *
    561  * @param c character to check
    562  * @return boolean true if character is upper case letter,
    563  *         boolean false otherwise
    564  */
    565 #define isasciiupper(c) (((char) (c)) >= 'A' && ((char) (c)) <= 'Z')
    566 
    567 
    568 /**
    569  * Checks whether character is letter in US-ASCII
    570  *
    571  * @param c character to check
    572  * @return boolean true if character is letter, boolean false
    573  *         otherwise
    574  */
    575 #define isasciialpha(c) (isasciilower (c) || isasciiupper (c))
    576 
    577 
    578 /**
    579  * Check whether character is decimal digit in US-ASCII
    580  *
    581  * @param c character to check
    582  * @return boolean true if character is decimal digit, boolean false
    583  *         otherwise
    584  */
    585 #define isasciidigit(c) (((char) (c)) >= '0' && ((char) (c)) <= '9')
    586 
    587 
    588 /**
    589  * Check whether character is hexadecimal digit in US-ASCII
    590  *
    591  * @param c character to check
    592  * @return boolean true if character is hexadecimal digit,
    593  *         boolean false otherwise
    594  */
    595 #define isasciixdigit(c) (isasciidigit ((c)) || \
    596                           (((char) (c)) >= 'A' && ((char) (c)) <= 'F') || \
    597                           (((char) (c)) >= 'a' && ((char) (c)) <= 'f') )
    598 
    599 
    600 /**
    601  * Check whether character is decimal digit or letter in US-ASCII
    602  *
    603  * @param c character to check
    604  * @return boolean true if character is decimal digit or letter,
    605  *         boolean false otherwise
    606  */
    607 #define isasciialnum(c) (isasciialpha (c) || isasciidigit (c))
    608 
    609 
    610 /**
    611  * Convert US-ASCII character to lower case.
    612  * If character is upper case letter in US-ASCII than it's converted to lower
    613  * case analog. If character is NOT upper case letter than it's returned
    614  * unmodified.
    615  *
    616  * @param c character to convert
    617  * @return converted to lower case character
    618  */
    619 #define toasciilower(c) ((isasciiupper (c)) ? (((char) (c)) - 'A' + 'a') : \
    620                          ((char) (c)))
    621 
    622 
    623 /**
    624  * Convert US-ASCII character to upper case.
    625  * If character is lower case letter in US-ASCII than it's converted to upper
    626  * case analog. If character is NOT lower case letter than it's returned
    627  * unmodified.
    628  *
    629  * @param c character to convert
    630  * @return converted to upper case character
    631  */
    632 #define toasciiupper(c) ((isasciilower (c)) ? (((char) (c)) - 'a' + 'A') : \
    633                          ((char) (c)))
    634 
    635 
    636 /**
    637  * Convert US-ASCII decimal digit to its value.
    638  *
    639  * @param c character to convert
    640  * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit
    641  */
    642 #define todigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \
    643                          (int) (-1))
    644 
    645 
    646 /**
    647  * Convert US-ASCII hexadecimal digit to its value.
    648  * @param c character to convert
    649  * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit
    650  */
    651 #define toxdigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \
    652                           ( (((char) (c)) >= 'A' && ((char) (c)) <= 'F') ? \
    653                             (int) (((unsigned char) (c)) - 'A' + 10) : \
    654                             ( (((char) (c)) >= 'a' && ((char) (c)) <= 'f') ? \
    655                               (int) (((unsigned char) (c)) - 'a' + 10) : \
    656                               (int) (-1) )))
    657 
    658 /**
    659  * Caseless compare two characters.
    660  *
    661  * @param c1 the first char to compare
    662  * @param c2 the second char to compare
    663  * @return boolean 'true' if chars are caseless equal, false otherwise
    664  */
    665 #define charsequalcaseless(c1, c2) \
    666   ( ((c1) == (c2)) || \
    667            (isasciiupper (c1) ? \
    668              (((c1) - 'A' + 'a') == (c2)) : \
    669              (((c1) == ((c2) - 'A' + 'a')) && isasciiupper (c2))) )
    670 
    671 #endif /* !HAVE_INLINE_FUNCS */
    672 
    673 
    674 #ifndef MHD_FAVOR_SMALL_CODE
    675 /**
    676  * Check two strings for equality, ignoring case of US-ASCII letters.
    677  *
    678  * @param str1 first string to compare
    679  * @param str2 second string to compare
    680  * @return non-zero if two strings are equal, zero otherwise.
    681  */
    682 int
    683 MHD_str_equal_caseless_ (const char *str1,
    684                          const char *str2)
    685 {
    686   while (0 != (*str1))
    687   {
    688     const char c1 = *str1;
    689     const char c2 = *str2;
    690     if (charsequalcaseless (c1, c2))
    691     {
    692       str1++;
    693       str2++;
    694     }
    695     else
    696       return 0;
    697   }
    698   return 0 == (*str2);
    699 }
    700 
    701 
    702 #endif /* ! MHD_FAVOR_SMALL_CODE */
    703 
    704 
    705 /**
    706  * Check two string for equality, ignoring case of US-ASCII letters and
    707  * checking not more than @a maxlen characters.
    708  * Compares up to first terminating null character, but not more than
    709  * first @a maxlen characters.
    710  *
    711  * @param str1 first string to compare
    712  * @param str2 second string to compare
    713  * @param maxlen maximum number of characters to compare
    714  * @return non-zero if two strings are equal, zero otherwise.
    715  */
    716 int
    717 MHD_str_equal_caseless_n_ (const char *const str1,
    718                            const char *const str2,
    719                            size_t maxlen)
    720 {
    721   size_t i;
    722 
    723   for (i = 0; i < maxlen; ++i)
    724   {
    725     const char c1 = str1[i];
    726     const char c2 = str2[i];
    727     if (0 == c2)
    728       return 0 == c1;
    729     if (charsequalcaseless (c1, c2))
    730       continue;
    731     else
    732       return 0;
    733   }
    734   return ! 0;
    735 }
    736 
    737 
    738 /**
    739  * Check two string for equality, ignoring case of US-ASCII letters and
    740  * checking not more than @a len bytes.
    741  * Compares not more first than @a len bytes, including binary zero characters.
    742  * Comparison stops at first unmatched byte.
    743  * @param str1 first string to compare
    744  * @param str2 second string to compare
    745  * @param len number of characters to compare
    746  * @return non-zero if @a len bytes are equal, zero otherwise.
    747  */
    748 bool
    749 MHD_str_equal_caseless_bin_n_ (const char *const str1,
    750                                const char *const str2,
    751                                size_t len)
    752 {
    753   size_t i;
    754 
    755   for (i = 0; i < len; ++i)
    756   {
    757     const char c1 = str1[i];
    758     const char c2 = str2[i];
    759     if (charsequalcaseless (c1, c2))
    760       continue;
    761     else
    762       return 0;
    763   }
    764   return ! 0;
    765 }
    766 
    767 
    768 /**
    769  * Check whether @a str has case-insensitive @a token.
    770  * Token could be surrounded by spaces and tabs and delimited by comma.
    771  * Match succeed if substring between start, end (of string) or comma
    772  * contains only case-insensitive token and optional spaces and tabs.
    773  * @warning token must not contain null-characters except optional
    774  *          terminating null-character.
    775  * @param str the string to check
    776  * @param token the token to find
    777  * @param token_len length of token, not including optional terminating
    778  *                  null-character.
    779  * @return non-zero if two strings are equal, zero otherwise.
    780  */
    781 bool
    782 MHD_str_has_token_caseless_ (const char *str,
    783                              const char *const token,
    784                              size_t token_len)
    785 {
    786   if (0 == token_len)
    787     return false;
    788 
    789   while (0 != *str)
    790   {
    791     size_t i;
    792     /* Skip all whitespaces and empty tokens. */
    793     while (' ' == *str || '\t' == *str || ',' == *str)
    794       str++;
    795 
    796     /* Check for token match. */
    797     i = 0;
    798     while (1)
    799     {
    800       const char sc = *(str++);
    801       const char tc = token[i++];
    802 
    803       if (0 == sc)
    804         return false;
    805       if (! charsequalcaseless (sc, tc))
    806         break;
    807       if (i >= token_len)
    808       {
    809         /* Check whether substring match token fully or
    810          * has additional unmatched chars at tail. */
    811         while (' ' == *str || '\t' == *str)
    812           str++;
    813         /* End of (sub)string? */
    814         if ((0 == *str) || (',' == *str) )
    815           return true;
    816         /* Unmatched chars at end of substring. */
    817         break;
    818       }
    819     }
    820     /* Find next substring. */
    821     while (0 != *str && ',' != *str)
    822       str++;
    823   }
    824   return false;
    825 }
    826 
    827 
    828 /**
    829  * Remove case-insensitive @a token from the @a str and put result
    830  * to the output @a buf.
    831  *
    832  * Tokens in @a str could be surrounded by spaces and tabs and delimited by
    833  * comma. The token match succeed if substring between start, end (of string)
    834  * or comma contains only case-insensitive token and optional spaces and tabs.
    835  * The quoted strings and comments are not supported by this function.
    836  *
    837  * The output string is normalised: empty tokens and repeated whitespaces
    838  * are removed, no whitespaces before commas, exactly one space is used after
    839  * each comma.
    840  *
    841  * @param str the string to process
    842  * @param str_len the length of the @a str, not including optional
    843  *                terminating null-character.
    844  * @param token the token to find
    845  * @param token_len the length of @a token, not including optional
    846  *                  terminating null-character.
    847  * @param[out] buf the output buffer, not null-terminated.
    848  * @param[in,out] buf_size pointer to the size variable, at input it
    849  *                         is the size of allocated buffer, at output
    850  *                         it is the size of the resulting string (can
    851  *                         be up to 50% larger than input) or negative value
    852  *                         if there is not enough space for the result
    853  * @return 'true' if token has been removed,
    854  *         'false' otherwise.
    855  */
    856 bool
    857 MHD_str_remove_token_caseless_ (const char *str,
    858                                 size_t str_len,
    859                                 const char *const token,
    860                                 const size_t token_len,
    861                                 char *buf,
    862                                 ssize_t *buf_size)
    863 {
    864   const char *s1; /**< the "input" string / character */
    865   char *s2;       /**< the "output" string / character */
    866   size_t t_pos;   /**< position of matched character in the token */
    867   bool token_removed;
    868 
    869   mhd_assert (NULL == memchr (token, 0, token_len));
    870   mhd_assert (NULL == memchr (token, ' ', token_len));
    871   mhd_assert (NULL == memchr (token, '\t', token_len));
    872   mhd_assert (NULL == memchr (token, ',', token_len));
    873   mhd_assert (0 <= *buf_size);
    874 
    875   if (SSIZE_MAX <= ((str_len / 2) * 3 + 3))
    876   {
    877     /* The return value may overflow, refuse */
    878     *buf_size = (ssize_t) -1;
    879     return false;
    880   }
    881   s1 = str;
    882   s2 = buf;
    883   token_removed = false;
    884 
    885   while ((size_t) (s1 - str) < str_len)
    886   {
    887     const char *cur_token; /**< the first char of current token */
    888     size_t copy_size;
    889 
    890     /* Skip any initial whitespaces and empty tokens */
    891     while ( ((size_t) (s1 - str) < str_len) &&
    892             ((' ' == *s1) || ('\t' == *s1) || (',' == *s1)) )
    893       s1++;
    894 
    895     /* 's1' points to the first char of token in the input string or
    896      * points just beyond the end of the input string */
    897 
    898     if ((size_t) (s1 - str) >= str_len)
    899       break; /* Nothing to copy, end of the input string */
    900 
    901     /* 's1' points to the first char of token in the input string */
    902 
    903     cur_token = s1; /* the first char of input token */
    904 
    905     /* Check the token with case-insensetive match */
    906     t_pos = 0;
    907     while ( ((size_t) (s1 - str) < str_len) && (token_len > t_pos) &&
    908             (charsequalcaseless (*s1, token[t_pos])) )
    909     {
    910       s1++;
    911       t_pos++;
    912     }
    913     /* s1 may point just beyond the end of the input string */
    914     if ( (token_len == t_pos) && (0 != token_len) )
    915     {
    916       /* 'token' matched, check that current input token does not have
    917        * any suffixes */
    918       while ( ((size_t) (s1 - str) < str_len) &&
    919               ((' ' == *s1) || ('\t' == *s1)) )
    920         s1++;
    921       /* 's1' points to the first non-whitespace char after the token matched
    922        * requested token or points just beyond the end of the input string after
    923        * the requested token */
    924       if (((size_t) (s1 - str) == str_len) || (',' == *s1))
    925       {/* full token match, do not copy current token to the output */
    926         token_removed = true;
    927         continue;
    928       }
    929     }
    930 
    931     /* 's1' points to first non-whitespace char, to some char after
    932      * first non-whitespace char in the token in the input string, to
    933      * the ',', or just beyond the end of the input string */
    934     /* The current token in the input string does not match the token
    935      * to exclude, it must be copied to the output string */
    936     /* the current token size excluding leading whitespaces and current char */
    937     copy_size = (size_t) (s1 - cur_token);
    938     if (buf == s2)
    939     { /* The first token to copy to the output */
    940       if ((size_t) *buf_size < copy_size)
    941       { /* Not enough space in the output buffer */
    942         *buf_size = (ssize_t) -1;
    943         return false;
    944       }
    945     }
    946     else
    947     { /* Some token was already copied to the output buffer */
    948       mhd_assert (s2 > buf);
    949       if ((size_t) *buf_size < ((size_t) (s2 - buf)) + copy_size + 2)
    950       { /* Not enough space in the output buffer */
    951         *buf_size = (ssize_t) -1;
    952         return false;
    953       }
    954       *(s2++) = ',';
    955       *(s2++) = ' ';
    956     }
    957     /* Copy non-matched token to the output */
    958     if (0 != copy_size)
    959     {
    960       memcpy (s2, cur_token, copy_size);
    961       s2 += copy_size;
    962     }
    963 
    964     while ( ((size_t) (s1 - str) < str_len) && (',' != *s1))
    965     {
    966       /* 's1' points to first non-whitespace char, to some char after
    967        * first non-whitespace char in the token in the input string */
    968       /* Copy all non-whitespace chars from the current token in
    969        * the input string */
    970       while ( ((size_t) (s1 - str) < str_len) &&
    971               (',' != *s1) && (' ' != *s1) && ('\t' != *s1) )
    972       {
    973         mhd_assert (s2 >= buf);
    974         if ((size_t) *buf_size <= (size_t) (s2 - buf)) /* '<= s2' equals '< s2 + 1' */
    975         { /* Not enough space in the output buffer */
    976           *buf_size = (ssize_t) -1;
    977           return false;
    978         }
    979         *(s2++) = *(s1++);
    980       }
    981       /* 's1' points to some whitespace char in the token in the input
    982        * string, to the ',', or just beyond the end of the input string */
    983       /* Skip all whitespaces */
    984       while ( ((size_t) (s1 - str) < str_len) &&
    985               ((' ' == *s1) || ('\t' == *s1)) )
    986         s1++;
    987 
    988       /* 's1' points to the first non-whitespace char in the input string
    989        * after whitespace chars, to the ',', or just beyond the end of
    990        * the input string */
    991       if (((size_t) (s1 - str) < str_len) && (',' != *s1))
    992       { /* Not the end of the current token */
    993         mhd_assert (s2 >= buf);
    994         if ((size_t) *buf_size <= (size_t) (s2 - buf)) /* '<= s2' equals '< s2 + 1' */
    995         { /* Not enough space in the output buffer */
    996           *buf_size = (ssize_t) -1;
    997           return false;
    998         }
    999         *(s2++) = ' ';
   1000       }
   1001     }
   1002   }
   1003   mhd_assert (((ssize_t) (s2 - buf)) <= *buf_size);
   1004   *buf_size = (ssize_t) (s2 - buf);
   1005   return token_removed;
   1006 }
   1007 
   1008 
   1009 /**
   1010  * Perform in-place case-insensitive removal of @a tokens from the @a str.
   1011  *
   1012  * Token could be surrounded by spaces and tabs and delimited by comma.
   1013  * The token match succeed if substring between start, end (of the string), or
   1014  * comma contains only case-insensitive token and optional spaces and tabs.
   1015  * The quoted strings and comments are not supported by this function.
   1016  *
   1017  * The input string must be normalised: empty tokens and repeated whitespaces
   1018  * are removed, no whitespaces before commas, exactly one space is used after
   1019  * each comma. The string is updated in-place.
   1020  *
   1021  * Behavior is undefined is the input string in not normalised.
   1022  *
   1023  * @param[in,out] str the string to update
   1024  * @param[in,out] str_len the length of the @a str, not including optional
   1025  *                        terminating null-character, not null-terminated
   1026  * @param tokens the token to find
   1027  * @param tokens_len the length of @a tokens, not including optional
   1028  *                   terminating null-character.
   1029  * @return 'true' if any token has been removed,
   1030  *         'false' otherwise.
   1031  */
   1032 bool
   1033 MHD_str_remove_tokens_caseless_ (char *str,
   1034                                  size_t *str_len,
   1035                                  const char *const tokens,
   1036                                  const size_t tokens_len)
   1037 {
   1038   const char *const t = tokens;   /**< a short alias for @a tokens */
   1039   size_t pt;                      /**< position in @a tokens */
   1040   bool token_removed;
   1041 
   1042   mhd_assert (NULL == memchr (tokens, 0, tokens_len));
   1043 
   1044   token_removed = false;
   1045   pt = 0;
   1046 
   1047   while (pt < tokens_len && *str_len != 0)
   1048   {
   1049     const char *tkn; /**< the current token */
   1050     size_t tkn_len;
   1051 
   1052     /* Skip any initial whitespaces and empty tokens in 'tokens' */
   1053     while ( (pt < tokens_len) &&
   1054             ((' ' == t[pt]) || ('\t' == t[pt]) || (',' == t[pt])) )
   1055       pt++;
   1056 
   1057     if (pt >= tokens_len)
   1058       break; /* No more tokens, nothing to remove */
   1059 
   1060     /* Found non-whitespace char which is not a comma */
   1061     tkn = t + pt;
   1062     do
   1063     {
   1064       do
   1065       {
   1066         pt++;
   1067       } while (pt < tokens_len &&
   1068                (' ' != t[pt] && '\t' != t[pt] && ',' != t[pt]));
   1069       /* Found end of the token string, space, tab, or comma */
   1070       tkn_len = pt - (size_t) (tkn - t);
   1071 
   1072       /* Skip all spaces and tabs */
   1073       while (pt < tokens_len && (' ' == t[pt] || '\t' == t[pt]))
   1074         pt++;
   1075       /* Found end of the token string or non-whitespace char */
   1076     } while (pt < tokens_len && ',' != t[pt]);
   1077 
   1078     /* 'tkn' is the input token with 'tkn_len' chars */
   1079     mhd_assert (0 != tkn_len);
   1080 
   1081     if (*str_len == tkn_len)
   1082     {
   1083       if (MHD_str_equal_caseless_bin_n_ (str, tkn, tkn_len))
   1084       {
   1085         *str_len = 0;
   1086         token_removed = true;
   1087       }
   1088       continue;
   1089     }
   1090     /* 'tkn' cannot match part of 'str' if length of 'tkn' is larger
   1091      * than length of 'str'.
   1092      * It's know that 'tkn' is not equal to the 'str' (was checked previously).
   1093      * As 'str' is normalized when 'tkn' is not equal to the 'str'
   1094      * it is required that 'str' to be at least 3 chars larger then 'tkn'
   1095      * (the comma, the space and at least one additional character for the next
   1096      * token) to remove 'tkn' from the 'str'. */
   1097     if (*str_len > tkn_len + 2)
   1098     { /* Remove 'tkn' from the input string */
   1099       size_t pr;    /**< the 'read' position in the @a str */
   1100       size_t pw;    /**< the 'write' position in the @a str */
   1101 
   1102       pr = 0;
   1103       pw = 0;
   1104 
   1105       do
   1106       {
   1107         mhd_assert (pr >= pw);
   1108         mhd_assert ((*str_len) >= (pr + tkn_len));
   1109         if ( ( ((*str_len) == (pr + tkn_len)) || (',' == str[pr + tkn_len]) ) &&
   1110              MHD_str_equal_caseless_bin_n_ (str + pr, tkn, tkn_len) )
   1111         {
   1112           /* current token in the input string matches the 'tkn', skip it */
   1113           mhd_assert ((*str_len == pr + tkn_len) || \
   1114                       (' ' == str[pr + tkn_len + 1])); /* 'str' must be normalized */
   1115           token_removed = true;
   1116           /* Advance to the next token in the input string or beyond
   1117            * the end of the input string. */
   1118           pr += tkn_len + 2;
   1119         }
   1120         else
   1121         {
   1122           /* current token in the input string does not match the 'tkn',
   1123            * copy to the output */
   1124           if (0 != pw)
   1125           { /* not the first output token, add ", " to separate */
   1126             if (pr != pw + 2)
   1127             {
   1128               str[pw++] = ',';
   1129               str[pw++] = ' ';
   1130             }
   1131             else
   1132               pw += 2; /* 'str' is not yet modified in this round */
   1133           }
   1134           do
   1135           {
   1136             if (pr != pw)
   1137               str[pw] = str[pr];
   1138             pr++;
   1139             pw++;
   1140           } while (pr < *str_len && ',' != str[pr]);
   1141           /* Advance to the next token in the input string or beyond
   1142            * the end of the input string. */
   1143           pr += 2;
   1144         }
   1145         /* 'pr' should point to the next token in the input string or beyond
   1146          * the end of the input string */
   1147         if ((*str_len) < (pr + tkn_len))
   1148         { /* The rest of the 'str + pr' is too small to match 'tkn' */
   1149           if ((*str_len) > pr)
   1150           { /* Copy the rest of the string */
   1151             size_t copy_size;
   1152             copy_size = *str_len - pr;
   1153             if (0 != pw)
   1154             { /* not the first output token, add ", " to separate */
   1155               if (pr != pw + 2)
   1156               {
   1157                 str[pw++] = ',';
   1158                 str[pw++] = ' ';
   1159               }
   1160               else
   1161                 pw += 2; /* 'str' is not yet modified in this round */
   1162             }
   1163             if (pr != pw)
   1164               memmove (str + pw, str + pr, copy_size);
   1165             pw += copy_size;
   1166           }
   1167           *str_len = pw;
   1168           break;
   1169         }
   1170         mhd_assert ((' ' != str[0]) && ('\t' != str[0]));
   1171         mhd_assert ((0 == pr) || (3 <= pr));
   1172         mhd_assert ((0 == pr) || (' ' == str[pr - 1]));
   1173         mhd_assert ((0 == pr) || (',' == str[pr - 2]));
   1174       } while (1);
   1175     }
   1176   }
   1177 
   1178   return token_removed;
   1179 }
   1180 
   1181 
   1182 #ifndef MHD_FAVOR_SMALL_CODE
   1183 /* Use individual function for each case */
   1184 
   1185 /**
   1186  * Convert decimal US-ASCII digits in string to number in uint64_t.
   1187  * Conversion stopped at first non-digit character.
   1188  *
   1189  * @param str string to convert
   1190  * @param[out] out_val pointer to uint64_t to store result of conversion
   1191  * @return non-zero number of characters processed on succeed,
   1192  *         zero if no digit is found, resulting value is larger
   1193  *         then possible to store in uint64_t or @a out_val is NULL
   1194  */
   1195 size_t
   1196 MHD_str_to_uint64_ (const char *str,
   1197                     uint64_t *out_val)
   1198 {
   1199   const char *const start = str;
   1200   uint64_t res;
   1201 
   1202   if (! str || ! out_val || ! isasciidigit (str[0]))
   1203     return 0;
   1204 
   1205   res = 0;
   1206   do
   1207   {
   1208     const int digit = (unsigned char) (*str) - '0';
   1209     if ( (res > (UINT64_MAX / 10)) ||
   1210          ( (res == (UINT64_MAX / 10)) &&
   1211            ((uint64_t) digit > (UINT64_MAX % 10)) ) )
   1212       return 0;
   1213 
   1214     res *= 10;
   1215     res += (unsigned int) digit;
   1216     str++;
   1217   } while (isasciidigit (*str));
   1218 
   1219   *out_val = res;
   1220   return (size_t) (str - start);
   1221 }
   1222 
   1223 
   1224 /**
   1225  * Convert not more then @a maxlen decimal US-ASCII digits in string to
   1226  * number in uint64_t.
   1227  * Conversion stopped at first non-digit character or after @a maxlen
   1228  * digits.
   1229  *
   1230  * @param str string to convert
   1231  * @param maxlen maximum number of characters to process
   1232  * @param[out] out_val pointer to uint64_t to store result of conversion
   1233  * @return non-zero number of characters processed on succeed,
   1234  *         zero if no digit is found, resulting value is larger
   1235  *         then possible to store in uint64_t or @a out_val is NULL
   1236  */
   1237 size_t
   1238 MHD_str_to_uint64_n_ (const char *str,
   1239                       size_t maxlen,
   1240                       uint64_t *out_val)
   1241 {
   1242   uint64_t res;
   1243   size_t i;
   1244 
   1245   if (! str || ! maxlen || ! out_val || ! isasciidigit (str[0]))
   1246     return 0;
   1247 
   1248   res = 0;
   1249   i = 0;
   1250   do
   1251   {
   1252     const int digit = (unsigned char) str[i] - '0';
   1253 
   1254     if ( (res > (UINT64_MAX / 10)) ||
   1255          ( (res == (UINT64_MAX / 10)) &&
   1256            ((uint64_t) digit > (UINT64_MAX % 10)) ) )
   1257       return 0;
   1258 
   1259     res *= 10;
   1260     res += (unsigned int) digit;
   1261     i++;
   1262   } while ( (i < maxlen) &&
   1263             isasciidigit (str[i]) );
   1264 
   1265   *out_val = res;
   1266   return i;
   1267 }
   1268 
   1269 
   1270 /**
   1271  * Convert hexadecimal US-ASCII digits in string to number in uint32_t.
   1272  * Conversion stopped at first non-digit character.
   1273  *
   1274  * @param str string to convert
   1275  * @param[out] out_val pointer to uint32_t to store result of conversion
   1276  * @return non-zero number of characters processed on succeed,
   1277  *         zero if no digit is found, resulting value is larger
   1278  *         then possible to store in uint32_t or @a out_val is NULL
   1279  */
   1280 size_t
   1281 MHD_strx_to_uint32_ (const char *str,
   1282                      uint32_t *out_val)
   1283 {
   1284   const char *const start = str;
   1285   uint32_t res;
   1286   int digit;
   1287 
   1288   if (! str || ! out_val)
   1289     return 0;
   1290 
   1291   res = 0;
   1292   digit = toxdigitvalue (*str);
   1293   while (digit >= 0)
   1294   {
   1295     if ( (res < (UINT32_MAX / 16)) ||
   1296          ((res == (UINT32_MAX / 16)) &&
   1297           ( (uint32_t) digit <= (UINT32_MAX % 16)) ) )
   1298     {
   1299       res *= 16;
   1300       res += (unsigned int) digit;
   1301     }
   1302     else
   1303       return 0;
   1304     str++;
   1305     digit = toxdigitvalue (*str);
   1306   }
   1307 
   1308   if (str - start > 0)
   1309     *out_val = res;
   1310   return (size_t) (str - start);
   1311 }
   1312 
   1313 
   1314 /**
   1315  * Convert not more then @a maxlen hexadecimal US-ASCII digits in string
   1316  * to number in uint32_t.
   1317  * Conversion stopped at first non-digit character or after @a maxlen
   1318  * digits.
   1319  *
   1320  * @param str string to convert
   1321  * @param maxlen maximum number of characters to process
   1322  * @param[out] out_val pointer to uint32_t to store result of conversion
   1323  * @return non-zero number of characters processed on succeed,
   1324  *         zero if no digit is found, resulting value is larger
   1325  *         then possible to store in uint32_t or @a out_val is NULL
   1326  */
   1327 size_t
   1328 MHD_strx_to_uint32_n_ (const char *str,
   1329                        size_t maxlen,
   1330                        uint32_t *out_val)
   1331 {
   1332   size_t i;
   1333   uint32_t res;
   1334   int digit;
   1335   if (! str || ! out_val)
   1336     return 0;
   1337 
   1338   res = 0;
   1339   i = 0;
   1340   while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
   1341   {
   1342     if ( (res > (UINT32_MAX / 16)) ||
   1343          ((res == (UINT32_MAX / 16)) &&
   1344           ( (uint32_t) digit > (UINT32_MAX % 16)) ) )
   1345       return 0;
   1346 
   1347     res *= 16;
   1348     res += (unsigned int) digit;
   1349     i++;
   1350   }
   1351 
   1352   if (i)
   1353     *out_val = res;
   1354   return i;
   1355 }
   1356 
   1357 
   1358 /**
   1359  * Convert hexadecimal US-ASCII digits in string to number in uint64_t.
   1360  * Conversion stopped at first non-digit character.
   1361  *
   1362  * @param str string to convert
   1363  * @param[out] out_val pointer to uint64_t to store result of conversion
   1364  * @return non-zero number of characters processed on succeed,
   1365  *         zero if no digit is found, resulting value is larger
   1366  *         then possible to store in uint64_t or @a out_val is NULL
   1367  */
   1368 size_t
   1369 MHD_strx_to_uint64_ (const char *str,
   1370                      uint64_t *out_val)
   1371 {
   1372   const char *const start = str;
   1373   uint64_t res;
   1374   int digit;
   1375   if (! str || ! out_val)
   1376     return 0;
   1377 
   1378   res = 0;
   1379   digit = toxdigitvalue (*str);
   1380   while (digit >= 0)
   1381   {
   1382     if ( (res < (UINT64_MAX / 16)) ||
   1383          ((res == (UINT64_MAX / 16)) &&
   1384           ( (uint64_t) digit <= (UINT64_MAX % 16)) ) )
   1385     {
   1386       res *= 16;
   1387       res += (unsigned int) digit;
   1388     }
   1389     else
   1390       return 0;
   1391     str++;
   1392     digit = toxdigitvalue (*str);
   1393   }
   1394 
   1395   if (str - start > 0)
   1396     *out_val = res;
   1397   return (size_t) (str - start);
   1398 }
   1399 
   1400 
   1401 /**
   1402  * Convert not more then @a maxlen hexadecimal US-ASCII digits in string
   1403  * to number in uint64_t.
   1404  * Conversion stopped at first non-digit character or after @a maxlen
   1405  * digits.
   1406  *
   1407  * @param str string to convert
   1408  * @param maxlen maximum number of characters to process
   1409  * @param[out] out_val pointer to uint64_t to store result of conversion
   1410  * @return non-zero number of characters processed on succeed,
   1411  *         zero if no digit is found, resulting value is larger
   1412  *         then possible to store in uint64_t or @a out_val is NULL
   1413  */
   1414 size_t
   1415 MHD_strx_to_uint64_n_ (const char *str,
   1416                        size_t maxlen,
   1417                        uint64_t *out_val)
   1418 {
   1419   size_t i;
   1420   uint64_t res;
   1421   int digit;
   1422   if (! str || ! out_val)
   1423     return 0;
   1424 
   1425   res = 0;
   1426   i = 0;
   1427   while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
   1428   {
   1429     if ( (res > (UINT64_MAX / 16)) ||
   1430          ((res == (UINT64_MAX / 16)) &&
   1431           ( (uint64_t) digit > (UINT64_MAX % 16)) ) )
   1432       return 0;
   1433 
   1434     res *= 16;
   1435     res += (unsigned int) digit;
   1436     i++;
   1437   }
   1438 
   1439   if (i)
   1440     *out_val = res;
   1441   return i;
   1442 }
   1443 
   1444 
   1445 #else  /* MHD_FAVOR_SMALL_CODE */
   1446 
   1447 /**
   1448  * Generic function for converting not more then @a maxlen
   1449  * hexadecimal or decimal US-ASCII digits in string to number.
   1450  * Conversion stopped at first non-digit character or after @a maxlen
   1451  * digits.
   1452  * To be used only within macro.
   1453  *
   1454  * @param str the string to convert
   1455  * @param maxlen the maximum number of characters to process
   1456  * @param out_val the pointer to variable to store result of conversion
   1457  * @param val_size the size of variable pointed by @a out_val, in bytes, 4 or 8
   1458  * @param max_val the maximum decoded number
   1459  * @param base the numeric base, 10 or 16
   1460  * @return non-zero number of characters processed on succeed,
   1461  *         zero if no digit is found, resulting value is larger
   1462  *         then @a max_val, @a val_size is not 4/8 or @a out_val is NULL
   1463  */
   1464 size_t
   1465 MHD_str_to_uvalue_n_ (const char *str,
   1466                       size_t maxlen,
   1467                       void *out_val,
   1468                       size_t val_size,
   1469                       uint64_t max_val,
   1470                       unsigned int base)
   1471 {
   1472   size_t i;
   1473   uint64_t res;
   1474   const uint64_t max_v_div_b = max_val / base;
   1475   const uint64_t max_v_mod_b = max_val % base;
   1476 
   1477   if (! str || ! out_val ||
   1478       ((base != 16) && (base != 10)) )
   1479     return 0;
   1480 
   1481   res = 0;
   1482   i = 0;
   1483   while (maxlen > i)
   1484   {
   1485     const int digit = (base == 16) ?
   1486                       toxdigitvalue (str[i]) : todigitvalue (str[i]);
   1487 
   1488     if (0 > digit)
   1489       break;
   1490     if ( ((max_v_div_b) < res) ||
   1491          (( (max_v_div_b) == res) && ( (max_v_mod_b) < (uint64_t) digit) ) )
   1492       return 0;
   1493 
   1494     res *= base;
   1495     res += (unsigned int) digit;
   1496     i++;
   1497   }
   1498 
   1499   if (i)
   1500   {
   1501     if (8 == val_size)
   1502       *(uint64_t *) out_val = res;
   1503     else if (4 == val_size)
   1504       *(uint32_t *) out_val = (uint32_t) res;
   1505     else
   1506       return 0;
   1507   }
   1508   return i;
   1509 }
   1510 
   1511 
   1512 #endif /* MHD_FAVOR_SMALL_CODE */
   1513 
   1514 
   1515 size_t
   1516 MHD_uint32_to_strx (uint32_t val,
   1517                     char *buf,
   1518                     size_t buf_size)
   1519 {
   1520   size_t o_pos = 0; /**< position of the output character */
   1521   int digit_pos = 8; /** zero-based, digit position in @a 'val' */
   1522   int digit;
   1523 
   1524   /* Skip leading zeros */
   1525   do
   1526   {
   1527     digit_pos--;
   1528     digit = (int) (val >> 28);
   1529     val <<= 4;
   1530   } while ((0 == digit) && (0 != digit_pos));
   1531 
   1532   while (o_pos < buf_size)
   1533   {
   1534     buf[o_pos++] =
   1535       (char) ((digit <= 9) ?
   1536               ('0' + (char) digit) :
   1537               ('A' + (char) digit - 10));
   1538     if (0 == digit_pos)
   1539       return o_pos;
   1540     digit_pos--;
   1541     digit = (int) (val >> 28);
   1542     val <<= 4;
   1543   }
   1544   return 0; /* The buffer is too small */
   1545 }
   1546 
   1547 
   1548 #ifndef MHD_FAVOR_SMALL_CODE
   1549 size_t
   1550 MHD_uint16_to_str (uint16_t val,
   1551                    char *buf,
   1552                    size_t buf_size)
   1553 {
   1554   char *chr;  /**< pointer to the current printed digit */
   1555   /* The biggest printable number is 65535 */
   1556   uint16_t divisor = UINT16_C (10000);
   1557   int digit;
   1558 
   1559   chr = buf;
   1560   digit = (int) (val / divisor);
   1561   mhd_assert (digit < 10);
   1562 
   1563   /* Do not print leading zeros */
   1564   while ((0 == digit) && (1 < divisor))
   1565   {
   1566     divisor /= 10;
   1567     digit = (int) (val / divisor);
   1568     mhd_assert (digit < 10);
   1569   }
   1570 
   1571   while (0 != buf_size)
   1572   {
   1573     *chr = (char) ((char) digit + '0');
   1574     chr++;
   1575     buf_size--;
   1576     if (1 == divisor)
   1577       return (size_t) (chr - buf);
   1578     val = (uint16_t) (val % divisor);
   1579     divisor /= 10;
   1580     digit = (int) (val / divisor);
   1581     mhd_assert (digit < 10);
   1582   }
   1583   return 0; /* The buffer is too small */
   1584 }
   1585 
   1586 
   1587 #endif /* !MHD_FAVOR_SMALL_CODE */
   1588 
   1589 
   1590 size_t
   1591 MHD_uint64_to_str (uint64_t val,
   1592                    char *buf,
   1593                    size_t buf_size)
   1594 {
   1595   char *chr;  /**< pointer to the current printed digit */
   1596   /* The biggest printable number is 18446744073709551615 */
   1597   uint64_t divisor = UINT64_C (10000000000000000000);
   1598   int digit;
   1599 
   1600   chr = buf;
   1601   digit = (int) (val / divisor);
   1602   mhd_assert (digit < 10);
   1603 
   1604   /* Do not print leading zeros */
   1605   while ((0 == digit) && (1 < divisor))
   1606   {
   1607     divisor /= 10;
   1608     digit = (int) (val / divisor);
   1609     mhd_assert (digit < 10);
   1610   }
   1611 
   1612   while (0 != buf_size)
   1613   {
   1614     *chr = (char) ((char) digit + '0');
   1615     chr++;
   1616     buf_size--;
   1617     if (1 == divisor)
   1618       return (size_t) (chr - buf);
   1619     val %= divisor;
   1620     divisor /= 10;
   1621     digit = (int) (val / divisor);
   1622     mhd_assert (digit < 10);
   1623   }
   1624   return 0; /* The buffer is too small */
   1625 }
   1626 
   1627 
   1628 size_t
   1629 MHD_uint8_to_str_pad (uint8_t val,
   1630                       uint8_t min_digits,
   1631                       char *buf,
   1632                       size_t buf_size)
   1633 {
   1634   size_t pos; /**< the position of the current printed digit */
   1635   int digit;
   1636   mhd_assert (3 >= min_digits);
   1637   if (0 == buf_size)
   1638     return 0;
   1639 
   1640   pos = 0;
   1641   digit = val / 100;
   1642   if (0 == digit)
   1643   {
   1644     if (3 <= min_digits)
   1645       buf[pos++] = '0';
   1646   }
   1647   else
   1648   {
   1649     buf[pos++] = (char) ('0' + (char) digit);
   1650     val %= 100;
   1651     min_digits = 2;
   1652   }
   1653 
   1654   if (buf_size <= pos)
   1655     return 0;
   1656   digit = val / 10;
   1657   if (0 == digit)
   1658   {
   1659     if (2 <= min_digits)
   1660       buf[pos++] = '0';
   1661   }
   1662   else
   1663   {
   1664     buf[pos++] = (char) ('0' + (char) digit);
   1665     val %= 10;
   1666   }
   1667 
   1668   if (buf_size <= pos)
   1669     return 0;
   1670   buf[pos++] = (char) ('0' + (char) val);
   1671   return pos;
   1672 }
   1673 
   1674 
   1675 size_t
   1676 MHD_bin_to_hex (const void *bin,
   1677                 size_t size,
   1678                 char *hex)
   1679 {
   1680   size_t i;
   1681 
   1682   for (i = 0; i < size; ++i)
   1683   {
   1684     uint8_t j;
   1685     const uint8_t b = ((const uint8_t *) bin)[i];
   1686     j = b >> 4;
   1687     hex[i * 2] = (char) ((j < 10) ? (j + '0') : (j - 10 + 'a'));
   1688     j = b & 0x0f;
   1689     hex[i * 2 + 1] = (char) ((j < 10) ? (j + '0') : (j - 10 + 'a'));
   1690   }
   1691   return i * 2;
   1692 }
   1693 
   1694 
   1695 size_t
   1696 MHD_bin_to_hex_z (const void *bin,
   1697                   size_t size,
   1698                   char *hex)
   1699 {
   1700   size_t res;
   1701 
   1702   res = MHD_bin_to_hex (bin, size, hex);
   1703   hex[res] = 0;
   1704 
   1705   return res;
   1706 }
   1707 
   1708 
   1709 size_t
   1710 MHD_hex_to_bin (const char *hex,
   1711                 size_t len,
   1712                 void *bin)
   1713 {
   1714   uint8_t *const out = (uint8_t *) bin;
   1715   size_t r;
   1716   size_t w;
   1717 
   1718   if (0 == len)
   1719     return 0;
   1720   r = 0;
   1721   w = 0;
   1722   if (0 != len % 2)
   1723   {
   1724     /* Assume the first byte is encoded with single digit */
   1725     const char c2 = hex[r++];
   1726     const int l = toxdigitvalue (c2);
   1727     if (0 > l)
   1728       return 0;
   1729     out[w++] = (uint8_t) ((unsigned int) l);
   1730   }
   1731   while (r < len)
   1732   {
   1733     const char c1 = hex[r++];
   1734     const char c2 = hex[r++];
   1735     const int h = toxdigitvalue (c1);
   1736     const int l = toxdigitvalue (c2);
   1737     if ((0 > h) || (0 > l))
   1738       return 0;
   1739     out[w++] = (uint8_t) ( ((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
   1740                            | ((uint8_t) ((unsigned int) l)) );
   1741   }
   1742   mhd_assert (len == r);
   1743   mhd_assert ((len + 1) / 2 == w);
   1744   return w;
   1745 }
   1746 
   1747 
   1748 size_t
   1749 MHD_str_pct_decode_strict_n_ (const char *pct_encoded,
   1750                               size_t pct_encoded_len,
   1751                               char *decoded,
   1752                               size_t buf_size)
   1753 {
   1754 #ifdef MHD_FAVOR_SMALL_CODE
   1755   bool broken;
   1756   size_t res;
   1757 
   1758   res = MHD_str_pct_decode_lenient_n_ (pct_encoded, pct_encoded_len, decoded,
   1759                                        buf_size, &broken);
   1760   if (broken)
   1761     return 0;
   1762   return res;
   1763 #else  /* ! MHD_FAVOR_SMALL_CODE */
   1764   size_t r;
   1765   size_t w;
   1766   r = 0;
   1767   w = 0;
   1768 
   1769   if (buf_size >= pct_encoded_len)
   1770   {
   1771     while (r < pct_encoded_len)
   1772     {
   1773       const char chr = pct_encoded[r];
   1774       if ('%' == chr)
   1775       {
   1776         if (2 > pct_encoded_len - r)
   1777           return 0;
   1778         else
   1779         {
   1780           const char c1 = pct_encoded[++r];
   1781           const char c2 = pct_encoded[++r];
   1782           const int h = toxdigitvalue (c1);
   1783           const int l = toxdigitvalue (c2);
   1784           unsigned char out;
   1785           if ((0 > h) || (0 > l))
   1786             return 0;
   1787           out =
   1788             (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
   1789                              | ((uint8_t) ((unsigned int) l)));
   1790           decoded[w] = (char) out;
   1791         }
   1792       }
   1793       else
   1794         decoded[w] = chr;
   1795       ++r;
   1796       ++w;
   1797     }
   1798     return w;
   1799   }
   1800 
   1801   while (r < pct_encoded_len)
   1802   {
   1803     const char chr = pct_encoded[r];
   1804     if (w >= buf_size)
   1805       return 0;
   1806     if ('%' == chr)
   1807     {
   1808       if (2 > pct_encoded_len - r)
   1809         return 0;
   1810       else
   1811       {
   1812         const char c1 = pct_encoded[++r];
   1813         const char c2 = pct_encoded[++r];
   1814         const int h = toxdigitvalue (c1);
   1815         const int l = toxdigitvalue (c2);
   1816         unsigned char out;
   1817         if ((0 > h) || (0 > l))
   1818           return 0;
   1819         out =
   1820           (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
   1821                            | ((uint8_t) ((unsigned int) l)));
   1822         decoded[w] = (char) out;
   1823       }
   1824     }
   1825     else
   1826       decoded[w] = chr;
   1827     ++r;
   1828     ++w;
   1829   }
   1830   return w;
   1831 #endif /* ! MHD_FAVOR_SMALL_CODE */
   1832 }
   1833 
   1834 
   1835 size_t
   1836 MHD_str_pct_decode_lenient_n_ (const char *pct_encoded,
   1837                                size_t pct_encoded_len,
   1838                                char *decoded,
   1839                                size_t buf_size,
   1840                                bool *broken_encoding)
   1841 {
   1842   size_t r;
   1843   size_t w;
   1844   r = 0;
   1845   w = 0;
   1846   if (NULL != broken_encoding)
   1847     *broken_encoding = false;
   1848 #ifndef MHD_FAVOR_SMALL_CODE
   1849   if (buf_size >= pct_encoded_len)
   1850   {
   1851     while (r < pct_encoded_len)
   1852     {
   1853       const char chr = pct_encoded[r];
   1854       if ('%' == chr)
   1855       {
   1856         if (2 > pct_encoded_len - r)
   1857         {
   1858           if (NULL != broken_encoding)
   1859             *broken_encoding = true;
   1860           decoded[w] = chr; /* Copy "as is" */
   1861         }
   1862         else
   1863         {
   1864           const char c1 = pct_encoded[++r];
   1865           const char c2 = pct_encoded[++r];
   1866           const int h = toxdigitvalue (c1);
   1867           const int l = toxdigitvalue (c2);
   1868           unsigned char out;
   1869           if ((0 > h) || (0 > l))
   1870           {
   1871             r -= 2;
   1872             if (NULL != broken_encoding)
   1873               *broken_encoding = true;
   1874             decoded[w] = chr; /* Copy "as is" */
   1875           }
   1876           else
   1877           {
   1878             out =
   1879               (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
   1880                                | ((uint8_t) ((unsigned int) l)));
   1881             decoded[w] = (char) out;
   1882           }
   1883         }
   1884       }
   1885       else
   1886         decoded[w] = chr;
   1887       ++r;
   1888       ++w;
   1889     }
   1890     return w;
   1891   }
   1892 #endif /* ! MHD_FAVOR_SMALL_CODE */
   1893   while (r < pct_encoded_len)
   1894   {
   1895     const char chr = pct_encoded[r];
   1896     if (w >= buf_size)
   1897       return 0;
   1898     if ('%' == chr)
   1899     {
   1900       if (2 > pct_encoded_len - r)
   1901       {
   1902         if (NULL != broken_encoding)
   1903           *broken_encoding = true;
   1904         decoded[w] = chr; /* Copy "as is" */
   1905       }
   1906       else
   1907       {
   1908         const char c1 = pct_encoded[++r];
   1909         const char c2 = pct_encoded[++r];
   1910         const int h = toxdigitvalue (c1);
   1911         const int l = toxdigitvalue (c2);
   1912         if ((0 > h) || (0 > l))
   1913         {
   1914           r -= 2;
   1915           if (NULL != broken_encoding)
   1916             *broken_encoding = true;
   1917           decoded[w] = chr; /* Copy "as is" */
   1918         }
   1919         else
   1920         {
   1921           unsigned char out;
   1922           out =
   1923             (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
   1924                              | ((uint8_t) ((unsigned int) l)));
   1925           decoded[w] = (char) out;
   1926         }
   1927       }
   1928     }
   1929     else
   1930       decoded[w] = chr;
   1931     ++r;
   1932     ++w;
   1933   }
   1934   return w;
   1935 }
   1936 
   1937 
   1938 size_t
   1939 MHD_str_pct_decode_in_place_strict_ (char *str)
   1940 {
   1941 #ifdef MHD_FAVOR_SMALL_CODE
   1942   size_t res;
   1943   bool broken;
   1944 
   1945   res = MHD_str_pct_decode_in_place_lenient_ (str, &broken);
   1946   if (broken)
   1947   {
   1948     res = 0;
   1949     str[0] = 0;
   1950   }
   1951   return res;
   1952 #else  /* ! MHD_FAVOR_SMALL_CODE */
   1953   size_t r;
   1954   size_t w;
   1955   r = 0;
   1956   w = 0;
   1957 
   1958   while (0 != str[r])
   1959   {
   1960     const char chr = str[r++];
   1961     if ('%' == chr)
   1962     {
   1963       const char d1 = str[r++];
   1964       if (0 == d1)
   1965         return 0;
   1966       else
   1967       {
   1968         const char d2 = str[r++];
   1969         if (0 == d2)
   1970           return 0;
   1971         else
   1972         {
   1973           const int h = toxdigitvalue (d1);
   1974           const int l = toxdigitvalue (d2);
   1975           unsigned char out;
   1976           if ((0 > h) || (0 > l))
   1977             return 0;
   1978           out =
   1979             (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
   1980                              | ((uint8_t) ((unsigned int) l)));
   1981           str[w++] = (char) out;
   1982         }
   1983       }
   1984     }
   1985     else
   1986       str[w++] = chr;
   1987   }
   1988   str[w] = 0;
   1989   return w;
   1990 #endif /* ! MHD_FAVOR_SMALL_CODE */
   1991 }
   1992 
   1993 
   1994 size_t
   1995 MHD_str_pct_decode_in_place_lenient_ (char *str,
   1996                                       bool *broken_encoding)
   1997 {
   1998 #ifdef MHD_FAVOR_SMALL_CODE
   1999   size_t len;
   2000   size_t res;
   2001 
   2002   len = strlen (str);
   2003   res = MHD_str_pct_decode_lenient_n_ (str, len, str, len, broken_encoding);
   2004   str[res] = 0;
   2005 
   2006   return res;
   2007 #else  /* ! MHD_FAVOR_SMALL_CODE */
   2008   size_t r;
   2009   size_t w;
   2010   if (NULL != broken_encoding)
   2011     *broken_encoding = false;
   2012   r = 0;
   2013   w = 0;
   2014   while (0 != str[r])
   2015   {
   2016     const char chr = str[r++];
   2017     if ('%' == chr)
   2018     {
   2019       const char d1 = str[r++];
   2020       if (0 == d1)
   2021       {
   2022         if (NULL != broken_encoding)
   2023           *broken_encoding = true;
   2024         str[w++] = chr; /* Copy "as is" */
   2025         str[w] = 0;
   2026         return w;
   2027       }
   2028       else
   2029       {
   2030         const char d2 = str[r++];
   2031         if (0 == d2)
   2032         {
   2033           if (NULL != broken_encoding)
   2034             *broken_encoding = true;
   2035           str[w++] = chr; /* Copy "as is" */
   2036           str[w++] = d1; /* Copy "as is" */
   2037           str[w] = 0;
   2038           return w;
   2039         }
   2040         else
   2041         {
   2042           const int h = toxdigitvalue (d1);
   2043           const int l = toxdigitvalue (d2);
   2044           unsigned char out;
   2045           if ((0 > h) || (0 > l))
   2046           {
   2047             if (NULL != broken_encoding)
   2048               *broken_encoding = true;
   2049             str[w++] = chr; /* Copy "as is" */
   2050             str[w++] = d1;
   2051             str[w++] = d2;
   2052             continue;
   2053           }
   2054           out =
   2055             (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
   2056                              | ((uint8_t) ((unsigned int) l)));
   2057           str[w++] = (char) out;
   2058           continue;
   2059         }
   2060       }
   2061     }
   2062     str[w++] = chr;
   2063   }
   2064   str[w] = 0;
   2065   return w;
   2066 #endif /* ! MHD_FAVOR_SMALL_CODE */
   2067 }
   2068 
   2069 
   2070 #ifdef DAUTH_SUPPORT
   2071 bool
   2072 MHD_str_equal_quoted_bin_n (const char *quoted,
   2073                             size_t quoted_len,
   2074                             const char *unquoted,
   2075                             size_t unquoted_len)
   2076 {
   2077   size_t i;
   2078   size_t j;
   2079   if (unquoted_len < quoted_len / 2)
   2080     return false;
   2081 
   2082   j = 0;
   2083   for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j)
   2084   {
   2085     if ('\\' == quoted[i])
   2086     {
   2087       i++; /* Advance to the next character */
   2088       if (quoted_len == i)
   2089         return false; /* No character after escaping backslash */
   2090     }
   2091     if (quoted[i] != unquoted[j])
   2092       return false; /* Different characters */
   2093   }
   2094   if ((quoted_len != i) || (unquoted_len != j))
   2095     return false; /* The strings have different length */
   2096 
   2097   return true;
   2098 }
   2099 
   2100 
   2101 bool
   2102 MHD_str_equal_caseless_quoted_bin_n (const char *quoted,
   2103                                      size_t quoted_len,
   2104                                      const char *unquoted,
   2105                                      size_t unquoted_len)
   2106 {
   2107   size_t i;
   2108   size_t j;
   2109   if (unquoted_len < quoted_len / 2)
   2110     return false;
   2111 
   2112   j = 0;
   2113   for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j)
   2114   {
   2115     if ('\\' == quoted[i])
   2116     {
   2117       i++; /* Advance to the next character */
   2118       if (quoted_len == i)
   2119         return false; /* No character after escaping backslash */
   2120     }
   2121     if (! charsequalcaseless (quoted[i], unquoted[j]))
   2122       return false; /* Different characters */
   2123   }
   2124   if ((quoted_len != i) || (unquoted_len != j))
   2125     return false; /* The strings have different length */
   2126 
   2127   return true;
   2128 }
   2129 
   2130 
   2131 size_t
   2132 MHD_str_unquote (const char *quoted,
   2133                  size_t quoted_len,
   2134                  char *result)
   2135 {
   2136   size_t r;
   2137   size_t w;
   2138 
   2139   r = 0;
   2140   w = 0;
   2141 
   2142   while (quoted_len > r)
   2143   {
   2144     if ('\\' == quoted[r])
   2145     {
   2146       ++r;
   2147       if (quoted_len == r)
   2148         return 0; /* Last backslash is not followed by char to unescape */
   2149     }
   2150     result[w++] = quoted[r++];
   2151   }
   2152   return w;
   2153 }
   2154 
   2155 
   2156 #endif /* DAUTH_SUPPORT */
   2157 
   2158 #if defined(DAUTH_SUPPORT) || defined(BAUTH_SUPPORT)
   2159 
   2160 size_t
   2161 MHD_str_quote (const char *unquoted,
   2162                size_t unquoted_len,
   2163                char *result,
   2164                size_t buf_size)
   2165 {
   2166   size_t r;
   2167   size_t w;
   2168 
   2169   r = 0;
   2170   w = 0;
   2171 
   2172 #ifndef MHD_FAVOR_SMALL_CODE
   2173   if (unquoted_len * 2 <= buf_size)
   2174   {
   2175     /* Fast loop: the output will fit the buffer with any input string content */
   2176     while (unquoted_len > r)
   2177     {
   2178       const char chr = unquoted[r++];
   2179       if (('\\' == chr) || ('\"' == chr))
   2180         result[w++] = '\\'; /* Escape current char */
   2181       result[w++] = chr;
   2182     }
   2183   }
   2184   else
   2185   {
   2186     if (unquoted_len > buf_size)
   2187       return 0; /* Quick fail: the output buffer is too small */
   2188 #else  /* MHD_FAVOR_SMALL_CODE */
   2189   if (1)
   2190   {
   2191 #endif /* MHD_FAVOR_SMALL_CODE */
   2192 
   2193     while (unquoted_len > r)
   2194     {
   2195       if (buf_size <= w)
   2196         return 0; /* The output buffer is too small */
   2197       else
   2198       {
   2199         const char chr = unquoted[r++];
   2200         if (('\\' == chr) || ('\"' == chr))
   2201         {
   2202           result[w++] = '\\'; /* Escape current char */
   2203           if (buf_size <= w)
   2204             return 0; /* The output buffer is too small */
   2205         }
   2206         result[w++] = chr;
   2207       }
   2208     }
   2209   }
   2210 
   2211   mhd_assert (w >= r);
   2212   mhd_assert (w <= r * 2);
   2213   return w;
   2214 }
   2215 
   2216 
   2217 #endif /* DAUTH_SUPPORT || BAUTH_SUPPORT */
   2218 
   2219 #ifdef BAUTH_SUPPORT
   2220 
   2221 /*
   2222  * MHD_BASE64_FUNC_VERSION
   2223  * 1 = smallest,
   2224  * 2 = medium,
   2225  * 3 = fastest
   2226  */
   2227 #ifndef MHD_BASE64_FUNC_VERSION
   2228 #ifdef MHD_FAVOR_SMALL_CODE
   2229 #define MHD_BASE64_FUNC_VERSION 1
   2230 #else  /* ! MHD_FAVOR_SMALL_CODE */
   2231 #define MHD_BASE64_FUNC_VERSION 3
   2232 #endif /* ! MHD_FAVOR_SMALL_CODE */
   2233 #endif /* ! MHD_BASE64_FUNC_VERSION */
   2234 
   2235 #if MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3
   2236 #error Wrong MHD_BASE64_FUNC_VERSION value
   2237 #endif /* MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 */
   2238 
   2239 #if MHD_BASE64_FUNC_VERSION == 3
   2240 #define MHD_base64_map_type_ int
   2241 #else  /* MHD_BASE64_FUNC_VERSION < 3 */
   2242 #define MHD_base64_map_type_ int8_t
   2243 #endif /* MHD_BASE64_FUNC_VERSION < 3 */
   2244 
   2245 #if MHD_BASE64_FUNC_VERSION == 1
   2246 static MHD_base64_map_type_
   2247 base64_char_to_value_ (uint8_t c)
   2248 {
   2249   if ('Z' >= c)
   2250   {
   2251     if ('A' <= c)
   2252       return (MHD_base64_map_type_) ((c - 'A') + 0);
   2253     if ('0' <= c)
   2254     {
   2255       if ('9' >= c)
   2256         return (MHD_base64_map_type_) ((c - '0') + 52);
   2257       if ('=' == c)
   2258         return -2;
   2259       return -1;
   2260     }
   2261     if ('+' == c)
   2262       return 62;
   2263     if ('/' == c)
   2264       return 63;
   2265     return -1;
   2266   }
   2267   if (('z' >= c) && ('a' <= c))
   2268     return (MHD_base64_map_type_) ((c - 'a') + 26);
   2269   return -1;
   2270 }
   2271 
   2272 
   2273 #endif /* MHD_BASE64_FUNC_VERSION == 1 */
   2274 
   2275 
   2276 MHD_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE_
   2277 
   2278 
   2279 size_t
   2280 MHD_base64_to_bin_n (const char *base64,
   2281                      size_t base64_len,
   2282                      void *bin,
   2283                      size_t bin_size)
   2284 {
   2285 #if MHD_BASE64_FUNC_VERSION >= 2
   2286   static const MHD_base64_map_type_ map[] = {
   2287     /* -1 = invalid char, -2 = padding
   2288     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   2289     NUL,  SOH,  STX,  ETX,  EOT,  ENQ,  ACK,  BEL,  */
   2290     -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   2291     /*
   2292     0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
   2293     BS,   HT,   LF,   VT,   FF,   CR,   SO,   SI,   */
   2294     -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   2295     /*
   2296     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
   2297     DLE,  DC1,  DC2,  DC3,  DC4,  NAK,  SYN,  ETB,  */
   2298     -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   2299     /*
   2300     0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
   2301     CAN,  EM,   SUB,  ESC,  FS,   GS,   RS,   US,   */
   2302     -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   2303     /*
   2304     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
   2305     ' ',  '!',  '"',  '#',  '$',  '%',  '&',  '\'', */
   2306     -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   2307     /*
   2308     0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
   2309     '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',  */
   2310     -1,   -1,   -1,   62,   -1,   -1,   -1,   63,
   2311     /*
   2312     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
   2313     '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  */
   2314     52,   53,   54,   55,   56,   57,   58,   59,
   2315     /*
   2316     0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
   2317     '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',  */
   2318     60,   61,   -1,   -1,   -1,   -2,   -1,   -1,
   2319     /*
   2320     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
   2321     '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',  */
   2322     -1,    0,    1,    2,    3,    4,    5,    6,
   2323     /*
   2324     0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
   2325     'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',  */
   2326     7,     8,    9,   10,   11,   12,   13,   14,
   2327     /*
   2328     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
   2329     'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  */
   2330     15,   16,   17,   18,   19,   20,   21,   22,
   2331     /*
   2332      0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
   2333     'X',  'Y',  'Z',  '[',  '\',  ']',  '^',  '_',  */
   2334     23,   24,   25,   -1,   -1,   -1,   -1,   -1,
   2335     /*
   2336     0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
   2337     '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',  */
   2338     -1,   26,   27,   28,   29,   30,   31,   32,
   2339     /*
   2340     0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
   2341     'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',  */
   2342     33,   34,   35,   36,   37,   38,   39,   40,
   2343     /*
   2344     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
   2345     'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  */
   2346     41,   42,   43,   44,   45,   46,   47,   48,
   2347     /*
   2348     0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
   2349     'x',  'y',  'z',  '{',  '|',  '}',  '~',  DEL,  */
   2350     49,   50,   51,   -1,   -1,   -1,   -1,   -1
   2351 
   2352 #if MHD_BASE64_FUNC_VERSION == 3
   2353     ,
   2354     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 80..8F */
   2355     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 90..9F */
   2356     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* A0..AF */
   2357     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* B0..BF */
   2358     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* C0..CF */
   2359     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* D0..DF */
   2360     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* E0..EF */
   2361     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* F0..FF */
   2362 #endif /* ! MHD_BASE64_FUNC_VERSION == 3 */
   2363   };
   2364 #define base64_char_to_value_(c) map[(c)]
   2365 #endif /* MHD_BASE64_FUNC_VERSION >= 2 */
   2366   const uint8_t *const in = (const uint8_t *) base64;
   2367   uint8_t *const out = (uint8_t *) bin;
   2368   size_t i;
   2369   size_t j;
   2370   if (0 == base64_len)
   2371     return 0;  /* Nothing to decode */
   2372   if (0 != base64_len % 4)
   2373     return 0;  /* Wrong input length */
   2374   if (base64_len / 4 * 3 - 2 > bin_size)
   2375     return 0;
   2376 
   2377   j = 0;
   2378   for (i = 0; i < (base64_len - 4); i += 4)
   2379   {
   2380 #if MHD_BASE64_FUNC_VERSION == 2
   2381     if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3])))
   2382       return 0;
   2383 #endif /* MHD_BASE64_FUNC_VERSION == 2 */
   2384     if (1)
   2385     {
   2386       const MHD_base64_map_type_ v1 = base64_char_to_value_ (in[i + 0]);
   2387       const MHD_base64_map_type_ v2 = base64_char_to_value_ (in[i + 1]);
   2388       const MHD_base64_map_type_ v3 = base64_char_to_value_ (in[i + 2]);
   2389       const MHD_base64_map_type_ v4 = base64_char_to_value_ (in[i + 3]);
   2390       if ((0 > v1) || (0 > v2) || (0 > v3) || (0 > v4))
   2391         return 0;
   2392       out[j + 0] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2))
   2393                               | ((uint8_t) (((uint8_t) v2) >> 4)));
   2394       out[j + 1] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4))
   2395                               | ((uint8_t) (((uint8_t) v3) >> 2)));
   2396       out[j + 2] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6))
   2397                               | ((uint8_t) v4));
   2398     }
   2399     j += 3;
   2400   }
   2401 #if MHD_BASE64_FUNC_VERSION == 2
   2402   if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3])))
   2403     return 0;
   2404 #endif /* MHD_BASE64_FUNC_VERSION == 2 */
   2405   if (1)
   2406   { /* The last four chars block */
   2407     const MHD_base64_map_type_ v1 = base64_char_to_value_ (in[i + 0]);
   2408     const MHD_base64_map_type_ v2 = base64_char_to_value_ (in[i + 1]);
   2409     const MHD_base64_map_type_ v3 = base64_char_to_value_ (in[i + 2]);
   2410     const MHD_base64_map_type_ v4 = base64_char_to_value_ (in[i + 3]);
   2411     if ((0 > v1) || (0 > v2))
   2412       return 0; /* Invalid char or padding at first two positions */
   2413     mhd_assert (j < bin_size);
   2414     out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2))
   2415                           | ((uint8_t) (((uint8_t) v2) >> 4)));
   2416     if (0 > v3)
   2417     { /* Third char is either padding or invalid */
   2418       if ((-2 != v3) || (-2 != v4))
   2419         return 0;  /* Both two last chars must be padding */
   2420       if (0 != (uint8_t) (((uint8_t) v2) << 4))
   2421         return 0;  /* Wrong last char */
   2422       return j;
   2423     }
   2424     if (j >= bin_size)
   2425       return 0; /* Not enough space */
   2426     out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4))
   2427                           | ((uint8_t) (((uint8_t) v3) >> 2)));
   2428     if (0 > v4)
   2429     { /* Fourth char is either padding or invalid */
   2430       if (-2 != v4)
   2431         return 0;  /* The char must be padding */
   2432       if (0 != (uint8_t) (((uint8_t) v3) << 6))
   2433         return 0;  /* Wrong last char */
   2434       return j;
   2435     }
   2436     if (j >= bin_size)
   2437       return 0; /* Not enough space */
   2438     out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6))
   2439                           | ((uint8_t) v4));
   2440   }
   2441   return j;
   2442 #if MHD_BASE64_FUNC_VERSION >= 2
   2443 #undef base64_char_to_value_
   2444 #endif /* MHD_BASE64_FUNC_VERSION >= 2 */
   2445 }
   2446 
   2447 
   2448 MHD_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE_
   2449 
   2450 
   2451 #undef MHD_base64_map_type_
   2452 
   2453 #endif /* BAUTH_SUPPORT */