GNU libmicrohttpd 1.0.2
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
25
26#include "mhd_str.h"
27
28#ifdef HAVE_STDBOOL_H
29#include <stdbool.h>
30#endif /* HAVE_STDBOOL_H */
31#include <string.h>
32
33#include "mhd_assert.h"
34#include "mhd_limits.h"
35#include "mhd_assert.h"
36
37#ifdef MHD_FAVOR_SMALL_CODE
38#ifdef _MHD_static_inline
39#undef _MHD_static_inline
40#endif /* _MHD_static_inline */
41/* Do not force inlining and do not use macro functions, use normal static
42 functions instead.
43 This may give more flexibility for size optimizations. */
44#define _MHD_static_inline static
45#ifndef HAVE_INLINE_FUNCS
46#define HAVE_INLINE_FUNCS 1
47#endif /* !INLINE_FUNC */
48#endif /* MHD_FAVOR_SMALL_CODE */
49
50/*
51 * Block of functions/macros that use US-ASCII charset as required by HTTP
52 * standards. Not affected by current locale settings.
53 */
54
55#ifdef HAVE_INLINE_FUNCS
56
57#if 0 /* Disable unused functions. */
64_MHD_static_inline bool
65isasciilower (char c)
66{
67 return (c >= 'a') && (c <= 'z');
68}
69
70
71#endif /* Disable unused functions. */
72
73
80_MHD_static_inline bool
81isasciiupper (char c)
82{
83 return (c >= 'A') && (c <= 'Z');
84}
85
86
87#if 0 /* Disable unused functions. */
94_MHD_static_inline bool
95isasciialpha (char c)
96{
97 return isasciilower (c) || isasciiupper (c);
98}
99
100
101#endif /* Disable unused functions. */
102
103
110_MHD_static_inline bool
111isasciidigit (char c)
112{
113 return (c >= '0') && (c <= '9');
114}
115
116
117#if 0 /* Disable unused functions. */
124_MHD_static_inline bool
125isasciixdigit (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
140isasciialnum (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
160toasciilower (char c)
161{
162 return isasciiupper (c) ? (c - 'A' + 'a') : c;
163}
164
165
175_MHD_static_inline char
176toasciiupper (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
193todigitvalue (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
212toxdigitvalue (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
536charsequalcaseless (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 /* !HAVE_INLINE_FUNCS */
672
673
674#ifndef MHD_FAVOR_SMALL_CODE
682int
683MHD_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
716int
717MHD_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
748bool
749MHD_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
781bool
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
856bool
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
1032bool
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;
1101
1102 pr = 0;
1103 pw = 0;
1104
1105 do
1106 {
1107 mhd_assert (pr >= pw);
1108 mhd_assert ((*str_len) >= (pr + tkn_len));
1109 if ( ( ((*str_len) == (pr + tkn_len)) || (',' == str[pr + tkn_len]) ) &&
1110 MHD_str_equal_caseless_bin_n_ (str + pr, tkn, tkn_len) )
1111 {
1112 /* current token in the input string matches the 'tkn', skip it */
1113 mhd_assert ((*str_len == pr + tkn_len) || \
1114 (' ' == str[pr + tkn_len + 1])); /* 'str' must be normalized */
1115 token_removed = true;
1116 /* Advance to the next token in the input string or beyond
1117 * the end of the input string. */
1118 pr += tkn_len + 2;
1119 }
1120 else
1121 {
1122 /* current token in the input string does not match the 'tkn',
1123 * copy to the output */
1124 if (0 != pw)
1125 { /* not the first output token, add ", " to separate */
1126 if (pr != pw + 2)
1127 {
1128 str[pw++] = ',';
1129 str[pw++] = ' ';
1130 }
1131 else
1132 pw += 2; /* 'str' is not yet modified in this round */
1133 }
1134 do
1135 {
1136 if (pr != pw)
1137 str[pw] = str[pr];
1138 pr++;
1139 pw++;
1140 } while (pr < *str_len && ',' != str[pr]);
1141 /* Advance to the next token in the input string or beyond
1142 * the end of the input string. */
1143 pr += 2;
1144 }
1145 /* 'pr' should point to the next token in the input string or beyond
1146 * the end of the input string */
1147 if ((*str_len) < (pr + tkn_len))
1148 { /* The rest of the 'str + pr' is too small to match 'tkn' */
1149 if ((*str_len) > pr)
1150 { /* Copy the rest of the string */
1151 size_t copy_size;
1152 copy_size = *str_len - pr;
1153 if (0 != pw)
1154 { /* not the first output token, add ", " to separate */
1155 if (pr != pw + 2)
1156 {
1157 str[pw++] = ',';
1158 str[pw++] = ' ';
1159 }
1160 else
1161 pw += 2; /* 'str' is not yet modified in this round */
1162 }
1163 if (pr != pw)
1164 memmove (str + pw, str + pr, copy_size);
1165 pw += copy_size;
1166 }
1167 *str_len = pw;
1168 break;
1169 }
1170 mhd_assert ((' ' != str[0]) && ('\t' != str[0]));
1171 mhd_assert ((0 == pr) || (3 <= pr));
1172 mhd_assert ((0 == pr) || (' ' == str[pr - 1]));
1173 mhd_assert ((0 == pr) || (',' == str[pr - 2]));
1174 } while (1);
1175 }
1176 }
1177
1178 return token_removed;
1179}
1180
1181
1182#ifndef MHD_FAVOR_SMALL_CODE
1183/* Use individual function for each case */
1184
1195size_t
1196MHD_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
1237size_t
1238MHD_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
1280size_t
1281MHD_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
1327size_t
1328MHD_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
1368size_t
1369MHD_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
1414size_t
1415MHD_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
1464size_t
1465MHD_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
1515size_t
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
1549size_t
1550MHD_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
1590size_t
1591MHD_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
1628size_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
1675size_t
1676MHD_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
1695size_t
1696MHD_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
1709size_t
1710MHD_hex_to_bin (const char *hex,
1711 size_t len,
1712 void *bin)
1713{
1714 uint8_t *const out = (uint8_t *) bin;
1715 size_t r;
1716 size_t w;
1717
1718 if (0 == len)
1719 return 0;
1720 r = 0;
1721 w = 0;
1722 if (0 != len % 2)
1723 {
1724 /* Assume the first byte is encoded with single digit */
1725 const char c2 = hex[r++];
1726 const int l = toxdigitvalue (c2);
1727 if (0 > l)
1728 return 0;
1729 out[w++] = (uint8_t) ((unsigned int) l);
1730 }
1731 while (r < len)
1732 {
1733 const char c1 = hex[r++];
1734 const char c2 = hex[r++];
1735 const int h = toxdigitvalue (c1);
1736 const int l = toxdigitvalue (c2);
1737 if ((0 > h) || (0 > l))
1738 return 0;
1739 out[w++] = (uint8_t) ( ((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1740 | ((uint8_t) ((unsigned int) l)) );
1741 }
1742 mhd_assert (len == r);
1743 mhd_assert ((len + 1) / 2 == w);
1744 return w;
1745}
1746
1747
1748size_t
1749MHD_str_pct_decode_strict_n_ (const char *pct_encoded,
1750 size_t pct_encoded_len,
1751 char *decoded,
1752 size_t buf_size)
1753{
1754#ifdef MHD_FAVOR_SMALL_CODE
1755 bool broken;
1756 size_t res;
1757
1758 res = MHD_str_pct_decode_lenient_n_ (pct_encoded, pct_encoded_len, decoded,
1759 buf_size, &broken);
1760 if (broken)
1761 return 0;
1762 return res;
1763#else /* ! MHD_FAVOR_SMALL_CODE */
1764 size_t r;
1765 size_t w;
1766 r = 0;
1767 w = 0;
1768
1769 if (buf_size >= pct_encoded_len)
1770 {
1771 while (r < pct_encoded_len)
1772 {
1773 const char chr = pct_encoded[r];
1774 if ('%' == chr)
1775 {
1776 if (2 > pct_encoded_len - r)
1777 return 0;
1778 else
1779 {
1780 const char c1 = pct_encoded[++r];
1781 const char c2 = pct_encoded[++r];
1782 const int h = toxdigitvalue (c1);
1783 const int l = toxdigitvalue (c2);
1784 unsigned char out;
1785 if ((0 > h) || (0 > l))
1786 return 0;
1787 out =
1788 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1789 | ((uint8_t) ((unsigned int) l)));
1790 decoded[w] = (char) out;
1791 }
1792 }
1793 else
1794 decoded[w] = chr;
1795 ++r;
1796 ++w;
1797 }
1798 return w;
1799 }
1800
1801 while (r < pct_encoded_len)
1802 {
1803 const char chr = pct_encoded[r];
1804 if (w >= buf_size)
1805 return 0;
1806 if ('%' == chr)
1807 {
1808 if (2 > pct_encoded_len - r)
1809 return 0;
1810 else
1811 {
1812 const char c1 = pct_encoded[++r];
1813 const char c2 = pct_encoded[++r];
1814 const int h = toxdigitvalue (c1);
1815 const int l = toxdigitvalue (c2);
1816 unsigned char out;
1817 if ((0 > h) || (0 > l))
1818 return 0;
1819 out =
1820 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1821 | ((uint8_t) ((unsigned int) l)));
1822 decoded[w] = (char) out;
1823 }
1824 }
1825 else
1826 decoded[w] = chr;
1827 ++r;
1828 ++w;
1829 }
1830 return w;
1831#endif /* ! MHD_FAVOR_SMALL_CODE */
1832}
1833
1834
1835size_t
1836MHD_str_pct_decode_lenient_n_ (const char *pct_encoded,
1837 size_t pct_encoded_len,
1838 char *decoded,
1839 size_t buf_size,
1840 bool *broken_encoding)
1841{
1842 size_t r;
1843 size_t w;
1844 r = 0;
1845 w = 0;
1846 if (NULL != broken_encoding)
1847 *broken_encoding = false;
1848#ifndef MHD_FAVOR_SMALL_CODE
1849 if (buf_size >= pct_encoded_len)
1850 {
1851 while (r < pct_encoded_len)
1852 {
1853 const char chr = pct_encoded[r];
1854 if ('%' == chr)
1855 {
1856 if (2 > pct_encoded_len - r)
1857 {
1858 if (NULL != broken_encoding)
1859 *broken_encoding = true;
1860 decoded[w] = chr; /* Copy "as is" */
1861 }
1862 else
1863 {
1864 const char c1 = pct_encoded[++r];
1865 const char c2 = pct_encoded[++r];
1866 const int h = toxdigitvalue (c1);
1867 const int l = toxdigitvalue (c2);
1868 unsigned char out;
1869 if ((0 > h) || (0 > l))
1870 {
1871 r -= 2;
1872 if (NULL != broken_encoding)
1873 *broken_encoding = true;
1874 decoded[w] = chr; /* Copy "as is" */
1875 }
1876 else
1877 {
1878 out =
1879 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1880 | ((uint8_t) ((unsigned int) l)));
1881 decoded[w] = (char) out;
1882 }
1883 }
1884 }
1885 else
1886 decoded[w] = chr;
1887 ++r;
1888 ++w;
1889 }
1890 return w;
1891 }
1892#endif /* ! MHD_FAVOR_SMALL_CODE */
1893 while (r < pct_encoded_len)
1894 {
1895 const char chr = pct_encoded[r];
1896 if (w >= buf_size)
1897 return 0;
1898 if ('%' == chr)
1899 {
1900 if (2 > pct_encoded_len - r)
1901 {
1902 if (NULL != broken_encoding)
1903 *broken_encoding = true;
1904 decoded[w] = chr; /* Copy "as is" */
1905 }
1906 else
1907 {
1908 const char c1 = pct_encoded[++r];
1909 const char c2 = pct_encoded[++r];
1910 const int h = toxdigitvalue (c1);
1911 const int l = toxdigitvalue (c2);
1912 if ((0 > h) || (0 > l))
1913 {
1914 r -= 2;
1915 if (NULL != broken_encoding)
1916 *broken_encoding = true;
1917 decoded[w] = chr; /* Copy "as is" */
1918 }
1919 else
1920 {
1921 unsigned char out;
1922 out =
1923 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1924 | ((uint8_t) ((unsigned int) l)));
1925 decoded[w] = (char) out;
1926 }
1927 }
1928 }
1929 else
1930 decoded[w] = chr;
1931 ++r;
1932 ++w;
1933 }
1934 return w;
1935}
1936
1937
1938size_t
1940{
1941#ifdef MHD_FAVOR_SMALL_CODE
1942 size_t res;
1943 bool broken;
1944
1945 res = MHD_str_pct_decode_in_place_lenient_ (str, &broken);
1946 if (broken)
1947 {
1948 res = 0;
1949 str[0] = 0;
1950 }
1951 return res;
1952#else /* ! MHD_FAVOR_SMALL_CODE */
1953 size_t r;
1954 size_t w;
1955 r = 0;
1956 w = 0;
1957
1958 while (0 != str[r])
1959 {
1960 const char chr = str[r++];
1961 if ('%' == chr)
1962 {
1963 const char d1 = str[r++];
1964 if (0 == d1)
1965 return 0;
1966 else
1967 {
1968 const char d2 = str[r++];
1969 if (0 == d2)
1970 return 0;
1971 else
1972 {
1973 const int h = toxdigitvalue (d1);
1974 const int l = toxdigitvalue (d2);
1975 unsigned char out;
1976 if ((0 > h) || (0 > l))
1977 return 0;
1978 out =
1979 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
1980 | ((uint8_t) ((unsigned int) l)));
1981 str[w++] = (char) out;
1982 }
1983 }
1984 }
1985 else
1986 str[w++] = chr;
1987 }
1988 str[w] = 0;
1989 return w;
1990#endif /* ! MHD_FAVOR_SMALL_CODE */
1991}
1992
1993
1994size_t
1996 bool *broken_encoding)
1997{
1998#ifdef MHD_FAVOR_SMALL_CODE
1999 size_t len;
2000 size_t res;
2001
2002 len = strlen (str);
2003 res = MHD_str_pct_decode_lenient_n_ (str, len, str, len, broken_encoding);
2004 str[res] = 0;
2005
2006 return res;
2007#else /* ! MHD_FAVOR_SMALL_CODE */
2008 size_t r;
2009 size_t w;
2010 if (NULL != broken_encoding)
2011 *broken_encoding = false;
2012 r = 0;
2013 w = 0;
2014 while (0 != str[r])
2015 {
2016 const char chr = str[r++];
2017 if ('%' == chr)
2018 {
2019 const char d1 = str[r++];
2020 if (0 == d1)
2021 {
2022 if (NULL != broken_encoding)
2023 *broken_encoding = true;
2024 str[w++] = chr; /* Copy "as is" */
2025 str[w] = 0;
2026 return w;
2027 }
2028 else
2029 {
2030 const char d2 = str[r++];
2031 if (0 == d2)
2032 {
2033 if (NULL != broken_encoding)
2034 *broken_encoding = true;
2035 str[w++] = chr; /* Copy "as is" */
2036 str[w++] = d1; /* Copy "as is" */
2037 str[w] = 0;
2038 return w;
2039 }
2040 else
2041 {
2042 const int h = toxdigitvalue (d1);
2043 const int l = toxdigitvalue (d2);
2044 unsigned char out;
2045 if ((0 > h) || (0 > l))
2046 {
2047 if (NULL != broken_encoding)
2048 *broken_encoding = true;
2049 str[w++] = chr; /* Copy "as is" */
2050 str[w++] = d1;
2051 str[w++] = d2;
2052 continue;
2053 }
2054 out =
2055 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4))
2056 | ((uint8_t) ((unsigned int) l)));
2057 str[w++] = (char) out;
2058 continue;
2059 }
2060 }
2061 }
2062 str[w++] = chr;
2063 }
2064 str[w] = 0;
2065 return w;
2066#endif /* ! MHD_FAVOR_SMALL_CODE */
2067}
2068
2069
2070#ifdef DAUTH_SUPPORT
2071bool
2072MHD_str_equal_quoted_bin_n (const char *quoted,
2073 size_t quoted_len,
2074 const char *unquoted,
2075 size_t unquoted_len)
2076{
2077 size_t i;
2078 size_t j;
2079 if (unquoted_len < quoted_len / 2)
2080 return false;
2081
2082 j = 0;
2083 for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j)
2084 {
2085 if ('\\' == quoted[i])
2086 {
2087 i++; /* Advance to the next character */
2088 if (quoted_len == i)
2089 return false; /* No character after escaping backslash */
2090 }
2091 if (quoted[i] != unquoted[j])
2092 return false; /* Different characters */
2093 }
2094 if ((quoted_len != i) || (unquoted_len != j))
2095 return false; /* The strings have different length */
2096
2097 return true;
2098}
2099
2100
2101bool
2102MHD_str_equal_caseless_quoted_bin_n (const char *quoted,
2103 size_t quoted_len,
2104 const char *unquoted,
2105 size_t unquoted_len)
2106{
2107 size_t i;
2108 size_t j;
2109 if (unquoted_len < quoted_len / 2)
2110 return false;
2111
2112 j = 0;
2113 for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j)
2114 {
2115 if ('\\' == quoted[i])
2116 {
2117 i++; /* Advance to the next character */
2118 if (quoted_len == i)
2119 return false; /* No character after escaping backslash */
2120 }
2121 if (! charsequalcaseless (quoted[i], unquoted[j]))
2122 return false; /* Different characters */
2123 }
2124 if ((quoted_len != i) || (unquoted_len != j))
2125 return false; /* The strings have different length */
2126
2127 return true;
2128}
2129
2130
2131size_t
2132MHD_str_unquote (const char *quoted,
2133 size_t quoted_len,
2134 char *result)
2135{
2136 size_t r;
2137 size_t w;
2138
2139 r = 0;
2140 w = 0;
2141
2142 while (quoted_len > r)
2143 {
2144 if ('\\' == quoted[r])
2145 {
2146 ++r;
2147 if (quoted_len == r)
2148 return 0; /* Last backslash is not followed by char to unescape */
2149 }
2150 result[w++] = quoted[r++];
2151 }
2152 return w;
2153}
2154
2155
2156#endif /* DAUTH_SUPPORT */
2157
2158#if defined(DAUTH_SUPPORT) || defined(BAUTH_SUPPORT)
2159
2160size_t
2161MHD_str_quote (const char *unquoted,
2162 size_t unquoted_len,
2163 char *result,
2164 size_t buf_size)
2165{
2166 size_t r;
2167 size_t w;
2168
2169 r = 0;
2170 w = 0;
2171
2172#ifndef MHD_FAVOR_SMALL_CODE
2173 if (unquoted_len * 2 <= buf_size)
2174 {
2175 /* Fast loop: the output will fit the buffer with any input string content */
2176 while (unquoted_len > r)
2177 {
2178 const char chr = unquoted[r++];
2179 if (('\\' == chr) || ('\"' == chr))
2180 result[w++] = '\\'; /* Escape current char */
2181 result[w++] = chr;
2182 }
2183 }
2184 else
2185 {
2186 if (unquoted_len > buf_size)
2187 return 0; /* Quick fail: the output buffer is too small */
2188#else /* MHD_FAVOR_SMALL_CODE */
2189 if (1)
2190 {
2191#endif /* MHD_FAVOR_SMALL_CODE */
2192
2193 while (unquoted_len > r)
2194 {
2195 if (buf_size <= w)
2196 return 0; /* The output buffer is too small */
2197 else
2198 {
2199 const char chr = unquoted[r++];
2200 if (('\\' == chr) || ('\"' == chr))
2201 {
2202 result[w++] = '\\'; /* Escape current char */
2203 if (buf_size <= w)
2204 return 0; /* The output buffer is too small */
2205 }
2206 result[w++] = chr;
2207 }
2208 }
2209 }
2210
2211 mhd_assert (w >= r);
2212 mhd_assert (w <= r * 2);
2213 return w;
2214}
2215
2216
2217#endif /* DAUTH_SUPPORT || BAUTH_SUPPORT */
2218
2219#ifdef BAUTH_SUPPORT
2220
2221/*
2222 * MHD_BASE64_FUNC_VERSION
2223 * 1 = smallest,
2224 * 2 = medium,
2225 * 3 = fastest
2226 */
2227#ifndef MHD_BASE64_FUNC_VERSION
2228#ifdef MHD_FAVOR_SMALL_CODE
2229#define MHD_BASE64_FUNC_VERSION 1
2230#else /* ! MHD_FAVOR_SMALL_CODE */
2231#define MHD_BASE64_FUNC_VERSION 3
2232#endif /* ! MHD_FAVOR_SMALL_CODE */
2233#endif /* ! MHD_BASE64_FUNC_VERSION */
2234
2235#if MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3
2236#error Wrong MHD_BASE64_FUNC_VERSION value
2237#endif /* MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 */
2238
2239#if MHD_BASE64_FUNC_VERSION == 3
2240#define MHD_base64_map_type_ int
2241#else /* MHD_BASE64_FUNC_VERSION < 3 */
2242#define MHD_base64_map_type_ int8_t
2243#endif /* MHD_BASE64_FUNC_VERSION < 3 */
2244
2245#if MHD_BASE64_FUNC_VERSION == 1
2246static MHD_base64_map_type_
2247base64_char_to_value_ (uint8_t c)
2248{
2249 if ('Z' >= c)
2250 {
2251 if ('A' <= c)
2252 return (MHD_base64_map_type_) ((c - 'A') + 0);
2253 if ('0' <= c)
2254 {
2255 if ('9' >= c)
2256 return (MHD_base64_map_type_) ((c - '0') + 52);
2257 if ('=' == c)
2258 return -2;
2259 return -1;
2260 }
2261 if ('+' == c)
2262 return 62;
2263 if ('/' == c)
2264 return 63;
2265 return -1;
2266 }
2267 if (('z' >= c) && ('a' <= c))
2268 return (MHD_base64_map_type_) ((c - 'a') + 26);
2269 return -1;
2270}
2271
2272
2273#endif /* MHD_BASE64_FUNC_VERSION == 1 */
2274
2275
2277
2278
2279size_t
2280MHD_base64_to_bin_n (const char *base64,
2281 size_t base64_len,
2282 void *bin,
2283 size_t bin_size)
2284{
2285#if MHD_BASE64_FUNC_VERSION >= 2
2286 static const MHD_base64_map_type_ map[] = {
2287 /* -1 = invalid char, -2 = padding
2288 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
2289 NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, */
2290 -1, -1, -1, -1, -1, -1, -1, -1,
2291 /*
2292 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
2293 BS, HT, LF, VT, FF, CR, SO, SI, */
2294 -1, -1, -1, -1, -1, -1, -1, -1,
2295 /*
2296 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
2297 DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, */
2298 -1, -1, -1, -1, -1, -1, -1, -1,
2299 /*
2300 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
2301 CAN, EM, SUB, ESC, FS, GS, RS, US, */
2302 -1, -1, -1, -1, -1, -1, -1, -1,
2303 /*
2304 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
2305 ' ', '!', '"', '#', '$', '%', '&', '\'', */
2306 -1, -1, -1, -1, -1, -1, -1, -1,
2307 /*
2308 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
2309 '(', ')', '*', '+', ',', '-', '.', '/', */
2310 -1, -1, -1, 62, -1, -1, -1, 63,
2311 /*
2312 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
2313 '0', '1', '2', '3', '4', '5', '6', '7', */
2314 52, 53, 54, 55, 56, 57, 58, 59,
2315 /*
2316 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
2317 '8', '9', ':', ';', '<', '=', '>', '?', */
2318 60, 61, -1, -1, -1, -2, -1, -1,
2319 /*
2320 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
2321 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */
2322 -1, 0, 1, 2, 3, 4, 5, 6,
2323 /*
2324 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
2325 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */
2326 7, 8, 9, 10, 11, 12, 13, 14,
2327 /*
2328 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
2329 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */
2330 15, 16, 17, 18, 19, 20, 21, 22,
2331 /*
2332 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
2333 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */
2334 23, 24, 25, -1, -1, -1, -1, -1,
2335 /*
2336 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
2337 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */
2338 -1, 26, 27, 28, 29, 30, 31, 32,
2339 /*
2340 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
2341 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */
2342 33, 34, 35, 36, 37, 38, 39, 40,
2343 /*
2344 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
2345 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */
2346 41, 42, 43, 44, 45, 46, 47, 48,
2347 /*
2348 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
2349 'x', 'y', 'z', '{', '|', '}', '~', DEL, */
2350 49, 50, 51, -1, -1, -1, -1, -1
2351
2352#if MHD_BASE64_FUNC_VERSION == 3
2353 ,
2354 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80..8F */
2355 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90..9F */
2356 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0..AF */
2357 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0..BF */
2358 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0..CF */
2359 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0..DF */
2360 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0..EF */
2361 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* F0..FF */
2362#endif /* ! MHD_BASE64_FUNC_VERSION == 3 */
2363 };
2364#define base64_char_to_value_(c) map[(c)]
2365#endif /* MHD_BASE64_FUNC_VERSION >= 2 */
2366 const uint8_t *const in = (const uint8_t *) base64;
2367 uint8_t *const out = (uint8_t *) bin;
2368 size_t i;
2369 size_t j;
2370 if (0 == base64_len)
2371 return 0; /* Nothing to decode */
2372 if (0 != base64_len % 4)
2373 return 0; /* Wrong input length */
2374 if (base64_len / 4 * 3 - 2 > bin_size)
2375 return 0;
2376
2377 j = 0;
2378 for (i = 0; i < (base64_len - 4); i += 4)
2379 {
2380#if MHD_BASE64_FUNC_VERSION == 2
2381 if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3])))
2382 return 0;
2383#endif /* MHD_BASE64_FUNC_VERSION == 2 */
2384 if (1)
2385 {
2386 const MHD_base64_map_type_ v1 = base64_char_to_value_ (in[i + 0]);
2387 const MHD_base64_map_type_ v2 = base64_char_to_value_ (in[i + 1]);
2388 const MHD_base64_map_type_ v3 = base64_char_to_value_ (in[i + 2]);
2389 const MHD_base64_map_type_ v4 = base64_char_to_value_ (in[i + 3]);
2390 if ((0 > v1) || (0 > v2) || (0 > v3) || (0 > v4))
2391 return 0;
2392 out[j + 0] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2))
2393 | ((uint8_t) (((uint8_t) v2) >> 4)));
2394 out[j + 1] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4))
2395 | ((uint8_t) (((uint8_t) v3) >> 2)));
2396 out[j + 2] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6))
2397 | ((uint8_t) v4));
2398 }
2399 j += 3;
2400 }
2401#if MHD_BASE64_FUNC_VERSION == 2
2402 if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3])))
2403 return 0;
2404#endif /* MHD_BASE64_FUNC_VERSION == 2 */
2405 if (1)
2406 { /* The last four chars block */
2407 const MHD_base64_map_type_ v1 = base64_char_to_value_ (in[i + 0]);
2408 const MHD_base64_map_type_ v2 = base64_char_to_value_ (in[i + 1]);
2409 const MHD_base64_map_type_ v3 = base64_char_to_value_ (in[i + 2]);
2410 const MHD_base64_map_type_ v4 = base64_char_to_value_ (in[i + 3]);
2411 if ((0 > v1) || (0 > v2))
2412 return 0; /* Invalid char or padding at first two positions */
2413 mhd_assert (j < bin_size);
2414 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2))
2415 | ((uint8_t) (((uint8_t) v2) >> 4)));
2416 if (0 > v3)
2417 { /* Third char is either padding or invalid */
2418 if ((-2 != v3) || (-2 != v4))
2419 return 0; /* Both two last chars must be padding */
2420 if (0 != (uint8_t) (((uint8_t) v2) << 4))
2421 return 0; /* Wrong last char */
2422 return j;
2423 }
2424 if (j >= bin_size)
2425 return 0; /* Not enough space */
2426 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4))
2427 | ((uint8_t) (((uint8_t) v3) >> 2)));
2428 if (0 > v4)
2429 { /* Fourth char is either padding or invalid */
2430 if (-2 != v4)
2431 return 0; /* The char must be padding */
2432 if (0 != (uint8_t) (((uint8_t) v3) << 6))
2433 return 0; /* Wrong last char */
2434 return j;
2435 }
2436 if (j >= bin_size)
2437 return 0; /* Not enough space */
2438 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6))
2439 | ((uint8_t) v4));
2440 }
2441 return j;
2442#if MHD_BASE64_FUNC_VERSION >= 2
2443#undef base64_char_to_value_
2444#endif /* MHD_BASE64_FUNC_VERSION >= 2 */
2445}
2446
2447
2449
2450
2451#undef MHD_base64_map_type_
2452
2453#endif /* BAUTH_SUPPORT */
macros for mhd_assert()
#define mhd_assert(ignore)
Definition mhd_assert.h:45
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:683
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:1749
size_t MHD_bin_to_hex_z(const void *bin, size_t size, char *hex)
Definition mhd_str.c:1696
size_t MHD_strx_to_uint32_(const char *str, uint32_t *out_val)
Definition mhd_str.c:1281
#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:1836
size_t MHD_uint16_to_str(uint16_t val, char *buf, size_t buf_size)
Definition mhd_str.c:1550
size_t MHD_str_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition mhd_str.c:1238
size_t MHD_str_pct_decode_in_place_lenient_(char *str, bool *broken_encoding)
Definition mhd_str.c:1995
size_t MHD_uint64_to_str(uint64_t val, char *buf, size_t buf_size)
Definition mhd_str.c:1591
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition mhd_str.c:1415
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
Definition mhd_str.c:717
size_t MHD_str_pct_decode_in_place_strict_(char *str)
Definition mhd_str.c:1939
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition mhd_str.c:1196
#define charsequalcaseless(c1, c2)
Definition mhd_str.c:665
#define isasciialnum(c)
Definition mhd_str.c:607
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition mhd_str.c:782
#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
size_t MHD_strx_to_uint64_(const char *str, uint64_t *out_val)
Definition mhd_str.c:1369
#define isasciiupper(c)
Definition mhd_str.c:565
#define isasciialpha(c)
Definition mhd_str.c:575
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition mhd_str.c:1328
#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.