libmicrohttpd

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

mhd_str.c (65785B)


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