GNU libmicrohttpd  1.0.1
mhd_str.c
Go to the documentation of this file.
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 
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 INLINE_FUNC
46 #define INLINE_FUNC 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 INLINE_FUNC
56 
57 #if 0 /* Disable unused functions. */
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 
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. */
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 
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. */
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 
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. */
159 _MHD_static_inline char
160 toasciilower (char c)
161 {
162  return isasciiupper (c) ? (c - 'A' + 'a') : c;
163 }
164 
165 
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_() */
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 
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 
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 
555 #define isasciilower(c) (((char) (c)) >= 'a' && ((char) (c)) <= 'z')
556 
557 
565 #define isasciiupper(c) (((char) (c)) >= 'A' && ((char) (c)) <= 'Z')
566 
567 
575 #define isasciialpha(c) (isasciilower (c) || isasciiupper (c))
576 
577 
585 #define isasciidigit(c) (((char) (c)) >= '0' && ((char) (c)) <= '9')
586 
587 
595 #define isasciixdigit(c) (isasciidigit ((c)) || \
596  (((char) (c)) >= 'A' && ((char) (c)) <= 'F') || \
597  (((char) (c)) >= 'a' && ((char) (c)) <= 'f') )
598 
599 
607 #define isasciialnum(c) (isasciialpha (c) || isasciidigit (c))
608 
609 
619 #define toasciilower(c) ((isasciiupper (c)) ? (((char) (c)) - 'A' + 'a') : \
620  ((char) (c)))
621 
622 
632 #define toasciiupper(c) ((isasciilower (c)) ? (((char) (c)) - 'a' + 'A') : \
633  ((char) (c)))
634 
635 
642 #define todigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \
643  (int) (-1))
644 
645 
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 
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 /* !INLINE_FUNC */
672 
673 
674 #ifndef MHD_FAVOR_SMALL_CODE
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 
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 
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 
781 bool
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 
856 bool
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;
865  char *s2;
866  size_t t_pos;
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;
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 
1032 bool
1034  size_t *str_len,
1035  const char *const tokens,
1036  const size_t tokens_len)
1037 {
1038  const char *const t = tokens;
1039  size_t pt;
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;
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;
1100  size_t pw;
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 
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 
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 
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 
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 
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 
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 
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;
1521  int digit_pos = 8;
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;
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;
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
1630  uint8_t min_digits,
1631  char *buf,
1632  size_t buf_size)
1633 {
1634  size_t pos;
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 int l = toxdigitvalue (hex[r++]);
1726  if (0 > l)
1727  return 0;
1728  out[w++] = (uint8_t) ((unsigned int) l);
1729  }
1730  while (r < len)
1731  {
1732  const int h = toxdigitvalue (hex[r++]);
1733  const int l = toxdigitvalue (hex[r++]);
1734  if ((0 > h) || (0 > l))
1735  return 0;
1736  out[w++] = (uint8_t) ( ((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1737  | ((uint8_t) ((unsigned int) l)) );
1738  }
1739  mhd_assert (len == r);
1740  mhd_assert ((len + 1) / 2 == w);
1741  return w;
1742 }
1743 
1744 
1745 size_t
1746 MHD_str_pct_decode_strict_n_ (const char *pct_encoded,
1747  size_t pct_encoded_len,
1748  char *decoded,
1749  size_t buf_size)
1750 {
1751 #ifdef MHD_FAVOR_SMALL_CODE
1752  bool broken;
1753  size_t res;
1754 
1755  res = MHD_str_pct_decode_lenient_n_ (pct_encoded, pct_encoded_len, decoded,
1756  buf_size, &broken);
1757  if (broken)
1758  return 0;
1759  return res;
1760 #else /* ! MHD_FAVOR_SMALL_CODE */
1761  size_t r;
1762  size_t w;
1763  r = 0;
1764  w = 0;
1765 
1766  if (buf_size >= pct_encoded_len)
1767  {
1768  while (r < pct_encoded_len)
1769  {
1770  const char chr = pct_encoded[r];
1771  if ('%' == chr)
1772  {
1773  if (2 > pct_encoded_len - r)
1774  return 0;
1775  else
1776  {
1777  const int h = toxdigitvalue (pct_encoded[++r]);
1778  const int l = toxdigitvalue (pct_encoded[++r]);
1779  unsigned char out;
1780  if ((0 > h) || (0 > l))
1781  return 0;
1782  out =
1783  (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1784  | ((uint8_t) ((unsigned int) l)));
1785  decoded[w] = (char) out;
1786  }
1787  }
1788  else
1789  decoded[w] = chr;
1790  ++r;
1791  ++w;
1792  }
1793  return w;
1794  }
1795 
1796  while (r < pct_encoded_len)
1797  {
1798  const char chr = pct_encoded[r];
1799  if (w >= buf_size)
1800  return 0;
1801  if ('%' == chr)
1802  {
1803  if (2 > pct_encoded_len - r)
1804  return 0;
1805  else
1806  {
1807  const int h = toxdigitvalue (pct_encoded[++r]);
1808  const int l = toxdigitvalue (pct_encoded[++r]);
1809  unsigned char out;
1810  if ((0 > h) || (0 > l))
1811  return 0;
1812  out =
1813  (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1814  | ((uint8_t) ((unsigned int) l)));
1815  decoded[w] = (char) out;
1816  }
1817  }
1818  else
1819  decoded[w] = chr;
1820  ++r;
1821  ++w;
1822  }
1823  return w;
1824 #endif /* ! MHD_FAVOR_SMALL_CODE */
1825 }
1826 
1827 
1828 size_t
1829 MHD_str_pct_decode_lenient_n_ (const char *pct_encoded,
1830  size_t pct_encoded_len,
1831  char *decoded,
1832  size_t buf_size,
1833  bool *broken_encoding)
1834 {
1835  size_t r;
1836  size_t w;
1837  r = 0;
1838  w = 0;
1839  if (NULL != broken_encoding)
1840  *broken_encoding = false;
1841 #ifndef MHD_FAVOR_SMALL_CODE
1842  if (buf_size >= pct_encoded_len)
1843  {
1844  while (r < pct_encoded_len)
1845  {
1846  const char chr = pct_encoded[r];
1847  if ('%' == chr)
1848  {
1849  if (2 > pct_encoded_len - r)
1850  {
1851  if (NULL != broken_encoding)
1852  *broken_encoding = true;
1853  decoded[w] = chr; /* Copy "as is" */
1854  }
1855  else
1856  {
1857  const int h = toxdigitvalue (pct_encoded[++r]);
1858  const int l = toxdigitvalue (pct_encoded[++r]);
1859  unsigned char out;
1860  if ((0 > h) || (0 > l))
1861  {
1862  r -= 2;
1863  if (NULL != broken_encoding)
1864  *broken_encoding = true;
1865  decoded[w] = chr; /* Copy "as is" */
1866  }
1867  else
1868  {
1869  out =
1870  (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1871  | ((uint8_t) ((unsigned int) l)));
1872  decoded[w] = (char) out;
1873  }
1874  }
1875  }
1876  else
1877  decoded[w] = chr;
1878  ++r;
1879  ++w;
1880  }
1881  return w;
1882  }
1883 #endif /* ! MHD_FAVOR_SMALL_CODE */
1884  while (r < pct_encoded_len)
1885  {
1886  const char chr = pct_encoded[r];
1887  if (w >= buf_size)
1888  return 0;
1889  if ('%' == chr)
1890  {
1891  if (2 > pct_encoded_len - r)
1892  {
1893  if (NULL != broken_encoding)
1894  *broken_encoding = true;
1895  decoded[w] = chr; /* Copy "as is" */
1896  }
1897  else
1898  {
1899  const int h = toxdigitvalue (pct_encoded[++r]);
1900  const int l = toxdigitvalue (pct_encoded[++r]);
1901  if ((0 > h) || (0 > l))
1902  {
1903  r -= 2;
1904  if (NULL != broken_encoding)
1905  *broken_encoding = true;
1906  decoded[w] = chr; /* Copy "as is" */
1907  }
1908  else
1909  {
1910  unsigned char out;
1911  out =
1912  (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1913  | ((uint8_t) ((unsigned int) l)));
1914  decoded[w] = (char) out;
1915  }
1916  }
1917  }
1918  else
1919  decoded[w] = chr;
1920  ++r;
1921  ++w;
1922  }
1923  return w;
1924 }
1925 
1926 
1927 size_t
1929 {
1930 #ifdef MHD_FAVOR_SMALL_CODE
1931  size_t res;
1932  bool broken;
1933 
1934  res = MHD_str_pct_decode_in_place_lenient_ (str, &broken);
1935  if (broken)
1936  {
1937  res = 0;
1938  str[0] = 0;
1939  }
1940  return res;
1941 #else /* ! MHD_FAVOR_SMALL_CODE */
1942  size_t r;
1943  size_t w;
1944  r = 0;
1945  w = 0;
1946 
1947  while (0 != str[r])
1948  {
1949  const char chr = str[r++];
1950  if ('%' == chr)
1951  {
1952  const char d1 = str[r++];
1953  if (0 == d1)
1954  return 0;
1955  else
1956  {
1957  const char d2 = str[r++];
1958  if (0 == d2)
1959  return 0;
1960  else
1961  {
1962  const int h = toxdigitvalue (d1);
1963  const int l = toxdigitvalue (d2);
1964  unsigned char out;
1965  if ((0 > h) || (0 > l))
1966  return 0;
1967  out =
1968  (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1969  | ((uint8_t) ((unsigned int) l)));
1970  str[w++] = (char) out;
1971  }
1972  }
1973  }
1974  else
1975  str[w++] = chr;
1976  }
1977  str[w] = 0;
1978  return w;
1979 #endif /* ! MHD_FAVOR_SMALL_CODE */
1980 }
1981 
1982 
1983 size_t
1985  bool *broken_encoding)
1986 {
1987 #ifdef MHD_FAVOR_SMALL_CODE
1988  size_t len;
1989  size_t res;
1990 
1991  len = strlen (str);
1992  res = MHD_str_pct_decode_lenient_n_ (str, len, str, len, broken_encoding);
1993  str[res] = 0;
1994 
1995  return res;
1996 #else /* ! MHD_FAVOR_SMALL_CODE */
1997  size_t r;
1998  size_t w;
1999  if (NULL != broken_encoding)
2000  *broken_encoding = false;
2001  r = 0;
2002  w = 0;
2003  while (0 != str[r])
2004  {
2005  const char chr = str[r++];
2006  if ('%' == chr)
2007  {
2008  const char d1 = str[r++];
2009  if (0 == d1)
2010  {
2011  if (NULL != broken_encoding)
2012  *broken_encoding = true;
2013  str[w++] = chr; /* Copy "as is" */
2014  str[w] = 0;
2015  return w;
2016  }
2017  else
2018  {
2019  const char d2 = str[r++];
2020  if (0 == d2)
2021  {
2022  if (NULL != broken_encoding)
2023  *broken_encoding = true;
2024  str[w++] = chr; /* Copy "as is" */
2025  str[w++] = d1; /* Copy "as is" */
2026  str[w] = 0;
2027  return w;
2028  }
2029  else
2030  {
2031  const int h = toxdigitvalue (d1);
2032  const int l = toxdigitvalue (d2);
2033  unsigned char out;
2034  if ((0 > h) || (0 > l))
2035  {
2036  if (NULL != broken_encoding)
2037  *broken_encoding = true;
2038  str[w++] = chr; /* Copy "as is" */
2039  str[w++] = d1;
2040  str[w++] = d2;
2041  continue;
2042  }
2043  out =
2044  (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
2045  | ((uint8_t) ((unsigned int) l)));
2046  str[w++] = (char) out;
2047  continue;
2048  }
2049  }
2050  }
2051  str[w++] = chr;
2052  }
2053  str[w] = 0;
2054  return w;
2055 #endif /* ! MHD_FAVOR_SMALL_CODE */
2056 }
2057 
2058 
2059 #ifdef DAUTH_SUPPORT
2060 bool
2061 MHD_str_equal_quoted_bin_n (const char *quoted,
2062  size_t quoted_len,
2063  const char *unquoted,
2064  size_t unquoted_len)
2065 {
2066  size_t i;
2067  size_t j;
2068  if (unquoted_len < quoted_len / 2)
2069  return false;
2070 
2071  j = 0;
2072  for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j)
2073  {
2074  if ('\\' == quoted[i])
2075  {
2076  i++; /* Advance to the next character */
2077  if (quoted_len == i)
2078  return false; /* No character after escaping backslash */
2079  }
2080  if (quoted[i] != unquoted[j])
2081  return false; /* Different characters */
2082  }
2083  if ((quoted_len != i) || (unquoted_len != j))
2084  return false; /* The strings have different length */
2085 
2086  return true;
2087 }
2088 
2089 
2090 bool
2091 MHD_str_equal_caseless_quoted_bin_n (const char *quoted,
2092  size_t quoted_len,
2093  const char *unquoted,
2094  size_t unquoted_len)
2095 {
2096  size_t i;
2097  size_t j;
2098  if (unquoted_len < quoted_len / 2)
2099  return false;
2100 
2101  j = 0;
2102  for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j)
2103  {
2104  if ('\\' == quoted[i])
2105  {
2106  i++; /* Advance to the next character */
2107  if (quoted_len == i)
2108  return false; /* No character after escaping backslash */
2109  }
2110  if (! charsequalcaseless (quoted[i], unquoted[j]))
2111  return false; /* Different characters */
2112  }
2113  if ((quoted_len != i) || (unquoted_len != j))
2114  return false; /* The strings have different length */
2115 
2116  return true;
2117 }
2118 
2119 
2120 size_t
2121 MHD_str_unquote (const char *quoted,
2122  size_t quoted_len,
2123  char *result)
2124 {
2125  size_t r;
2126  size_t w;
2127 
2128  r = 0;
2129  w = 0;
2130 
2131  while (quoted_len > r)
2132  {
2133  if ('\\' == quoted[r])
2134  {
2135  ++r;
2136  if (quoted_len == r)
2137  return 0; /* Last backslash is not followed by char to unescape */
2138  }
2139  result[w++] = quoted[r++];
2140  }
2141  return w;
2142 }
2143 
2144 
2145 #endif /* DAUTH_SUPPORT */
2146 
2147 #if defined(DAUTH_SUPPORT) || defined(BAUTH_SUPPORT)
2148 
2149 size_t
2150 MHD_str_quote (const char *unquoted,
2151  size_t unquoted_len,
2152  char *result,
2153  size_t buf_size)
2154 {
2155  size_t r;
2156  size_t w;
2157 
2158  r = 0;
2159  w = 0;
2160 
2161 #ifndef MHD_FAVOR_SMALL_CODE
2162  if (unquoted_len * 2 <= buf_size)
2163  {
2164  /* Fast loop: the output will fit the buffer with any input string content */
2165  while (unquoted_len > r)
2166  {
2167  const char chr = unquoted[r++];
2168  if (('\\' == chr) || ('\"' == chr))
2169  result[w++] = '\\'; /* Escape current char */
2170  result[w++] = chr;
2171  }
2172  }
2173  else
2174  {
2175  if (unquoted_len > buf_size)
2176  return 0; /* Quick fail: the output buffer is too small */
2177 #else /* MHD_FAVOR_SMALL_CODE */
2178  if (1)
2179  {
2180 #endif /* MHD_FAVOR_SMALL_CODE */
2181 
2182  while (unquoted_len > r)
2183  {
2184  if (buf_size <= w)
2185  return 0; /* The output buffer is too small */
2186  else
2187  {
2188  const char chr = unquoted[r++];
2189  if (('\\' == chr) || ('\"' == chr))
2190  {
2191  result[w++] = '\\'; /* Escape current char */
2192  if (buf_size <= w)
2193  return 0; /* The output buffer is too small */
2194  }
2195  result[w++] = chr;
2196  }
2197  }
2198  }
2199 
2200  mhd_assert (w >= r);
2201  mhd_assert (w <= r * 2);
2202  return w;
2203 }
2204 
2205 
2206 #endif /* DAUTH_SUPPORT || BAUTH_SUPPORT */
2207 
2208 #ifdef BAUTH_SUPPORT
2209 
2210 /*
2211  * MHD_BASE64_FUNC_VERSION
2212  * 1 = smallest,
2213  * 2 = medium,
2214  * 3 = fastest
2215  */
2216 #ifndef MHD_BASE64_FUNC_VERSION
2217 #ifdef MHD_FAVOR_SMALL_CODE
2218 #define MHD_BASE64_FUNC_VERSION 1
2219 #else /* ! MHD_FAVOR_SMALL_CODE */
2220 #define MHD_BASE64_FUNC_VERSION 3
2221 #endif /* ! MHD_FAVOR_SMALL_CODE */
2222 #endif /* ! MHD_BASE64_FUNC_VERSION */
2223 
2224 #if MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3
2225 #error Wrong MHD_BASE64_FUNC_VERSION value
2226 #endif /* MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 */
2227 
2228 #if MHD_BASE64_FUNC_VERSION == 3
2229 #define MHD_base64_map_type_ int
2230 #else /* MHD_BASE64_FUNC_VERSION < 3 */
2231 #define MHD_base64_map_type_ int8_t
2232 #endif /* MHD_BASE64_FUNC_VERSION < 3 */
2233 
2234 #if MHD_BASE64_FUNC_VERSION == 1
2235 static MHD_base64_map_type_
2236 base64_char_to_value_ (uint8_t c)
2237 {
2238  if ('Z' >= c)
2239  {
2240  if ('A' <= c)
2241  return (MHD_base64_map_type_) ((c - 'A') + 0);
2242  if ('0' <= c)
2243  {
2244  if ('9' >= c)
2245  return (MHD_base64_map_type_) ((c - '0') + 52);
2246  if ('=' == c)
2247  return -2;
2248  return -1;
2249  }
2250  if ('+' == c)
2251  return 62;
2252  if ('/' == c)
2253  return 63;
2254  return -1;
2255  }
2256  if (('z' >= c) && ('a' <= c))
2257  return (MHD_base64_map_type_) ((c - 'a') + 26);
2258  return -1;
2259 }
2260 
2261 
2262 #endif /* MHD_BASE64_FUNC_VERSION == 1 */
2263 
2264 
2266 
2267 
2268 size_t
2269 MHD_base64_to_bin_n (const char *base64,
2270  size_t base64_len,
2271  void *bin,
2272  size_t bin_size)
2273 {
2274 #if MHD_BASE64_FUNC_VERSION >= 2
2275  static const MHD_base64_map_type_ map[] = {
2276  /* -1 = invalid char, -2 = padding
2277  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
2278  NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, */
2279  -1, -1, -1, -1, -1, -1, -1, -1,
2280  /*
2281  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
2282  BS, HT, LF, VT, FF, CR, SO, SI, */
2283  -1, -1, -1, -1, -1, -1, -1, -1,
2284  /*
2285  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
2286  DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, */
2287  -1, -1, -1, -1, -1, -1, -1, -1,
2288  /*
2289  0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
2290  CAN, EM, SUB, ESC, FS, GS, RS, US, */
2291  -1, -1, -1, -1, -1, -1, -1, -1,
2292  /*
2293  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
2294  ' ', '!', '"', '#', '$', '%', '&', '\'', */
2295  -1, -1, -1, -1, -1, -1, -1, -1,
2296  /*
2297  0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
2298  '(', ')', '*', '+', ',', '-', '.', '/', */
2299  -1, -1, -1, 62, -1, -1, -1, 63,
2300  /*
2301  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
2302  '0', '1', '2', '3', '4', '5', '6', '7', */
2303  52, 53, 54, 55, 56, 57, 58, 59,
2304  /*
2305  0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
2306  '8', '9', ':', ';', '<', '=', '>', '?', */
2307  60, 61, -1, -1, -1, -2, -1, -1,
2308  /*
2309  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
2310  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */
2311  -1, 0, 1, 2, 3, 4, 5, 6,
2312  /*
2313  0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
2314  'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */
2315  7, 8, 9, 10, 11, 12, 13, 14,
2316  /*
2317  0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
2318  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */
2319  15, 16, 17, 18, 19, 20, 21, 22,
2320  /*
2321  0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
2322  'X', 'Y', 'Z', '[', '\', ']', '^', '_', */
2323  23, 24, 25, -1, -1, -1, -1, -1,
2324  /*
2325  0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
2326  '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */
2327  -1, 26, 27, 28, 29, 30, 31, 32,
2328  /*
2329  0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
2330  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */
2331  33, 34, 35, 36, 37, 38, 39, 40,
2332  /*
2333  0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
2334  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */
2335  41, 42, 43, 44, 45, 46, 47, 48,
2336  /*
2337  0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
2338  'x', 'y', 'z', '{', '|', '}', '~', DEL, */
2339  49, 50, 51, -1, -1, -1, -1, -1
2340 
2341 #if MHD_BASE64_FUNC_VERSION == 3
2342  ,
2343  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80..8F */
2344  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90..9F */
2345  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0..AF */
2346  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0..BF */
2347  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0..CF */
2348  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0..DF */
2349  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0..EF */
2350  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* F0..FF */
2351 #endif /* ! MHD_BASE64_FUNC_VERSION == 3 */
2352  };
2353 #define base64_char_to_value_(c) map[(c)]
2354 #endif /* MHD_BASE64_FUNC_VERSION >= 2 */
2355  const uint8_t *const in = (const uint8_t *) base64;
2356  uint8_t *const out = (uint8_t *) bin;
2357  size_t i;
2358  size_t j;
2359  if (0 == base64_len)
2360  return 0; /* Nothing to decode */
2361  if (0 != base64_len % 4)
2362  return 0; /* Wrong input length */
2363  if (base64_len / 4 * 3 - 2 > bin_size)
2364  return 0;
2365 
2366  j = 0;
2367  for (i = 0; i < (base64_len - 4); i += 4)
2368  {
2369 #if MHD_BASE64_FUNC_VERSION == 2
2370  if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3])))
2371  return 0;
2372 #endif /* MHD_BASE64_FUNC_VERSION == 2 */
2373  if (1)
2374  {
2375  const MHD_base64_map_type_ v1 = base64_char_to_value_ (in[i + 0]);
2376  const MHD_base64_map_type_ v2 = base64_char_to_value_ (in[i + 1]);
2377  const MHD_base64_map_type_ v3 = base64_char_to_value_ (in[i + 2]);
2378  const MHD_base64_map_type_ v4 = base64_char_to_value_ (in[i + 3]);
2379  if ((0 > v1) || (0 > v2) || (0 > v3) || (0 > v4))
2380  return 0;
2381  out[j + 0] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2))
2382  | ((uint8_t) (((uint8_t) v2) >> 4)));
2383  out[j + 1] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4))
2384  | ((uint8_t) (((uint8_t) v3) >> 2)));
2385  out[j + 2] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6))
2386  | ((uint8_t) v4));
2387  }
2388  j += 3;
2389  }
2390 #if MHD_BASE64_FUNC_VERSION == 2
2391  if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3])))
2392  return 0;
2393 #endif /* MHD_BASE64_FUNC_VERSION == 2 */
2394  if (1)
2395  { /* The last four chars block */
2396  const MHD_base64_map_type_ v1 = base64_char_to_value_ (in[i + 0]);
2397  const MHD_base64_map_type_ v2 = base64_char_to_value_ (in[i + 1]);
2398  const MHD_base64_map_type_ v3 = base64_char_to_value_ (in[i + 2]);
2399  const MHD_base64_map_type_ v4 = base64_char_to_value_ (in[i + 3]);
2400  if ((0 > v1) || (0 > v2))
2401  return 0; /* Invalid char or padding at first two positions */
2402  mhd_assert (j < bin_size);
2403  out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2))
2404  | ((uint8_t) (((uint8_t) v2) >> 4)));
2405  if (0 > v3)
2406  { /* Third char is either padding or invalid */
2407  if ((-2 != v3) || (-2 != v4))
2408  return 0; /* Both two last chars must be padding */
2409  if (0 != (uint8_t) (((uint8_t) v2) << 4))
2410  return 0; /* Wrong last char */
2411  return j;
2412  }
2413  if (j >= bin_size)
2414  return 0; /* Not enough space */
2415  out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4))
2416  | ((uint8_t) (((uint8_t) v3) >> 2)));
2417  if (0 > v4)
2418  { /* Fourth char is either padding or invalid */
2419  if (-2 != v4)
2420  return 0; /* The char must be padding */
2421  if (0 != (uint8_t) (((uint8_t) v3) << 6))
2422  return 0; /* Wrong last char */
2423  return j;
2424  }
2425  if (j >= bin_size)
2426  return 0; /* Not enough space */
2427  out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6))
2428  | ((uint8_t) v4));
2429  }
2430  return j;
2431 #if MHD_BASE64_FUNC_VERSION >= 2
2432 #undef base64_char_to_value_
2433 #endif /* MHD_BASE64_FUNC_VERSION >= 2 */
2434 }
2435 
2436 
2438 
2439 
2440 #undef MHD_base64_map_type_
2441 
2442 #endif /* BAUTH_SUPPORT */
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
#define UINT64_MAX
Definition: mhd_limits.h:81
#define UINT32_MAX
Definition: mhd_limits.h:73
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:346
size_t MHD_strx_to_uint32_(const char *str, uint32_t *out_val)
Definition: mhd_str.c:558
size_t MHD_str_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:515
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:692
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
Definition: mhd_str.c:378
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:473
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:412
size_t MHD_strx_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:646
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition: mhd_str.c:605
#define NULL
Definition: reason_phrase.c:30
#define MHD_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE_
Definition: mhd_options.h:176
#define MHD_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE_
Definition: mhd_options.h:177
macros for mhd_assert()
limits values definitions
#define SSIZE_MAX
Definition: mhd_limits.h:121
size_t MHD_bin_to_hex(const void *bin, size_t size, char *hex)
Definition: mhd_str.c:1676
size_t MHD_str_pct_decode_strict_n_(const char *pct_encoded, size_t pct_encoded_len, char *decoded, size_t buf_size)
Definition: mhd_str.c:1746
size_t MHD_bin_to_hex_z(const void *bin, size_t size, char *hex)
Definition: mhd_str.c:1696
#define toasciilower(c)
Definition: mhd_str.c:619
size_t MHD_uint8_to_str_pad(uint8_t val, uint8_t min_digits, char *buf, size_t buf_size)
Definition: mhd_str.c:1629
bool MHD_str_remove_tokens_caseless_(char *str, size_t *str_len, const char *const tokens, const size_t tokens_len)
Definition: mhd_str.c:1033
size_t MHD_str_pct_decode_lenient_n_(const char *pct_encoded, size_t pct_encoded_len, char *decoded, size_t buf_size, bool *broken_encoding)
Definition: mhd_str.c:1829
size_t MHD_uint16_to_str(uint16_t val, char *buf, size_t buf_size)
Definition: mhd_str.c:1550
size_t MHD_str_pct_decode_in_place_lenient_(char *str, bool *broken_encoding)
Definition: mhd_str.c:1984
size_t MHD_uint64_to_str(uint64_t val, char *buf, size_t buf_size)
Definition: mhd_str.c:1591
size_t MHD_str_pct_decode_in_place_strict_(char *str)
Definition: mhd_str.c:1928
#define charsequalcaseless(c1, c2)
Definition: mhd_str.c:665
#define isasciialnum(c)
Definition: mhd_str.c:607
#define toxdigitvalue(c)
Definition: mhd_str.c:651
bool MHD_str_remove_token_caseless_(const char *str, size_t str_len, const char *const token, const size_t token_len, char *buf, ssize_t *buf_size)
Definition: mhd_str.c:857
#define toasciiupper(c)
Definition: mhd_str.c:632
#define isasciilower(c)
Definition: mhd_str.c:555
#define isasciidigit(c)
Definition: mhd_str.c:585
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:749
size_t MHD_uint32_to_strx(uint32_t val, char *buf, size_t buf_size)
Definition: mhd_str.c:1516
#define isasciiupper(c)
Definition: mhd_str.c:565
#define isasciialpha(c)
Definition: mhd_str.c:575
#define isasciixdigit(c)
Definition: mhd_str.c:595
size_t MHD_hex_to_bin(const char *hex, size_t len, void *bin)
Definition: mhd_str.c:1710
#define todigitvalue(c)
Definition: mhd_str.c:642
Header for string manipulating helpers.