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