GNU libmicrohttpd 1.0.9
Loading...
Searching...
No Matches
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_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. */
65_MHD_static_inline bool
66isasciilower (char c)
67{
68 return (c >= 'a') && (c <= 'z');
69}
70
71
72#endif /* Disable unused functions. */
73
74
81_MHD_static_inline bool
82isasciiupper (char c)
83{
84 return (c >= 'A') && (c <= 'Z');
85}
86
87
88#if 0 /* Disable unused functions. */
95_MHD_static_inline bool
96isasciialpha (char c)
97{
98 return isasciilower (c) || isasciiupper (c);
99}
100
101
102#endif /* Disable unused functions. */
103
104
111_MHD_static_inline bool
112isasciidigit (char c)
113{
114 return (c >= '0') && (c <= '9');
115}
116
117
118#if 0 /* Disable unused functions. */
125_MHD_static_inline bool
126isasciixdigit (char c)
127{
128 return isasciidigit (c) ||
129 ( (c >= 'A') && (c <= 'F') ) ||
130 ( (c >= 'a') && (c <= 'f') );
131}
132
133
140_MHD_static_inline bool
141isasciialnum (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. */
160_MHD_static_inline char
161toasciilower (char c)
162{
163 return isasciiupper (c) ? (c - 'A' + 'a') : c;
164}
165
166
176_MHD_static_inline char
177toasciiupper (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_() */
193_MHD_static_inline int
194todigitvalue (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
212_MHD_static_inline int
213toxdigitvalue (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
536_MHD_static_inline bool
537charsequalcaseless (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
556#define isasciilower(c) (((char) (c)) >= 'a' && ((char) (c)) <= 'z')
557
558
566#define isasciiupper(c) (((char) (c)) >= 'A' && ((char) (c)) <= 'Z')
567
568
576#define isasciialpha(c) (isasciilower (c) || isasciiupper (c))
577
578
586#define isasciidigit(c) (((char) (c)) >= '0' && ((char) (c)) <= '9')
587
588
596#define isasciixdigit(c) (isasciidigit ((c)) || \
597 (((char) (c)) >= 'A' && ((char) (c)) <= 'F') || \
598 (((char) (c)) >= 'a' && ((char) (c)) <= 'f') )
599
600
608#define isasciialnum(c) (isasciialpha (c) || isasciidigit (c))
609
610
620#define toasciilower(c) ((isasciiupper (c)) ? (((char) (c)) - 'A' + 'a') : \
621 ((char) (c)))
622
623
633#define toasciiupper(c) ((isasciilower (c)) ? (((char) (c)) - 'a' + 'A') : \
634 ((char) (c)))
635
636
643#define todigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \
644 (int) (-1))
645
646
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
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
683int
684MHD_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
717int
718MHD_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
749bool
750MHD_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
782bool
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
857bool
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;
866 char *s2;
867 size_t t_pos;
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;
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
1033bool
1035 size_t *str_len,
1036 const char *const tokens,
1037 const size_t tokens_len)
1038{
1039 const char *const t = tokens;
1040 size_t pt;
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;
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;
1101 size_t pw;
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
1196size_t
1197MHD_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
1238size_t
1239MHD_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
1281size_t
1282MHD_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
1328size_t
1329MHD_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
1369size_t
1370MHD_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
1415size_t
1416MHD_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
1465size_t
1466MHD_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
1516size_t
1518 char *buf,
1519 size_t buf_size)
1520{
1521 size_t o_pos = 0;
1522 int digit_pos = 8;
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
1550size_t
1551MHD_uint16_to_str (uint16_t val,
1552 char *buf,
1553 size_t buf_size)
1554{
1555 char *chr;
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
1591size_t
1592MHD_uint64_to_str (uint64_t val,
1593 char *buf,
1594 size_t buf_size)
1595{
1596 char *chr;
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
1629size_t
1631 uint8_t min_digits,
1632 char *buf,
1633 size_t buf_size)
1634{
1635 size_t pos;
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
1676size_t
1677MHD_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
1696size_t
1697MHD_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
1710size_t
1711MHD_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
1749size_t
1750MHD_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
1834size_t
1835MHD_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
1937size_t
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
1993size_t
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
2070bool
2071MHD_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
2100bool
2101MHD_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
2130size_t
2131MHD_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
2159size_t
2160MHD_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
2245static MHD_base64_map_type_
2246base64_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
2276
2277
2278size_t
2279MHD_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
2448
2449
2450#undef MHD_base64_map_type_
2451
2452#endif /* BAUTH_SUPPORT */
macros for mhd_assert()
#define mhd_assert(ignore)
Definition mhd_assert.h:45
macros for MHD_CHECK_(), always-compiled memory-safety invariants
#define MHD_CHECK_RET_(expr, retval)
Definition mhd_check.h:137
limits values definitions
#define SSIZE_MAX
Definition mhd_limits.h:121
#define UINT64_MAX
Definition mhd_limits.h:93
#define UINT32_MAX
Definition mhd_limits.h:85
#define NULL
#define MHD_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE_
#define MHD_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE_
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition mhd_str.c:684
size_t MHD_bin_to_hex(const void *bin, size_t size, char *hex)
Definition mhd_str.c:1677
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:1750
size_t MHD_bin_to_hex_z(const void *bin, size_t size, char *hex)
Definition mhd_str.c:1697
size_t MHD_strx_to_uint32_(const char *str, uint32_t *out_val)
Definition mhd_str.c:1282
#define toasciilower(c)
Definition mhd_str.c:620
size_t MHD_uint8_to_str_pad(uint8_t val, uint8_t min_digits, char *buf, size_t buf_size)
Definition mhd_str.c:1630
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:1034
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:1835
size_t MHD_uint16_to_str(uint16_t val, char *buf, size_t buf_size)
Definition mhd_str.c:1551
size_t MHD_str_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition mhd_str.c:1239
size_t MHD_str_pct_decode_in_place_lenient_(char *str, bool *broken_encoding)
Definition mhd_str.c:1994
size_t MHD_uint64_to_str(uint64_t val, char *buf, size_t buf_size)
Definition mhd_str.c:1592
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition mhd_str.c:1416
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
Definition mhd_str.c:718
size_t MHD_str_pct_decode_in_place_strict_(char *str)
Definition mhd_str.c:1938
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition mhd_str.c:1197
#define charsequalcaseless(c1, c2)
Definition mhd_str.c:666
#define isasciialnum(c)
Definition mhd_str.c:608
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition mhd_str.c:783
#define toxdigitvalue(c)
Definition mhd_str.c:652
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:858
#define toasciiupper(c)
Definition mhd_str.c:633
#define isasciilower(c)
Definition mhd_str.c:556
#define isasciidigit(c)
Definition mhd_str.c:586
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition mhd_str.c:750
size_t MHD_uint32_to_strx(uint32_t val, char *buf, size_t buf_size)
Definition mhd_str.c:1517
size_t MHD_strx_to_uint64_(const char *str, uint64_t *out_val)
Definition mhd_str.c:1370
#define isasciiupper(c)
Definition mhd_str.c:566
#define isasciialpha(c)
Definition mhd_str.c:576
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition mhd_str.c:1329
#define isasciixdigit(c)
Definition mhd_str.c:596
size_t MHD_hex_to_bin(const char *hex, size_t len, void *bin)
Definition mhd_str.c:1711
#define todigitvalue(c)
Definition mhd_str.c:643
Header for string manipulating helpers.