mhd_str.c (84509B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2015-2024 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file microhttpd/mhd_str.c 41 * @brief Functions implementations for string manipulating 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 45 #include "mhd_sys_options.h" 46 47 #include "mhd_assert.h" 48 #include "mhd_limits.h" 49 50 #include "mhd_constexpr.h" 51 #include "mhd_assume.h" 52 53 #include <string.h> 54 55 #include "mhd_str.h" 56 57 #ifdef MHD_FAVOR_SMALL_CODE 58 # ifdef mhd_static_inline 59 # undef mhd_static_inline 60 # endif /* mhd_static_inline */ 61 /* Do not force inlining and do not use macro functions, use normal static 62 functions instead. 63 This may give more flexibility for size optimizations. */ 64 # define mhd_static_inline static 65 # ifndef HAVE_INLINE_FUNCS 66 # define HAVE_INLINE_FUNCS 1 67 # endif /* !HAVE_INLINE_FUNCS */ 68 #endif /* MHD_FAVOR_SMALL_CODE */ 69 70 /* 71 * Block of functions/macros that use US-ASCII charset as required by HTTP 72 * standards. Not affected by current locale settings. 73 */ 74 75 #ifdef HAVE_INLINE_FUNCS 76 77 #ifdef mhd_HAVE_STR_TO_UPPER 78 /** 79 * Check whether character is lower case letter in US-ASCII 80 * 81 * @param c character to check 82 * @return non-zero if character is lower case letter, zero otherwise 83 */ 84 mhd_static_inline MHD_FN_CONST_ bool 85 isasciilower (char c) 86 { 87 const unsigned int uc = (unsigned int) (unsigned char) c; 88 const unsigned int t = uc - (unsigned int) (unsigned char) 'a'; 89 return (((unsigned int) ('z' - 'a')) >= t); 90 } 91 92 93 #endif /* mhd_HAVE_STR_TO_UPPER */ 94 95 96 /** 97 * Check whether character is upper case letter in US-ASCII 98 * 99 * @param c character to check 100 * @return non-zero if character is upper case letter, zero otherwise 101 */ 102 mhd_static_inline MHD_FN_CONST_ bool 103 isasciiupper (char c) 104 { 105 const unsigned int uc = (unsigned int) (unsigned char) c; 106 const unsigned int t = uc - (unsigned int) (unsigned char) 'A'; 107 return (((unsigned int) ('Z' - 'A')) >= t); 108 } 109 110 111 #if 0 /* Disable unused functions. */ 112 /** 113 * Check whether character is letter in US-ASCII 114 * 115 * @param c character to check 116 * @return non-zero if character is letter in US-ASCII, zero otherwise 117 */ 118 mhd_static_inline MHD_FN_CONST_ bool 119 isasciialpha (char c) 120 { 121 return isasciilower (c) || isasciiupper (c); 122 } 123 124 125 #endif /* Disable unused functions. */ 126 127 128 /** 129 * Check whether character is decimal digit in US-ASCII 130 * 131 * @param c character to check 132 * @return non-zero if character is decimal digit, zero otherwise 133 */ 134 mhd_static_inline MHD_FN_CONST_ bool 135 isasciidigit (char c) 136 { 137 return (c <= '9') && (c >= '0'); 138 } 139 140 141 #if 0 /* Disable unused functions. */ 142 /** 143 * Check whether character is hexadecimal digit in US-ASCII 144 * 145 * @param c character to check 146 * @return non-zero if character is decimal digit, zero otherwise 147 */ 148 mhd_static_inline MHD_FN_CONST_ bool 149 isasciixdigit (char c) 150 { 151 return isasciidigit (c) || 152 ( (c <= 'F') && (c >= 'A') ) || 153 ( (c <= 'f') && (c >= 'a') ); 154 } 155 156 157 /** 158 * Check whether character is decimal digit or letter in US-ASCII 159 * 160 * @param c character to check 161 * @return non-zero if character is decimal digit or letter, zero otherwise 162 */ 163 mhd_static_inline MHD_FN_CONST_ bool 164 isasciialnum (char c) 165 { 166 return isasciialpha (c) || isasciidigit (c); 167 } 168 169 170 #endif /* Disable unused functions. */ 171 172 /** 173 * Convert US-ASCII character to lower case. 174 * If character is upper case letter in US-ASCII than it's converted to lower 175 * case analog. If character is NOT upper case letter than it's returned 176 * unmodified. 177 * 178 * @param c character to convert 179 * @return converted to lower case character 180 */ 181 mhd_static_inline MHD_FN_CONST_ char 182 toasciilower (char c) 183 { 184 return (char) (((unsigned char) c) | ((isasciiupper (c) ? 1u : 0u) << 5u)); 185 } 186 187 188 #ifdef mhd_HAVE_STR_TO_UPPER 189 190 /** 191 * Convert US-ASCII character to upper case. 192 * If character is lower case letter in US-ASCII than it's converted to upper 193 * case counterpart. If character is NOT lower case letter than it's returned 194 * unmodified. 195 * 196 * @param c character to convert 197 * @return converted to upper case character 198 */ 199 mhd_static_inline MHD_FN_CONST_ char 200 toasciiupper (char c) 201 { 202 return (char) (unsigned char) 203 (((unsigned char) c) & ~((isasciilower (c) ? 1u : 0u) << 5u)); 204 } 205 206 207 #endif /* mhd_HAVE_STR_TO_UPPER */ 208 209 210 #if defined(MHD_FAVOR_SMALL_CODE) /* Used only in mhd_str_to_uvalue_n() */ 211 /** 212 * Convert US-ASCII decimal digit to its value. 213 * 214 * @param c character to convert 215 * @return value of decimal digit or -1 if @ c is not decimal digit 216 */ 217 mhd_static_inline MHD_FN_CONST_ int 218 todigitvalue (char c) 219 { 220 if (isasciidigit (c)) 221 return (unsigned char) (c - '0'); 222 223 return -1; 224 } 225 226 227 #endif /* MHD_FAVOR_SMALL_CODE */ 228 229 230 /** 231 * Convert US-ASCII hexadecimal digit to its value. 232 * 233 * @param c character to convert 234 * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit 235 */ 236 mhd_static_inline MHD_FN_CONST_ int 237 xdigittovalue (char c) 238 { 239 const unsigned char uc = (unsigned char) c; /* Force unsigned value */ 240 #if ! defined(MHD_FAVOR_SMALL_CODE) 241 static const signed char map_xdigit_to_value[256] = { 242 -1 /* 0x00 (NUL) */, 243 -1 /* 0x01 (SOH) */, 244 -1 /* 0x02 (STX) */, 245 -1 /* 0x03 (ETX) */, 246 -1 /* 0x04 (EOT) */, 247 -1 /* 0x05 (ENQ) */, 248 -1 /* 0x06 (ACK) */, 249 -1 /* 0x07 (BEL) */, 250 -1 /* 0x08 (BS) */, 251 -1 /* 0x09 (HT) */, 252 -1 /* 0x0A (LF) */, 253 -1 /* 0x0B (VT) */, 254 -1 /* 0x0C (FF) */, 255 -1 /* 0x0D (CR) */, 256 -1 /* 0x0E (SO) */, 257 -1 /* 0x0F (SI) */, 258 -1 /* 0x10 (DLE) */, 259 -1 /* 0x11 (DC1) */, 260 -1 /* 0x12 (DC2) */, 261 -1 /* 0x13 (DC3) */, 262 -1 /* 0x14 (DC4) */, 263 -1 /* 0x15 (NAK) */, 264 -1 /* 0x16 (SYN) */, 265 -1 /* 0x17 (ETB) */, 266 -1 /* 0x18 (CAN) */, 267 -1 /* 0x19 (EM) */, 268 -1 /* 0x1A (SUB) */, 269 -1 /* 0x1B (ESC) */, 270 -1 /* 0x1C (FS) */, 271 -1 /* 0x1D (GS) */, 272 -1 /* 0x1E (RS) */, 273 -1 /* 0x1F (US) */, 274 -1 /* 0x20 (' ') */, 275 -1 /* 0x21 ('!') */, 276 -1 /* 0x22 ('"') */, 277 -1 /* 0x23 ('#') */, 278 -1 /* 0x24 ('$') */, 279 -1 /* 0x25 ('%') */, 280 -1 /* 0x26 ('&') */, 281 -1 /* 0x27 ('\'') */, 282 -1 /* 0x28 ('(') */, 283 -1 /* 0x29 (')') */, 284 -1 /* 0x2A ('*') */, 285 -1 /* 0x2B ('+') */, 286 -1 /* 0x2C (',') */, 287 -1 /* 0x2D ('-') */, 288 -1 /* 0x2E ('.') */, 289 -1 /* 0x2F ('/') */, 290 0 /* 0x30 ('0') */, 291 1 /* 0x31 ('1') */, 292 2 /* 0x32 ('2') */, 293 3 /* 0x33 ('3') */, 294 4 /* 0x34 ('4') */, 295 5 /* 0x35 ('5') */, 296 6 /* 0x36 ('6') */, 297 7 /* 0x37 ('7') */, 298 8 /* 0x38 ('8') */, 299 9 /* 0x39 ('9') */, 300 -1 /* 0x3A (':') */, 301 -1 /* 0x3B (';') */, 302 -1 /* 0x3C ('<') */, 303 -1 /* 0x3D ('=') */, 304 -1 /* 0x3E ('>') */, 305 -1 /* 0x3F ('?') */, 306 -1 /* 0x40 ('@') */, 307 10 /* 0x41 ('A') */, 308 11 /* 0x42 ('B') */, 309 12 /* 0x43 ('C') */, 310 13 /* 0x44 ('D') */, 311 14 /* 0x45 ('E') */, 312 15 /* 0x46 ('F') */, 313 -1 /* 0x47 ('G') */, 314 -1 /* 0x48 ('H') */, 315 -1 /* 0x49 ('I') */, 316 -1 /* 0x4A ('J') */, 317 -1 /* 0x4B ('K') */, 318 -1 /* 0x4C ('L') */, 319 -1 /* 0x4D ('M') */, 320 -1 /* 0x4E ('N') */, 321 -1 /* 0x4F ('O') */, 322 -1 /* 0x50 ('P') */, 323 -1 /* 0x51 ('Q') */, 324 -1 /* 0x52 ('R') */, 325 -1 /* 0x53 ('S') */, 326 -1 /* 0x54 ('T') */, 327 -1 /* 0x55 ('U') */, 328 -1 /* 0x56 ('V') */, 329 -1 /* 0x57 ('W') */, 330 -1 /* 0x58 ('X') */, 331 -1 /* 0x59 ('Y') */, 332 -1 /* 0x5A ('Z') */, 333 -1 /* 0x5B ('[') */, 334 -1 /* 0x5C ('\') */, 335 -1 /* 0x5D (']') */, 336 -1 /* 0x5E ('^') */, 337 -1 /* 0x5F ('_') */, 338 -1 /* 0x60 ('`') */, 339 10 /* 0x61 ('a') */, 340 11 /* 0x62 ('b') */, 341 12 /* 0x63 ('c') */, 342 13 /* 0x64 ('d') */, 343 14 /* 0x65 ('e') */, 344 15 /* 0x66 ('f') */, 345 -1 /* 0x67 ('g') */, 346 -1 /* 0x68 ('h') */, 347 -1 /* 0x69 ('i') */, 348 -1 /* 0x6A ('j') */, 349 -1 /* 0x6B ('k') */, 350 -1 /* 0x6C ('l') */, 351 -1 /* 0x6D ('m') */, 352 -1 /* 0x6E ('n') */, 353 -1 /* 0x6F ('o') */, 354 -1 /* 0x70 ('p') */, 355 -1 /* 0x71 ('q') */, 356 -1 /* 0x72 ('r') */, 357 -1 /* 0x73 ('s') */, 358 -1 /* 0x74 ('t') */, 359 -1 /* 0x75 ('u') */, 360 -1 /* 0x76 ('v') */, 361 -1 /* 0x77 ('w') */, 362 -1 /* 0x78 ('x') */, 363 -1 /* 0x79 ('y') */, 364 -1 /* 0x7A ('z') */, 365 -1 /* 0x7B ('{') */, 366 -1 /* 0x7C ('|') */, 367 -1 /* 0x7D ('}') */, 368 -1 /* 0x7E ('~') */, 369 -1 /* 0x7F (DEL) */, 370 -1 /* 0x80 (EXT) */, 371 -1 /* 0x81 (EXT) */, 372 -1 /* 0x82 (EXT) */, 373 -1 /* 0x83 (EXT) */, 374 -1 /* 0x84 (EXT) */, 375 -1 /* 0x85 (EXT) */, 376 -1 /* 0x86 (EXT) */, 377 -1 /* 0x87 (EXT) */, 378 -1 /* 0x88 (EXT) */, 379 -1 /* 0x89 (EXT) */, 380 -1 /* 0x8A (EXT) */, 381 -1 /* 0x8B (EXT) */, 382 -1 /* 0x8C (EXT) */, 383 -1 /* 0x8D (EXT) */, 384 -1 /* 0x8E (EXT) */, 385 -1 /* 0x8F (EXT) */, 386 -1 /* 0x90 (EXT) */, 387 -1 /* 0x91 (EXT) */, 388 -1 /* 0x92 (EXT) */, 389 -1 /* 0x93 (EXT) */, 390 -1 /* 0x94 (EXT) */, 391 -1 /* 0x95 (EXT) */, 392 -1 /* 0x96 (EXT) */, 393 -1 /* 0x97 (EXT) */, 394 -1 /* 0x98 (EXT) */, 395 -1 /* 0x99 (EXT) */, 396 -1 /* 0x9A (EXT) */, 397 -1 /* 0x9B (EXT) */, 398 -1 /* 0x9C (EXT) */, 399 -1 /* 0x9D (EXT) */, 400 -1 /* 0x9E (EXT) */, 401 -1 /* 0x9F (EXT) */, 402 -1 /* 0xA0 (EXT) */, 403 -1 /* 0xA1 (EXT) */, 404 -1 /* 0xA2 (EXT) */, 405 -1 /* 0xA3 (EXT) */, 406 -1 /* 0xA4 (EXT) */, 407 -1 /* 0xA5 (EXT) */, 408 -1 /* 0xA6 (EXT) */, 409 -1 /* 0xA7 (EXT) */, 410 -1 /* 0xA8 (EXT) */, 411 -1 /* 0xA9 (EXT) */, 412 -1 /* 0xAA (EXT) */, 413 -1 /* 0xAB (EXT) */, 414 -1 /* 0xAC (EXT) */, 415 -1 /* 0xAD (EXT) */, 416 -1 /* 0xAE (EXT) */, 417 -1 /* 0xAF (EXT) */, 418 -1 /* 0xB0 (EXT) */, 419 -1 /* 0xB1 (EXT) */, 420 -1 /* 0xB2 (EXT) */, 421 -1 /* 0xB3 (EXT) */, 422 -1 /* 0xB4 (EXT) */, 423 -1 /* 0xB5 (EXT) */, 424 -1 /* 0xB6 (EXT) */, 425 -1 /* 0xB7 (EXT) */, 426 -1 /* 0xB8 (EXT) */, 427 -1 /* 0xB9 (EXT) */, 428 -1 /* 0xBA (EXT) */, 429 -1 /* 0xBB (EXT) */, 430 -1 /* 0xBC (EXT) */, 431 -1 /* 0xBD (EXT) */, 432 -1 /* 0xBE (EXT) */, 433 -1 /* 0xBF (EXT) */, 434 -1 /* 0xC0 (EXT) */, 435 -1 /* 0xC1 (EXT) */, 436 -1 /* 0xC2 (EXT) */, 437 -1 /* 0xC3 (EXT) */, 438 -1 /* 0xC4 (EXT) */, 439 -1 /* 0xC5 (EXT) */, 440 -1 /* 0xC6 (EXT) */, 441 -1 /* 0xC7 (EXT) */, 442 -1 /* 0xC8 (EXT) */, 443 -1 /* 0xC9 (EXT) */, 444 -1 /* 0xCA (EXT) */, 445 -1 /* 0xCB (EXT) */, 446 -1 /* 0xCC (EXT) */, 447 -1 /* 0xCD (EXT) */, 448 -1 /* 0xCE (EXT) */, 449 -1 /* 0xCF (EXT) */, 450 -1 /* 0xD0 (EXT) */, 451 -1 /* 0xD1 (EXT) */, 452 -1 /* 0xD2 (EXT) */, 453 -1 /* 0xD3 (EXT) */, 454 -1 /* 0xD4 (EXT) */, 455 -1 /* 0xD5 (EXT) */, 456 -1 /* 0xD6 (EXT) */, 457 -1 /* 0xD7 (EXT) */, 458 -1 /* 0xD8 (EXT) */, 459 -1 /* 0xD9 (EXT) */, 460 -1 /* 0xDA (EXT) */, 461 -1 /* 0xDB (EXT) */, 462 -1 /* 0xDC (EXT) */, 463 -1 /* 0xDD (EXT) */, 464 -1 /* 0xDE (EXT) */, 465 -1 /* 0xDF (EXT) */, 466 -1 /* 0xE0 (EXT) */, 467 -1 /* 0xE1 (EXT) */, 468 -1 /* 0xE2 (EXT) */, 469 -1 /* 0xE3 (EXT) */, 470 -1 /* 0xE4 (EXT) */, 471 -1 /* 0xE5 (EXT) */, 472 -1 /* 0xE6 (EXT) */, 473 -1 /* 0xE7 (EXT) */, 474 -1 /* 0xE8 (EXT) */, 475 -1 /* 0xE9 (EXT) */, 476 -1 /* 0xEA (EXT) */, 477 -1 /* 0xEB (EXT) */, 478 -1 /* 0xEC (EXT) */, 479 -1 /* 0xED (EXT) */, 480 -1 /* 0xEE (EXT) */, 481 -1 /* 0xEF (EXT) */, 482 -1 /* 0xF0 (EXT) */, 483 -1 /* 0xF1 (EXT) */, 484 -1 /* 0xF2 (EXT) */, 485 -1 /* 0xF3 (EXT) */, 486 -1 /* 0xF4 (EXT) */, 487 -1 /* 0xF5 (EXT) */, 488 -1 /* 0xF6 (EXT) */, 489 -1 /* 0xF7 (EXT) */, 490 -1 /* 0xF8 (EXT) */, 491 -1 /* 0xF9 (EXT) */, 492 -1 /* 0xFA (EXT) */, 493 -1 /* 0xFB (EXT) */, 494 -1 /* 0xFC (EXT) */, 495 -1 /* 0xFD (EXT) */, 496 -1 /* 0xFE (EXT) */, 497 -1 /* 0xFF (EXT) */ 498 }; 499 return map_xdigit_to_value[uc]; 500 #else /* MHD_FAVOR_SMALL_CODE */ 501 unsigned int try_val; 502 503 try_val = uc - (unsigned char) '0'; 504 if (9 >= try_val) 505 return (int) (unsigned int) try_val; 506 try_val = (uc | 0x20u /* fold case */) - (unsigned char) 'a'; 507 if (5 >= try_val) 508 return (int) (unsigned int) (try_val + 10u); 509 510 return -1; 511 #endif /* MHD_FAVOR_SMALL_CODE */ 512 } 513 514 515 /** 516 * Convert 4 bit value to US-ASCII hexadecimal digit. 517 * 518 * @param v the value to convert, must be less then 16 519 * @return hexadecimal digit 520 */ 521 mhd_static_inline MHD_FN_CONST_ char 522 valuetoxdigit (unsigned int v) 523 { 524 #if ! defined(MHD_FAVOR_SMALL_CODE) 525 static const char map_value_to_xdigit[16] = 526 { '0', '1', '2', '3', '4', '5', '6', '7', 527 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 528 529 mhd_assert (16 > v); 530 531 return map_value_to_xdigit[v]; 532 #else /* MHD_FAVOR_SMALL_CODE */ 533 534 mhd_assert (16 > v); 535 536 if (v <= 9) 537 return '0' + (char) (v); 538 return 'a' + (char) (v - 10); 539 #endif /* MHD_FAVOR_SMALL_CODE */ 540 } 541 542 543 #if ! defined(MHD_FAVOR_SMALL_CODE) 544 /** 545 * Convert 8 bit value to two US-ASCII hexadecimal digits. 546 * 547 * @param v the value to convert 548 * @return pointer to char[2] with two hexadecimal digits 549 */ 550 mhd_static_inline MHD_FN_CONST_ MHD_FN_RETURNS_NONNULL_ const char* 551 uint8totwoxdigits (uint8_t v) 552 { 553 static const char map_uint8_to_two_xdigits[][2] = 554 { { '0', '0' }, 555 { '0', '1' }, 556 { '0', '2' }, 557 { '0', '3' }, 558 { '0', '4' }, 559 { '0', '5' }, 560 { '0', '6' }, 561 { '0', '7' }, 562 { '0', '8' }, 563 { '0', '9' }, 564 { '0', 'a' }, 565 { '0', 'b' }, 566 { '0', 'c' }, 567 { '0', 'd' }, 568 { '0', 'e' }, 569 { '0', 'f' }, 570 { '1', '0' }, 571 { '1', '1' }, 572 { '1', '2' }, 573 { '1', '3' }, 574 { '1', '4' }, 575 { '1', '5' }, 576 { '1', '6' }, 577 { '1', '7' }, 578 { '1', '8' }, 579 { '1', '9' }, 580 { '1', 'a' }, 581 { '1', 'b' }, 582 { '1', 'c' }, 583 { '1', 'd' }, 584 { '1', 'e' }, 585 { '1', 'f' }, 586 { '2', '0' }, 587 { '2', '1' }, 588 { '2', '2' }, 589 { '2', '3' }, 590 { '2', '4' }, 591 { '2', '5' }, 592 { '2', '6' }, 593 { '2', '7' }, 594 { '2', '8' }, 595 { '2', '9' }, 596 { '2', 'a' }, 597 { '2', 'b' }, 598 { '2', 'c' }, 599 { '2', 'd' }, 600 { '2', 'e' }, 601 { '2', 'f' }, 602 { '3', '0' }, 603 { '3', '1' }, 604 { '3', '2' }, 605 { '3', '3' }, 606 { '3', '4' }, 607 { '3', '5' }, 608 { '3', '6' }, 609 { '3', '7' }, 610 { '3', '8' }, 611 { '3', '9' }, 612 { '3', 'a' }, 613 { '3', 'b' }, 614 { '3', 'c' }, 615 { '3', 'd' }, 616 { '3', 'e' }, 617 { '3', 'f' }, 618 { '4', '0' }, 619 { '4', '1' }, 620 { '4', '2' }, 621 { '4', '3' }, 622 { '4', '4' }, 623 { '4', '5' }, 624 { '4', '6' }, 625 { '4', '7' }, 626 { '4', '8' }, 627 { '4', '9' }, 628 { '4', 'a' }, 629 { '4', 'b' }, 630 { '4', 'c' }, 631 { '4', 'd' }, 632 { '4', 'e' }, 633 { '4', 'f' }, 634 { '5', '0' }, 635 { '5', '1' }, 636 { '5', '2' }, 637 { '5', '3' }, 638 { '5', '4' }, 639 { '5', '5' }, 640 { '5', '6' }, 641 { '5', '7' }, 642 { '5', '8' }, 643 { '5', '9' }, 644 { '5', 'a' }, 645 { '5', 'b' }, 646 { '5', 'c' }, 647 { '5', 'd' }, 648 { '5', 'e' }, 649 { '5', 'f' }, 650 { '6', '0' }, 651 { '6', '1' }, 652 { '6', '2' }, 653 { '6', '3' }, 654 { '6', '4' }, 655 { '6', '5' }, 656 { '6', '6' }, 657 { '6', '7' }, 658 { '6', '8' }, 659 { '6', '9' }, 660 { '6', 'a' }, 661 { '6', 'b' }, 662 { '6', 'c' }, 663 { '6', 'd' }, 664 { '6', 'e' }, 665 { '6', 'f' }, 666 { '7', '0' }, 667 { '7', '1' }, 668 { '7', '2' }, 669 { '7', '3' }, 670 { '7', '4' }, 671 { '7', '5' }, 672 { '7', '6' }, 673 { '7', '7' }, 674 { '7', '8' }, 675 { '7', '9' }, 676 { '7', 'a' }, 677 { '7', 'b' }, 678 { '7', 'c' }, 679 { '7', 'd' }, 680 { '7', 'e' }, 681 { '7', 'f' }, 682 { '8', '0' }, 683 { '8', '1' }, 684 { '8', '2' }, 685 { '8', '3' }, 686 { '8', '4' }, 687 { '8', '5' }, 688 { '8', '6' }, 689 { '8', '7' }, 690 { '8', '8' }, 691 { '8', '9' }, 692 { '8', 'a' }, 693 { '8', 'b' }, 694 { '8', 'c' }, 695 { '8', 'd' }, 696 { '8', 'e' }, 697 { '8', 'f' }, 698 { '9', '0' }, 699 { '9', '1' }, 700 { '9', '2' }, 701 { '9', '3' }, 702 { '9', '4' }, 703 { '9', '5' }, 704 { '9', '6' }, 705 { '9', '7' }, 706 { '9', '8' }, 707 { '9', '9' }, 708 { '9', 'a' }, 709 { '9', 'b' }, 710 { '9', 'c' }, 711 { '9', 'd' }, 712 { '9', 'e' }, 713 { '9', 'f' }, 714 { 'a', '0' }, 715 { 'a', '1' }, 716 { 'a', '2' }, 717 { 'a', '3' }, 718 { 'a', '4' }, 719 { 'a', '5' }, 720 { 'a', '6' }, 721 { 'a', '7' }, 722 { 'a', '8' }, 723 { 'a', '9' }, 724 { 'a', 'a' }, 725 { 'a', 'b' }, 726 { 'a', 'c' }, 727 { 'a', 'd' }, 728 { 'a', 'e' }, 729 { 'a', 'f' }, 730 { 'b', '0' }, 731 { 'b', '1' }, 732 { 'b', '2' }, 733 { 'b', '3' }, 734 { 'b', '4' }, 735 { 'b', '5' }, 736 { 'b', '6' }, 737 { 'b', '7' }, 738 { 'b', '8' }, 739 { 'b', '9' }, 740 { 'b', 'a' }, 741 { 'b', 'b' }, 742 { 'b', 'c' }, 743 { 'b', 'd' }, 744 { 'b', 'e' }, 745 { 'b', 'f' }, 746 { 'c', '0' }, 747 { 'c', '1' }, 748 { 'c', '2' }, 749 { 'c', '3' }, 750 { 'c', '4' }, 751 { 'c', '5' }, 752 { 'c', '6' }, 753 { 'c', '7' }, 754 { 'c', '8' }, 755 { 'c', '9' }, 756 { 'c', 'a' }, 757 { 'c', 'b' }, 758 { 'c', 'c' }, 759 { 'c', 'd' }, 760 { 'c', 'e' }, 761 { 'c', 'f' }, 762 { 'd', '0' }, 763 { 'd', '1' }, 764 { 'd', '2' }, 765 { 'd', '3' }, 766 { 'd', '4' }, 767 { 'd', '5' }, 768 { 'd', '6' }, 769 { 'd', '7' }, 770 { 'd', '8' }, 771 { 'd', '9' }, 772 { 'd', 'a' }, 773 { 'd', 'b' }, 774 { 'd', 'c' }, 775 { 'd', 'd' }, 776 { 'd', 'e' }, 777 { 'd', 'f' }, 778 { 'e', '0' }, 779 { 'e', '1' }, 780 { 'e', '2' }, 781 { 'e', '3' }, 782 { 'e', '4' }, 783 { 'e', '5' }, 784 { 'e', '6' }, 785 { 'e', '7' }, 786 { 'e', '8' }, 787 { 'e', '9' }, 788 { 'e', 'a' }, 789 { 'e', 'b' }, 790 { 'e', 'c' }, 791 { 'e', 'd' }, 792 { 'e', 'e' }, 793 { 'e', 'f' }, 794 { 'f', '0' }, 795 { 'f', '1' }, 796 { 'f', '2' }, 797 { 'f', '3' }, 798 { 'f', '4' }, 799 { 'f', '5' }, 800 { 'f', '6' }, 801 { 'f', '7' }, 802 { 'f', '8' }, 803 { 'f', '9' }, 804 { 'f', 'a' }, 805 { 'f', 'b' }, 806 { 'f', 'c' }, 807 { 'f', 'd' }, 808 { 'f', 'e' }, 809 { 'f', 'f' } 810 #ifndef NDEBUG 811 , 812 { 0, 0 } 813 #endif /* ! NDEBUG */ 814 }; 815 816 mhd_assert (257u == \ 817 (sizeof(map_uint8_to_two_xdigits) \ 818 / sizeof(map_uint8_to_two_xdigits[0]))); 819 820 return map_uint8_to_two_xdigits[v]; 821 /** 822 * Indicates that function uint8totwoxdigits() is available 823 */ 824 #define mhd_HAVE_UINT8TOTWOXDIGITS 1 825 } 826 827 828 #endif /* ! MHD_FAVOR_SMALL_CODE */ 829 830 831 /** 832 * Caseless compare two characters. 833 * 834 * @param c1 the first char to compare 835 * @param c2 the second char to compare 836 * @return boolean 'true' if chars are caseless equal, false otherwise 837 */ 838 mhd_static_inline MHD_FN_CONST_ bool 839 charsequalcaseless (char c1, char c2) 840 { 841 if (c1 == c2) 842 return true; 843 /* Fold case on both sides */ 844 c1 = ((char) (~0x20u & (unsigned char) c1)); 845 c2 = ((char) (~0x20u & (unsigned char) c2)); 846 return (c1 == c2) && isasciiupper (c1); 847 } 848 849 850 /** 851 * Compare mixed case and lower case characters. 852 * 853 * @param mc the mixed case char to compare 854 * @param lc the lower case char to compare 855 * @return boolean 'true' if chars are caseless equal, false otherwise 856 */ 857 mhd_static_inline MHD_FN_CONST_ bool 858 charsequallowercase (char mc, char lc) 859 { 860 char uc; 861 if (mc == lc) 862 return true; 863 uc = ((char) (~0x20u & (unsigned char) lc)); 864 return (mc == uc) && isasciiupper (mc); 865 } 866 867 868 #else /* !HAVE_INLINE_FUNCS */ 869 870 871 /** 872 * Checks whether character is lower case letter in US-ASCII 873 * 874 * @param c character to check 875 * @return boolean true if character is lower case letter, 876 * boolean false otherwise 877 */ 878 # define isasciilower(c) ((((char) (c)) >= 'a') && (((char) (c)) <= 'z')) 879 880 881 /** 882 * Checks whether character is upper case letter in US-ASCII 883 * 884 * @param c character to check 885 * @return boolean true if character is upper case letter, 886 * boolean false otherwise 887 */ 888 # define isasciiupper(c) ((((char) (c)) <= 'Z') && (((char) (c)) >= 'A')) 889 890 891 /** 892 * Checks whether character is letter in US-ASCII 893 * 894 * @param c character to check 895 * @return boolean true if character is letter, boolean false 896 * otherwise 897 */ 898 # define isasciialpha(c) (isasciilower (c) || isasciiupper (c)) 899 900 901 /** 902 * Check whether character is decimal digit in US-ASCII 903 * 904 * @param c character to check 905 * @return boolean true if character is decimal digit, boolean false 906 * otherwise 907 */ 908 # define isasciidigit(c) ((((char) (c)) <= '9') && (((char) (c)) >= '0')) 909 910 911 /** 912 * Check whether character is hexadecimal digit in US-ASCII 913 * 914 * @param c character to check 915 * @return boolean true if character is hexadecimal digit, 916 * boolean false otherwise 917 */ 918 # define isasciixdigit(c) (isasciidigit ((c)) || \ 919 (((char) (c)) <= 'F' && ((char) (c)) >= 'A') || \ 920 (((char) (c)) <= 'f' && ((char) (c)) >= 'a')) 921 922 923 /** 924 * Check whether character is decimal digit or letter in US-ASCII 925 * 926 * @param c character to check 927 * @return boolean true if character is decimal digit or letter, 928 * boolean false otherwise 929 */ 930 # define isasciialnum(c) (isasciialpha (c) || isasciidigit (c)) 931 932 933 /** 934 * Convert US-ASCII character to lower case. 935 * If character is upper case letter in US-ASCII than it's converted to lower 936 * case analog. If character is NOT upper case letter than it's returned 937 * unmodified. 938 * 939 * @param c character to convert 940 * @return converted to lower case character 941 */ 942 # define toasciilower(c) \ 943 ((isasciiupper (c)) ? (((char) (c)) - 'A' + 'a') : ((char) (c))) 944 945 946 /** 947 * Convert US-ASCII character to upper case. 948 * If character is lower case letter in US-ASCII than it's converted to upper 949 * case analog. If character is NOT lower case letter than it's returned 950 * unmodified. 951 * 952 * @param c character to convert 953 * @return converted to upper case character 954 */ 955 # define toasciiupper(c) ((isasciilower (c)) ? (((char) (c)) - 'a' + 'A') : \ 956 ((char) (c))) 957 958 959 /** 960 * Convert US-ASCII decimal digit to its value. 961 * 962 * @param c character to convert 963 * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit 964 */ 965 # define todigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \ 966 (int) (-1)) 967 968 969 /** 970 * Convert US-ASCII hexadecimal digit to its value. 971 * @param c character to convert 972 * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit 973 */ 974 # define xdigittovalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \ 975 ( (((char) (c)) >= 'A' && ((char) (c)) <= 'F') ? \ 976 (int) (((unsigned char) (c)) - 'A' + 10) : \ 977 ( (((char) (c)) >= 'a' && ((char) (c)) <= 'f') ? \ 978 (int) (((unsigned char) (c)) - 'a' + 10) : \ 979 (int) (-1) ))) 980 981 982 #if ! defined(MHD_FAVOR_SMALL_CODE) 983 static const char map_value_to_xdigit[16] = 984 { '0', '1', '2', '3', '4', '5', '6', '7', 985 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 986 987 /** 988 * Convert 4 bit value to US-ASCII hexadecimal digit. 989 * 990 * @param v the value to convert, must be less then 16 991 * @return hexadecimal digit 992 */ 993 # define valuetoxdigit(v) map_value_to_xdigit[v] 994 #else /* MHD_FAVOR_SMALL_CODE */ 995 /** 996 * Convert 4 bit value to US-ASCII hexadecimal digit. 997 * 998 * @param v the value to convert, must be less then 16 999 * @return hexadecimal digit 1000 */ 1001 # define valuetoxdigit(v) \ 1002 (char) ((v <= 9) ? ('0' + (char) v) : ('a' + (char) v - 10)) 1003 #endif /* MHD_FAVOR_SMALL_CODE */ 1004 1005 /** 1006 * Caseless compare two characters. 1007 * 1008 * @param c1 the first char to compare 1009 * @param c2 the second char to compare 1010 * @return boolean 'true' if chars are caseless equal, false otherwise 1011 */ 1012 #define charsequalcaseless(c1, c2) \ 1013 (((c1) == (c2)) || \ 1014 (((0x20u | (unsigned char) (c1)) == (0x20u | (unsigned char) (c2))) \ 1015 && isasciilower (((char) (0x20u | (unsigned char) (c2))))) ) 1016 1017 /** 1018 * Compare mixed case and lower case characters. 1019 * 1020 * @param mc the mixed case char to compare 1021 * @param lc the lower case char to compare 1022 * @return boolean 'true' if chars are caseless equal, false otherwise 1023 */ 1024 #define charsequallowercase(mc,lc) \ 1025 ( ((mc) == (lc)) || \ 1026 (((0x20u | (unsigned char) (mc)) == ((unsigned char) (lc))) && \ 1027 isasciilower (lc)) ) 1028 #endif /* !HAVE_INLINE_FUNCS */ 1029 1030 1031 #ifndef MHD_FAVOR_SMALL_CODE 1032 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ 1033 MHD_FN_PAR_CSTR_ (1) MHD_FN_PAR_CSTR_ (2) bool 1034 mhd_str_equal_caseless (const char *str1, 1035 const char *str2) 1036 { 1037 while (0 != (*str1)) 1038 { 1039 const char c1 = *str1; 1040 const char c2 = *str2; 1041 if (charsequalcaseless (c1, c2)) 1042 { 1043 str1++; 1044 str2++; 1045 } 1046 else 1047 return false; 1048 } 1049 return 0 == (*str2); 1050 } 1051 1052 1053 #endif /* ! MHD_FAVOR_SMALL_CODE */ 1054 1055 1056 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ 1057 MHD_FN_PAR_IN_ (1) MHD_FN_PAR_IN_ (2) bool 1058 mhd_str_equal_caseless_n (const char *const str1, 1059 const char *const str2, 1060 size_t maxlen) 1061 { 1062 size_t i; 1063 1064 for (i = 0; i < maxlen; ++i) 1065 { 1066 const char c1 = str1[i]; 1067 const char c2 = str2[i]; 1068 if (0 == c2) 1069 return 0 == c1; 1070 if (charsequalcaseless (c1, c2)) 1071 continue; 1072 else 1073 return false; 1074 } 1075 return true; 1076 } 1077 1078 1079 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ 1080 MHD_FN_PAR_IN_ (1) MHD_FN_PAR_IN_ (2) bool 1081 mhd_str_equal_caseless_bin_n (const char *const str1, 1082 const char *const str2, 1083 size_t len) 1084 { 1085 size_t i; 1086 1087 for (i = 0; i < len; ++i) 1088 { 1089 const char c1 = str1[i]; 1090 const char c2 = str2[i]; 1091 if (charsequalcaseless (c1, c2)) 1092 continue; 1093 else 1094 return 0; 1095 } 1096 return ! 0; 1097 } 1098 1099 1100 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ 1101 MHD_FN_PAR_IN_ (1) 1102 MHD_FN_PAR_IN_ (2) bool 1103 mhd_str_equal_lowercase_bin_n (const char *const mixstr, 1104 const char *const lowstr, 1105 size_t len) 1106 { 1107 size_t i; 1108 1109 for (i = 0; i < len; ++i) 1110 { 1111 const char mc = mixstr[i]; 1112 const char lc = lowstr[i]; 1113 mhd_assert (! isasciiupper (lc)); 1114 if (! charsequallowercase (mc, lc)) 1115 return false; 1116 } 1117 return true; 1118 } 1119 1120 1121 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1122 MHD_FN_PAR_IN_SIZE_ (2,1) 1123 MHD_FN_PAR_OUT_SIZE_ (3,1) void 1124 mhd_str_to_lowercase_bin_n (size_t size, 1125 const char *restrict inbuff, 1126 char *restrict outbuff) 1127 { 1128 size_t i; 1129 1130 for (i = 0; i < size; ++i) 1131 outbuff[i] = toasciilower (inbuff[i]); 1132 } 1133 1134 1135 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1136 MHD_FN_PAR_IN_SIZE_ (2,1) bool 1137 mhd_str_is_lowercase_bin_n (size_t len, 1138 const char *restrict str) 1139 { 1140 size_t i; 1141 1142 for (i = 0; i < len; ++i) 1143 if (isasciiupper (str[i])) 1144 return false; 1145 1146 return true; 1147 } 1148 1149 1150 #ifdef mhd_HAVE_STR_TO_UPPER 1151 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1152 MHD_FN_PAR_IN_SIZE_ (2,1) 1153 MHD_FN_PAR_OUT_SIZE_ (3,1) void 1154 mhd_str_to_uppercase_bin_n (size_t size, 1155 const char *restrict inbuff, 1156 char *restrict outbuff) 1157 { 1158 size_t i; 1159 1160 for (i = 0; i < size; ++i) 1161 outbuff[i] = toasciiupper (inbuff[i]); 1162 } 1163 1164 1165 #endif /* mhd_HAVE_STR_TO_UPPER */ 1166 1167 1168 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ 1169 MHD_FN_PAR_CSTR_ (1) 1170 MHD_FN_PAR_IN_ (1) MHD_FN_PAR_IN_ (2) bool 1171 mhd_str_has_token_caseless (const char *restrict str, 1172 const char *const restrict token, 1173 size_t token_len) 1174 { 1175 if (0 == token_len) 1176 return false; 1177 1178 while (0 != *str) 1179 { 1180 size_t i; 1181 /* Skip all whitespaces and empty tokens. */ 1182 while (' ' == *str || '\t' == *str || ',' == *str) 1183 str++; 1184 1185 /* Check for token match. */ 1186 i = 0; 1187 while (1) 1188 { 1189 const char sc = *(str++); 1190 const char tc = token[i++]; 1191 1192 if (0 == sc) 1193 return false; 1194 if (! charsequalcaseless (sc, tc)) 1195 break; 1196 if (i >= token_len) 1197 { 1198 /* Check whether substring match token fully or 1199 * has additional unmatched chars at tail. */ 1200 while (' ' == *str || '\t' == *str) 1201 str++; 1202 /* End of (sub)string? */ 1203 if ((0 == *str) || (',' == *str) ) 1204 return true; 1205 /* Unmatched chars at end of substring. */ 1206 break; 1207 } 1208 } 1209 /* Find next substring. */ 1210 while (0 != *str && ',' != *str) 1211 str++; 1212 } 1213 return false; 1214 } 1215 1216 1217 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1218 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_IN_SIZE_ (3,4) 1219 MHD_FN_PAR_OUT_ (5) MHD_FN_PAR_INOUT_ (6) bool 1220 mhd_str_remove_token_caseless (const char *restrict str, 1221 size_t str_len, 1222 const char *const restrict token, 1223 const size_t token_len, 1224 char *restrict buf, 1225 ssize_t *restrict buf_size) 1226 { 1227 const char *s1; /**< the "input" string / character */ 1228 char *s2; /**< the "output" string / character */ 1229 size_t t_pos; /**< position of matched character in the token */ 1230 bool token_removed; 1231 1232 mhd_assert (NULL == memchr (token, 0, token_len)); 1233 mhd_assert (NULL == memchr (token, ' ', token_len)); 1234 mhd_assert (NULL == memchr (token, '\t', token_len)); 1235 mhd_assert (NULL == memchr (token, ',', token_len)); 1236 mhd_assert (0 <= *buf_size); 1237 1238 if (SSIZE_MAX <= ((str_len / 2) * 3 + 3)) 1239 { 1240 /* The return value may overflow, refuse */ 1241 *buf_size = (ssize_t) -1; 1242 return false; 1243 } 1244 s1 = str; 1245 s2 = buf; 1246 token_removed = false; 1247 1248 while ((size_t) (s1 - str) < str_len) 1249 { 1250 const char *cur_token; /**< the first char of current token */ 1251 size_t copy_size; 1252 1253 /* Skip any initial whitespaces and empty tokens */ 1254 while ( ((size_t) (s1 - str) < str_len) && 1255 ((' ' == *s1) || ('\t' == *s1) || (',' == *s1)) ) 1256 s1++; 1257 1258 /* 's1' points to the first char of token in the input string or 1259 * points just beyond the end of the input string */ 1260 1261 if ((size_t) (s1 - str) >= str_len) 1262 break; /* Nothing to copy, end of the input string */ 1263 1264 /* 's1' points to the first char of token in the input string */ 1265 1266 cur_token = s1; /* the first char of input token */ 1267 1268 /* Check the token with case-insensetive match */ 1269 t_pos = 0; 1270 while ( ((size_t) (s1 - str) < str_len) && (token_len > t_pos) && 1271 (charsequalcaseless (*s1, token[t_pos])) ) 1272 { 1273 s1++; 1274 t_pos++; 1275 } 1276 /* s1 may point just beyond the end of the input string */ 1277 if ( (token_len == t_pos) && (0 != token_len) ) 1278 { 1279 /* 'token' matched, check that current input token does not have 1280 * any suffixes */ 1281 while ( ((size_t) (s1 - str) < str_len) && 1282 ((' ' == *s1) || ('\t' == *s1)) ) 1283 s1++; 1284 /* 's1' points to the first non-whitespace char after the token matched 1285 * requested token or points just beyond the end of the input string after 1286 * the requested token */ 1287 if (((size_t) (s1 - str) == str_len) || (',' == *s1)) 1288 {/* full token match, do not copy current token to the output */ 1289 token_removed = true; 1290 continue; 1291 } 1292 } 1293 1294 /* 's1' points to first non-whitespace char, to some char after 1295 * first non-whitespace char in the token in the input string, to 1296 * the ',', or just beyond the end of the input string */ 1297 /* The current token in the input string does not match the token 1298 * to exclude, it must be copied to the output string */ 1299 /* the current token size excluding leading whitespaces and current char */ 1300 copy_size = (size_t) (s1 - cur_token); 1301 if (buf == s2) 1302 { /* The first token to copy to the output */ 1303 if ((size_t) *buf_size < copy_size) 1304 { /* Not enough space in the output buffer */ 1305 *buf_size = (ssize_t) -1; 1306 return false; 1307 } 1308 } 1309 else 1310 { /* Some token was already copied to the output buffer */ 1311 mhd_assert (s2 > buf); 1312 if ((size_t) *buf_size < ((size_t) (s2 - buf)) + copy_size + 2) 1313 { /* Not enough space in the output buffer */ 1314 *buf_size = (ssize_t) -1; 1315 return false; 1316 } 1317 *(s2++) = ','; 1318 *(s2++) = ' '; 1319 } 1320 /* Copy non-matched token to the output */ 1321 if (0 != copy_size) 1322 { 1323 memcpy (s2, cur_token, copy_size); 1324 s2 += copy_size; 1325 } 1326 1327 while ( ((size_t) (s1 - str) < str_len) && (',' != *s1)) 1328 { 1329 /* 's1' points to first non-whitespace char, to some char after 1330 * first non-whitespace char in the token in the input string */ 1331 /* Copy all non-whitespace chars from the current token in 1332 * the input string */ 1333 while ( ((size_t) (s1 - str) < str_len) && 1334 (',' != *s1) && (' ' != *s1) && ('\t' != *s1) ) 1335 { 1336 mhd_assert (s2 >= buf); 1337 if ((size_t) *buf_size <= (size_t) (s2 - buf)) /* '<= s2' equals '< s2 + 1' */ 1338 { /* Not enough space in the output buffer */ 1339 *buf_size = (ssize_t) -1; 1340 return false; 1341 } 1342 *(s2++) = *(s1++); 1343 } 1344 /* 's1' points to some whitespace char in the token in the input 1345 * string, to the ',', or just beyond the end of the input string */ 1346 /* Skip all whitespaces */ 1347 while ( ((size_t) (s1 - str) < str_len) && 1348 ((' ' == *s1) || ('\t' == *s1)) ) 1349 s1++; 1350 1351 /* 's1' points to the first non-whitespace char in the input string 1352 * after whitespace chars, to the ',', or just beyond the end of 1353 * the input string */ 1354 if (((size_t) (s1 - str) < str_len) && (',' != *s1)) 1355 { /* Not the end of the current token */ 1356 mhd_assert (s2 >= buf); 1357 if ((size_t) *buf_size <= (size_t) (s2 - buf)) /* '<= s2' equals '< s2 + 1' */ 1358 { /* Not enough space in the output buffer */ 1359 *buf_size = (ssize_t) -1; 1360 return false; 1361 } 1362 *(s2++) = ' '; 1363 } 1364 } 1365 } 1366 mhd_assert (((ssize_t) (s2 - buf)) <= *buf_size); 1367 *buf_size = (ssize_t) (s2 - buf); 1368 return token_removed; 1369 } 1370 1371 1372 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1373 MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_INOUT_ (2) 1374 MHD_FN_PAR_IN_SIZE_ (3,4) bool 1375 mhd_str_remove_tokens_caseless (char *restrict str, 1376 size_t *restrict str_len, 1377 const char *const restrict tkns, 1378 const size_t tkns_len) 1379 { 1380 size_t pt; /**< position in @a tokens */ 1381 bool token_removed; 1382 1383 mhd_assert (NULL == memchr (tkns, 0, tkns_len)); 1384 1385 token_removed = false; 1386 pt = 0; 1387 1388 while (pt < tkns_len && *str_len != 0) 1389 { 1390 const char *tkn; /**< the current token */ 1391 size_t tkn_len; 1392 1393 /* Skip any initial whitespaces and empty tokens in 'tokens' */ 1394 while ( (pt < tkns_len) && 1395 ((' ' == tkns[pt]) || ('\t' == tkns[pt]) || (',' == tkns[pt])) ) 1396 pt++; 1397 1398 if (pt >= tkns_len) 1399 break; /* No more tokens, nothing to remove */ 1400 1401 /* Found non-whitespace char which is not a comma */ 1402 tkn = tkns + pt; 1403 do 1404 { 1405 do 1406 { 1407 pt++; 1408 } while (pt < tkns_len && 1409 (' ' != tkns[pt] && '\t' != tkns[pt] && ',' != tkns[pt])); 1410 /* Found end of the token string, space, tab, or comma */ 1411 tkn_len = pt - (size_t) (tkn - tkns); 1412 1413 /* Skip all spaces and tabs */ 1414 while (pt < tkns_len && (' ' == tkns[pt] || '\t' == tkns[pt])) 1415 pt++; 1416 /* Found end of the token string or non-whitespace char */ 1417 } while (pt < tkns_len && ',' != tkns[pt]); 1418 1419 /* 'tkn' is the input token with 'tkn_len' chars */ 1420 mhd_assert (0 != tkn_len); 1421 1422 if (*str_len == tkn_len) 1423 { 1424 if (mhd_str_equal_caseless_bin_n (str, tkn, tkn_len)) 1425 { 1426 *str_len = 0; 1427 token_removed = true; 1428 } 1429 continue; 1430 } 1431 /* 'tkn' cannot match part of 'str' if length of 'tkn' is larger 1432 * than length of 'str'. 1433 * It's know that 'tkn' is not equal to the 'str' (was checked previously). 1434 * As 'str' is normalized when 'tkn' is not equal to the 'str' 1435 * it is required that 'str' to be at least 3 chars larger then 'tkn' 1436 * (the comma, the space and at least one additional character for the next 1437 * token) to remove 'tkn' from the 'str'. */ 1438 if (*str_len > tkn_len + 2) 1439 { /* Remove 'tkn' from the input string */ 1440 size_t pr; /**< the 'read' position in the @a str */ 1441 size_t pw; /**< the 'write' position in the @a str */ 1442 1443 pr = 0; 1444 pw = 0; 1445 1446 do 1447 { 1448 mhd_assert (pr >= pw); 1449 mhd_assert ((*str_len) >= (pr + tkn_len)); 1450 if ( ( ((*str_len) == (pr + tkn_len)) || (',' == str[pr + tkn_len]) ) && 1451 mhd_str_equal_caseless_bin_n (str + pr, tkn, tkn_len) ) 1452 { 1453 /* current token in the input string matches the 'tkn', skip it */ 1454 mhd_assert ((*str_len == pr + tkn_len) || \ 1455 (' ' == str[pr + tkn_len + 1])); /* 'str' must be normalized */ 1456 token_removed = true; 1457 /* Advance to the next token in the input string or beyond 1458 * the end of the input string. */ 1459 pr += tkn_len + 2; 1460 } 1461 else 1462 { 1463 /* current token in the input string does not match the 'tkn', 1464 * copy to the output */ 1465 if (0 != pw) 1466 { /* not the first output token, add ", " to separate */ 1467 if (pr != pw + 2) 1468 { 1469 str[pw++] = ','; 1470 str[pw++] = ' '; 1471 } 1472 else 1473 pw += 2; /* 'str' is not yet modified in this round */ 1474 } 1475 do 1476 { 1477 if (pr != pw) 1478 str[pw] = str[pr]; 1479 pr++; 1480 pw++; 1481 } while (pr < *str_len && ',' != str[pr]); 1482 /* Advance to the next token in the input string or beyond 1483 * the end of the input string. */ 1484 pr += 2; 1485 } 1486 /* 'pr' should point to the next token in the input string or beyond 1487 * the end of the input string */ 1488 if ((*str_len) < (pr + tkn_len)) 1489 { /* The rest of the 'str + pr' is too small to match 'tkn' */ 1490 if ((*str_len) > pr) 1491 { /* Copy the rest of the string */ 1492 size_t copy_size; 1493 copy_size = *str_len - pr; 1494 if (0 != pw) 1495 { /* not the first output token, add ", " to separate */ 1496 if (pr != pw + 2) 1497 { 1498 str[pw++] = ','; 1499 str[pw++] = ' '; 1500 } 1501 else 1502 pw += 2; /* 'str' is not yet modified in this round */ 1503 } 1504 if (pr != pw) 1505 memmove (str + pw, str + pr, copy_size); 1506 pw += copy_size; 1507 } 1508 *str_len = pw; 1509 break; 1510 } 1511 mhd_assert ((' ' != str[0]) && ('\t' != str[0])); 1512 mhd_assert ((0 == pr) || (3 <= pr)); 1513 mhd_assert ((0 == pr) || (' ' == str[pr - 1])); 1514 mhd_assert ((0 == pr) || (',' == str[pr - 2])); 1515 } while (1); 1516 } 1517 } 1518 1519 return token_removed; 1520 } 1521 1522 1523 #ifndef MHD_FAVOR_SMALL_CODE 1524 /* Use individual function for each case */ 1525 1526 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1527 MHD_FN_PAR_CSTR_ (1) MHD_FN_PAR_IN_ (1) 1528 MHD_FN_PAR_OUT_ (2) size_t 1529 mhd_str_to_uint64 (const char *restrict str, 1530 uint_fast64_t *restrict out_val) 1531 { 1532 const char *const start = str; 1533 uint_fast64_t res; 1534 1535 if (! isasciidigit (str[0])) 1536 return 0; 1537 1538 res = 0; 1539 do 1540 { 1541 const int digit = (unsigned char) (*str) - '0'; 1542 uint_fast64_t prev_res = res; 1543 1544 res *= 10; 1545 if (res / 10 != prev_res) 1546 return 0; 1547 res += (unsigned int) digit; 1548 if (res < (unsigned int) digit) 1549 return 0; 1550 1551 str++; 1552 } while (isasciidigit (*str)); 1553 1554 *out_val = res; 1555 return (size_t) (str - start); 1556 } 1557 1558 1559 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1560 MHD_FN_PAR_IN_SIZE_ (1,2) 1561 MHD_FN_PAR_OUT_ (3) size_t 1562 mhd_str_to_uint64_n (const char *restrict str, 1563 size_t maxlen, 1564 uint_fast64_t *restrict out_val) 1565 { 1566 uint_fast64_t res; 1567 size_t i; 1568 1569 if (! maxlen || ! isasciidigit (str[0])) 1570 return 0; 1571 1572 res = 0; 1573 i = 0; 1574 do 1575 { 1576 const int digit = (unsigned char) str[i] - '0'; 1577 uint_fast64_t prev_res = res; 1578 1579 res *= 10; 1580 if (res / 10 != prev_res) 1581 return 0; 1582 res += (unsigned int) digit; 1583 if (res < (unsigned int) digit) 1584 return 0; 1585 i++; 1586 } while ( (i < maxlen) && 1587 isasciidigit (str[i]) ); 1588 1589 *out_val = res; 1590 return i; 1591 } 1592 1593 1594 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1595 MHD_FN_PAR_CSTR_ (1) 1596 MHD_FN_PAR_IN_ (1) MHD_FN_PAR_OUT_ (2) size_t 1597 mhd_strx_to_uint32 (const char *restrict str, 1598 uint_fast32_t *restrict out_val) 1599 { 1600 const char *const start = str; 1601 uint_fast32_t res; 1602 int digit; 1603 1604 res = 0; 1605 digit = xdigittovalue (*str); 1606 while (digit >= 0) 1607 { 1608 uint_fast32_t prev_res = res; 1609 1610 res *= 16; 1611 if (res / 16 != prev_res) 1612 return 0; 1613 res += (unsigned int) digit; 1614 if (res < (unsigned int) digit) 1615 return 0; 1616 1617 str++; 1618 digit = xdigittovalue (*str); 1619 } 1620 1621 if (str - start > 0) 1622 *out_val = res; 1623 return (size_t) (str - start); 1624 } 1625 1626 1627 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1628 MHD_FN_PAR_IN_SIZE_ (1,2) 1629 MHD_FN_PAR_OUT_ (3) size_t 1630 mhd_strx_to_uint32_n (const char *restrict str, 1631 size_t maxlen, 1632 uint_fast32_t *restrict out_val) 1633 { 1634 size_t i; 1635 uint_fast32_t res; 1636 1637 res = 0; 1638 i = 0; 1639 while (i < maxlen) 1640 { 1641 const int digit = xdigittovalue (str[i]); 1642 uint_fast32_t prev_res = res; 1643 1644 if (0 > digit) 1645 break; 1646 1647 res *= 16; 1648 if (res / 16 != prev_res) 1649 return 0; 1650 res += (uint_fast32_t) digit; 1651 if (res < (uint_fast32_t) digit) 1652 return 0; 1653 1654 i++; 1655 } 1656 1657 if (0 != i) 1658 *out_val = res; 1659 return i; 1660 } 1661 1662 1663 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1664 MHD_FN_PAR_CSTR_ (1) 1665 MHD_FN_PAR_IN_ (1) MHD_FN_PAR_OUT_ (2) size_t 1666 mhd_strx_to_uint64 (const char *restrict str, 1667 uint_fast64_t *restrict out_val) 1668 { 1669 const char *const start = str; 1670 uint_fast64_t res; 1671 int digit; 1672 1673 res = 0; 1674 digit = xdigittovalue (*str); 1675 while (digit >= 0) 1676 { 1677 uint_fast64_t prev_res = res; 1678 1679 res *= 16; 1680 if (res / 16 != prev_res) 1681 return 0; 1682 res += (unsigned int) digit; 1683 if (res < (unsigned int) digit) 1684 return 0; 1685 1686 str++; 1687 digit = xdigittovalue (*str); 1688 } 1689 1690 if (str - start > 0) 1691 *out_val = res; 1692 return (size_t) (str - start); 1693 } 1694 1695 1696 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1697 MHD_FN_PAR_IN_SIZE_ (1,2) 1698 MHD_FN_PAR_OUT_ (3) size_t 1699 mhd_strx_to_uint64_n (const char *restrict str, 1700 size_t maxlen, 1701 uint_fast64_t *restrict out_val) 1702 { 1703 size_t i; 1704 uint_fast64_t res; 1705 1706 res = 0; 1707 i = 0; 1708 while (i < maxlen) 1709 { 1710 const int digit = xdigittovalue (str[i]); 1711 uint_fast64_t prev_res = res; 1712 1713 if (0 > digit) 1714 break; 1715 1716 res *= 16; 1717 if (res / 16 != prev_res) 1718 return 0; 1719 res += (unsigned int) digit; 1720 if (res < (unsigned int) digit) 1721 return 0; 1722 i++; 1723 } 1724 1725 if (0 != i) 1726 *out_val = res; 1727 return i; 1728 } 1729 1730 1731 #else /* MHD_FAVOR_SMALL_CODE */ 1732 1733 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1734 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_SIZE_ (3,4) size_t 1735 mhd_str_to_uvalue_n (const char *restrict str, 1736 size_t maxlen, 1737 void *restrict out_val, 1738 size_t val_size, 1739 uint_fast64_t max_val, 1740 unsigned int base) 1741 { 1742 size_t i; 1743 uint_fast64_t res; 1744 const uint_fast64_t max_v_div_b = max_val / base; 1745 const uint_fast64_t max_v_mod_b = max_val % base; 1746 1747 if ((base != 16) && (base != 10)) 1748 return 0; 1749 1750 res = 0; 1751 i = 0; 1752 while (maxlen > i) 1753 { 1754 const int digit = (base == 16) ? 1755 xdigittovalue (str[i]) : todigitvalue (str[i]); 1756 1757 if (0 > digit) 1758 break; 1759 if ( ((max_v_div_b) < res) || 1760 (( (max_v_div_b) == res) && 1761 ( (max_v_mod_b) < (uint_fast64_t) digit) ) ) 1762 return 0; 1763 1764 res *= base; 1765 res += (unsigned int) digit; 1766 i++; 1767 } 1768 1769 if (i) 1770 { 1771 if (8 == val_size) 1772 *(uint_fast64_t *) out_val = res; 1773 else if (4 == val_size) 1774 *(uint_fast32_t *) out_val = (uint_fast32_t) res; 1775 else 1776 return 0; 1777 } 1778 return i; 1779 } 1780 1781 1782 #endif /* MHD_FAVOR_SMALL_CODE */ 1783 1784 1785 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1786 MHD_FN_PAR_OUT_SIZE_ (2,3) size_t 1787 mhd_uint32_to_strx (uint_fast32_t val, 1788 char *buf, 1789 size_t buf_size) 1790 { 1791 size_t o_pos = 0; /**< position of the output character */ 1792 int digit_pos = 8; /** zero-based, digit position in @a 'val' */ 1793 uint_least32_t val32 = ((uint_least32_t) val) & 0xFFFFFFFFu; 1794 unsigned int xdigit; 1795 1796 /* Skip leading zeros */ 1797 do 1798 { 1799 digit_pos--; 1800 xdigit = (unsigned int) (val32 >> 28); 1801 val32 <<= 4; 1802 val32 &= 0xFFFFFFFFu; 1803 } while ((0 == xdigit) && (0 != digit_pos)); 1804 1805 while (o_pos < buf_size) 1806 { 1807 buf[o_pos++] = valuetoxdigit (xdigit); 1808 if (0 == digit_pos) 1809 return o_pos; 1810 digit_pos--; 1811 xdigit = (unsigned int) (val32 >> 28); 1812 val32 <<= 4; 1813 val32 &= 0xFFFFFFFFu; 1814 } 1815 return 0; /* The buffer is too small */ 1816 } 1817 1818 1819 #ifndef MHD_FAVOR_SMALL_CODE 1820 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1821 MHD_FN_PAR_OUT_SIZE_ (2,3) size_t 1822 mhd_uint16_to_str (uint_least16_t val, 1823 char *buf, 1824 size_t buf_size) 1825 { 1826 char *chr; /**< pointer to the current printed digit */ 1827 /* The biggest printable number is 65535 */ 1828 uint_least16_t divisor = UINT16_C (10000); 1829 int digit; 1830 1831 val &= 0xFFFFu; 1832 chr = buf; 1833 digit = (int) (val / divisor); 1834 mhd_assert (digit < 10); 1835 1836 /* Do not print leading zeros */ 1837 while ((0 == digit) && (1 < divisor)) 1838 { 1839 divisor /= 10; 1840 digit = (int) (val / divisor); 1841 mhd_assert (digit < 10); 1842 } 1843 1844 while (0 != buf_size) 1845 { 1846 *chr = (char) ((char) digit + '0'); 1847 chr++; 1848 buf_size--; 1849 if (1 == divisor) 1850 return (size_t) (chr - buf); 1851 val = (uint_least16_t) (val % divisor); 1852 divisor /= 10; 1853 digit = (int) (val / divisor); 1854 mhd_assert (digit < 10); 1855 } 1856 return 0; /* The buffer is too small */ 1857 } 1858 1859 1860 #endif /* !MHD_FAVOR_SMALL_CODE */ 1861 1862 1863 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1864 MHD_FN_PAR_OUT_SIZE_ (2,3) size_t 1865 mhd_uint64_to_str (uint_fast64_t val, 1866 char *buf, 1867 size_t buf_size) 1868 { 1869 char *chr; /**< pointer to the current printed digit */ 1870 /* The biggest printable number is 18446744073709551615 */ 1871 uint_fast64_t divisor = (uint_fast64_t) 10000000000000000000U; 1872 int digit; 1873 1874 val &= 0xFFFFFFFFFFFFFFFFu; 1875 chr = buf; 1876 digit = (int) (val / divisor); 1877 mhd_assert (digit < 10); 1878 1879 /* Do not print leading zeros */ 1880 while ((0 == digit) && (1 < divisor)) 1881 { 1882 divisor /= 10; 1883 digit = (int) (val / divisor); 1884 mhd_assert (digit < 10); 1885 } 1886 1887 while (0 != buf_size) 1888 { 1889 *chr = (char) ((char) digit + '0'); 1890 chr++; 1891 buf_size--; 1892 if (1 == divisor) 1893 return (size_t) (chr - buf); 1894 val %= divisor; 1895 divisor /= 10; 1896 digit = (int) (val / divisor); 1897 mhd_assert (digit < 10); 1898 } 1899 return 0; /* The buffer is too small */ 1900 } 1901 1902 1903 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1904 MHD_FN_PAR_OUT_SIZE_ (3,4) size_t 1905 mhd_uint8_to_str_pad (uint8_t val, 1906 uint8_t min_digits, 1907 char *buf, 1908 size_t buf_size) 1909 { 1910 size_t pos; /**< the position of the current printed digit */ 1911 int digit; 1912 mhd_assert (3 >= min_digits); 1913 1914 pos = 0; 1915 digit = val / 100; 1916 if (0 == digit) 1917 { 1918 if (3 <= min_digits) 1919 buf[pos++] = '0'; 1920 } 1921 else 1922 { 1923 buf[pos++] = (char) ('0' + (char) digit); 1924 val %= 100; 1925 min_digits = 2; 1926 } 1927 1928 if (buf_size <= pos) 1929 return 0; 1930 digit = val / 10; 1931 if (0 == digit) 1932 { 1933 if (2 <= min_digits) 1934 buf[pos++] = '0'; 1935 } 1936 else 1937 { 1938 buf[pos++] = (char) ('0' + (char) digit); 1939 val %= 10; 1940 } 1941 1942 if (buf_size <= pos) 1943 return 0; 1944 buf[pos++] = (char) ('0' + (char) val); 1945 return pos; 1946 } 1947 1948 1949 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1950 MHD_FN_PAR_IN_SIZE_ (1, 2) MHD_FN_PAR_OUT_ (3) size_t 1951 mhd_bin_to_hex (const void *restrict bin, 1952 size_t size, 1953 char *restrict hex) 1954 { 1955 size_t i; 1956 1957 for (i = 0; i < size; ++i) 1958 { 1959 const uint8_t b = ((const uint8_t *) bin)[i]; 1960 #ifdef mhd_HAVE_UINT8TOTWOXDIGITS 1961 const char *two_xdigits = uint8totwoxdigits (b); 1962 hex[i * 2] = two_xdigits[0]; 1963 hex[i * 2 + 1] = two_xdigits[1]; 1964 #else /* ! mhd_HAVE_UINT8TOTWOXDIGITS */ 1965 hex[i * 2] = valuetoxdigit (b >> 4); 1966 hex[i * 2 + 1] = valuetoxdigit (b & 0x0Fu); 1967 #endif /* ! mhd_HAVE_UINT8TOTWOXDIGITS */ 1968 } 1969 return i * 2; 1970 } 1971 1972 1973 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1974 MHD_FN_PAR_IN_SIZE_ (1, 2) MHD_FN_PAR_OUT_ (3) size_t 1975 mhd_bin_to_hex_z (const void *restrict bin, 1976 size_t size, 1977 char *restrict hex) 1978 { 1979 size_t res; 1980 1981 res = mhd_bin_to_hex (bin, size, hex); 1982 hex[res] = 0; 1983 1984 return res; 1985 } 1986 1987 1988 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1989 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_ (3) size_t 1990 mhd_hex_to_bin (const char *restrict hex, 1991 size_t len, 1992 void *restrict bin) 1993 { 1994 size_t r; 1995 size_t w; 1996 1997 r = 0; 1998 w = 0; 1999 if (0 != len % 2) 2000 { 2001 /* Assume the first byte is encoded with single digit */ 2002 const char c2 = hex[r++]; 2003 const int l = xdigittovalue (c2); 2004 if (0 > l) 2005 return 0; 2006 ((uint8_t *) bin)[w++] = (uint8_t) ((unsigned int) l); 2007 } 2008 while (r < len) 2009 { 2010 const char c1 = hex[r++]; 2011 const char c2 = hex[r++]; 2012 const int h = xdigittovalue (c1); 2013 const int l = xdigittovalue (c2); 2014 if ((0 > h) || (0 > l)) 2015 return 0; 2016 ((uint8_t *) bin)[w++] = 2017 (uint8_t) ( ((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2018 | ((uint8_t) ((unsigned int) l)) ); 2019 } 2020 mhd_assert (len == r); 2021 mhd_assert ((len + 1) / 2 == w); 2022 return w; 2023 } 2024 2025 2026 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 2027 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_SIZE_ (3,4) size_t 2028 mhd_str_pct_decode_strict_n (const char *pct_encoded, 2029 size_t pct_encoded_len, 2030 char *decoded, 2031 size_t buf_size) 2032 { 2033 #ifdef MHD_FAVOR_SMALL_CODE 2034 bool broken; 2035 size_t res; 2036 2037 res = mhd_str_pct_decode_lenient_n (pct_encoded, pct_encoded_len, decoded, 2038 buf_size, &broken); 2039 if (broken) 2040 return 0; 2041 return res; 2042 #else /* ! MHD_FAVOR_SMALL_CODE */ 2043 size_t r; 2044 size_t w; 2045 r = 0; 2046 w = 0; 2047 2048 if (buf_size >= pct_encoded_len) 2049 { 2050 while (r < pct_encoded_len) 2051 { 2052 const char chr = pct_encoded[r]; 2053 if ('%' == chr) 2054 { 2055 if (2 > pct_encoded_len - r) 2056 return 0; 2057 else 2058 { 2059 const char c1 = pct_encoded[++r]; 2060 const char c2 = pct_encoded[++r]; 2061 const int h = xdigittovalue (c1); 2062 const int l = xdigittovalue (c2); 2063 unsigned char out; 2064 if ((0 > h) || (0 > l)) 2065 return 0; 2066 out = 2067 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2068 | ((uint8_t) ((unsigned int) l))); 2069 decoded[w] = (char) out; 2070 } 2071 } 2072 else 2073 decoded[w] = chr; 2074 ++r; 2075 ++w; 2076 } 2077 return w; 2078 } 2079 2080 while (r < pct_encoded_len) 2081 { 2082 const char chr = pct_encoded[r]; 2083 if (w >= buf_size) 2084 return 0; 2085 if ('%' == chr) 2086 { 2087 if (2 > pct_encoded_len - r) 2088 return 0; 2089 else 2090 { 2091 const char c1 = pct_encoded[++r]; 2092 const char c2 = pct_encoded[++r]; 2093 const int h = xdigittovalue (c1); 2094 const int l = xdigittovalue (c2); 2095 unsigned char out; 2096 if ((0 > h) || (0 > l)) 2097 return 0; 2098 out = 2099 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2100 | ((uint8_t) ((unsigned int) l))); 2101 decoded[w] = (char) out; 2102 } 2103 } 2104 else 2105 decoded[w] = chr; 2106 ++r; 2107 ++w; 2108 } 2109 return w; 2110 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2111 } 2112 2113 2114 MHD_INTERNAL 2115 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) 2116 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_SIZE_ (3,4) size_t 2117 mhd_str_pct_decode_lenient_n (const char *pct_encoded, 2118 size_t pct_encoded_len, 2119 char *decoded, 2120 size_t buf_size, 2121 bool *restrict broken_encoding) 2122 { 2123 size_t r; 2124 size_t w; 2125 r = 0; 2126 w = 0; 2127 if (NULL != broken_encoding) 2128 *broken_encoding = false; 2129 #ifndef MHD_FAVOR_SMALL_CODE 2130 if (buf_size >= pct_encoded_len) 2131 { 2132 while (r < pct_encoded_len) 2133 { 2134 const char chr = pct_encoded[r]; 2135 if ('%' == chr) 2136 { 2137 if (2 > pct_encoded_len - r) 2138 { 2139 if (NULL != broken_encoding) 2140 *broken_encoding = true; 2141 decoded[w] = chr; /* Copy "as is" */ 2142 } 2143 else 2144 { 2145 const char c1 = pct_encoded[++r]; 2146 const char c2 = pct_encoded[++r]; 2147 const int h = xdigittovalue (c1); 2148 const int l = xdigittovalue (c2); 2149 unsigned char out; 2150 if ((0 > h) || (0 > l)) 2151 { 2152 r -= 2; 2153 if (NULL != broken_encoding) 2154 *broken_encoding = true; 2155 decoded[w] = chr; /* Copy "as is" */ 2156 } 2157 else 2158 { 2159 out = 2160 (unsigned char) 2161 (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2162 | ((uint8_t) ((unsigned int) l))); 2163 decoded[w] = (char) out; 2164 } 2165 } 2166 } 2167 else 2168 decoded[w] = chr; 2169 ++r; 2170 ++w; 2171 } 2172 return w; 2173 } 2174 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2175 while (r < pct_encoded_len) 2176 { 2177 const char chr = pct_encoded[r]; 2178 if (w >= buf_size) 2179 return 0; 2180 if ('%' == chr) 2181 { 2182 if (2 > pct_encoded_len - r) 2183 { 2184 if (NULL != broken_encoding) 2185 *broken_encoding = true; 2186 decoded[w] = chr; /* Copy "as is" */ 2187 } 2188 else 2189 { 2190 const char c1 = pct_encoded[++r]; 2191 const char c2 = pct_encoded[++r]; 2192 const int h = xdigittovalue (c1); 2193 const int l = xdigittovalue (c2); 2194 if ((0 > h) || (0 > l)) 2195 { 2196 r -= 2; 2197 if (NULL != broken_encoding) 2198 *broken_encoding = true; 2199 decoded[w] = chr; /* Copy "as is" */ 2200 } 2201 else 2202 { 2203 unsigned char out; 2204 out = 2205 (unsigned char) 2206 (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2207 | ((uint8_t) ((unsigned int) l))); 2208 decoded[w] = (char) out; 2209 } 2210 } 2211 } 2212 else 2213 decoded[w] = chr; 2214 ++r; 2215 ++w; 2216 } 2217 return w; 2218 } 2219 2220 2221 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 2222 MHD_FN_PAR_CSTR_ (1) size_t 2223 mhd_str_pct_decode_in_place_strict (char *str) 2224 { 2225 #ifdef MHD_FAVOR_SMALL_CODE 2226 size_t res; 2227 bool broken; 2228 2229 res = mhd_str_pct_decode_in_place_lenient (str, &broken); 2230 if (broken) 2231 { 2232 res = 0; 2233 str[0] = 0; 2234 } 2235 return res; 2236 #else /* ! MHD_FAVOR_SMALL_CODE */ 2237 size_t r; 2238 size_t w; 2239 r = 0; 2240 w = 0; 2241 2242 while (0 != str[r]) 2243 { 2244 const char chr = str[r++]; 2245 if ('%' == chr) 2246 { 2247 const char d1 = str[r++]; 2248 if (0 == d1) 2249 return 0; 2250 else 2251 { 2252 const char d2 = str[r++]; 2253 if (0 == d2) 2254 return 0; 2255 else 2256 { 2257 const int h = xdigittovalue (d1); 2258 const int l = xdigittovalue (d2); 2259 unsigned char out; 2260 if ((0 > h) || (0 > l)) 2261 return 0; 2262 out = 2263 (unsigned char) 2264 (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2265 | ((uint8_t) ((unsigned int) l))); 2266 str[w++] = (char) out; 2267 } 2268 } 2269 } 2270 else 2271 str[w++] = chr; 2272 } 2273 str[w] = 0; 2274 return w; 2275 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2276 } 2277 2278 2279 MHD_INTERNAL 2280 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (1) size_t 2281 mhd_str_pct_decode_in_place_lenient (char *restrict str, 2282 bool *restrict broken_encoding) 2283 { 2284 #ifdef MHD_FAVOR_SMALL_CODE 2285 size_t len; 2286 size_t res; 2287 2288 len = strlen (str); 2289 res = mhd_str_pct_decode_lenient_n (str, len, str, len, broken_encoding); 2290 str[res] = 0; 2291 2292 return res; 2293 #else /* ! MHD_FAVOR_SMALL_CODE */ 2294 size_t r; 2295 size_t w; 2296 if (NULL != broken_encoding) 2297 *broken_encoding = false; 2298 r = 0; 2299 w = 0; 2300 while (0 != str[r]) 2301 { 2302 const char chr = str[r++]; 2303 if ('%' == chr) 2304 { 2305 const char d1 = str[r++]; 2306 if (0 == d1) 2307 { 2308 if (NULL != broken_encoding) 2309 *broken_encoding = true; 2310 str[w++] = chr; /* Copy "as is" */ 2311 str[w] = 0; 2312 return w; 2313 } 2314 else 2315 { 2316 const char d2 = str[r++]; 2317 if (0 == d2) 2318 { 2319 if (NULL != broken_encoding) 2320 *broken_encoding = true; 2321 str[w++] = chr; /* Copy "as is" */ 2322 str[w++] = d1; /* Copy "as is" */ 2323 str[w] = 0; 2324 return w; 2325 } 2326 else 2327 { 2328 const int h = xdigittovalue (d1); 2329 const int l = xdigittovalue (d2); 2330 unsigned char out; 2331 if ((0 > h) || (0 > l)) 2332 { 2333 if (NULL != broken_encoding) 2334 *broken_encoding = true; 2335 str[w++] = chr; /* Copy "as is" */ 2336 str[w++] = d1; 2337 str[w++] = d2; 2338 continue; 2339 } 2340 out = 2341 (unsigned char) 2342 (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2343 | ((uint8_t) ((unsigned int) l))); 2344 str[w++] = (char) out; 2345 continue; 2346 } 2347 } 2348 } 2349 str[w++] = chr; 2350 } 2351 str[w] = 0; 2352 return w; 2353 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2354 } 2355 2356 2357 mhd_static_inline MHD_FN_PAR_NONNULL_ALL_ 2358 MHD_FN_PAR_IN_SIZE_ (2, 1) bool 2359 pct_decode_no_slash (const size_t str_len, 2360 const char *restrict str, 2361 const size_t chr_pos, 2362 char *restrict chr) 2363 { 2364 mhd_assert ('%' == *chr); 2365 mhd_assert (*chr == str[chr_pos]); 2366 mhd_ASSUME (str_len > chr_pos); 2367 2368 if ((str_len - chr_pos) <= 2u) /* Overflow-safe check */ 2369 return false; /* The string tail has less than two chars */ 2370 else 2371 { 2372 const char d1 = str[chr_pos + 1u]; 2373 const char d2 = str[chr_pos + 2u]; 2374 const int h = xdigittovalue (d1); 2375 const int l = xdigittovalue (d2); 2376 2377 if ((0 <= h) && (0 <= l)) 2378 { 2379 char dec; 2380 mhd_ASSUME (15 >= h); 2381 mhd_ASSUME (15 >= l); 2382 dec = (char) ((((unsigned char) h) << 4u) | ((unsigned char) l)); 2383 if ('/' != dec) 2384 { 2385 *chr = dec; 2386 return true; 2387 } 2388 } 2389 } 2390 /* No valid hex-number or a slash character (must not be encoded!) */ 2391 return false; 2392 } 2393 2394 2395 MHD_INTERNAL 2396 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_INOUT_SIZE_ (2,1) size_t 2397 mhd_str_dec_norm_uri_path (size_t str_len, 2398 char *restrict str) 2399 { 2400 size_t r; /**< "read" position */ 2401 size_t w; /**< "write" position */ 2402 2403 w = 0u; 2404 r = 0u; 2405 while (str_len > r) 2406 { 2407 /* Process all segments not started with "/" (if any) */ 2408 char c; 2409 mhd_ASSUME (w <= r); 2410 c = str[r]; 2411 if ('/' == c) 2412 break; /* Processed after this loop */ 2413 if (('%' == c) && 2414 pct_decode_no_slash (str_len, 2415 str, 2416 r, 2417 &c)) 2418 r += 2u; 2419 if ('.' == c) 2420 { 2421 char c2; 2422 if (str_len == r + 1u) /* overflow-safe as 'str_len > r' */ 2423 { 2424 /* The complete string is "." */ 2425 ++r; /* Skip "." */ 2426 break; /* At the edge, stop */ 2427 } 2428 mhd_ASSUME (w <= r); 2429 c2 = str[r + 1u]; 2430 if ('/' == c2) 2431 { 2432 /* Found "./" at the start of the string */ 2433 r += 2u; /* Skip "./" */ 2434 continue; 2435 } 2436 if (('%' == c2) && 2437 pct_decode_no_slash (str_len, 2438 str, 2439 r + 1u, 2440 &c2)) 2441 r += 2u; 2442 if ('.' == c2) 2443 { 2444 char c3; 2445 if (str_len == r + 2u) /* overflow-safe as 'str_len > r + 1 ' */ 2446 { 2447 /* The complete string is ".." */ 2448 r += 2u; /* Skip ".." */ 2449 break; /* At the edge, stop */ 2450 } 2451 mhd_ASSUME (w <= r); 2452 c3 = str[r + 2u]; 2453 if ('/' == c3) 2454 { 2455 /* Found "../" at the start of the string */ 2456 r += 3u; /* Skip "../" */ 2457 continue; 2458 } 2459 /* Do not write 'c3' as it has not been percent-decoded */ 2460 } 2461 str[w++] = c; 2462 str[w++] = c2; 2463 r += 2u; 2464 } 2465 else 2466 { 2467 str[w++] = c; 2468 r += 1u; 2469 } 2470 break; 2471 } 2472 2473 mhd_ASSUME (w <= r); 2474 /* Found first segment which is not "../" and is not "./" OR the end of the string */ 2475 for ((void) r; str_len > r && '/' != str[r]; ++r) 2476 { 2477 char c; 2478 mhd_ASSUME (w <= r); 2479 c = str[r]; 2480 if (('%' == c) && 2481 pct_decode_no_slash (str_len, 2482 str, 2483 r, 2484 &c)) 2485 r += 2u; 2486 mhd_ASSUME (w <= r); 2487 str[w++] = c; 2488 } 2489 2490 /* Found first '/' which is not skipped OR the end of the string */ 2491 while (str_len > r) 2492 { 2493 /* Start of a "/segment" */ 2494 char slash_chr = str[r]; 2495 const size_t seg_start = w; 2496 mhd_ASSUME ('/' == slash_chr); 2497 str[w++] = slash_chr; 2498 ++r; 2499 if (str_len > r) 2500 { 2501 char c; 2502 mhd_ASSUME (w <= r); 2503 c = str[r]; 2504 if ('/' == c) 2505 continue; 2506 if (('%' == c) && 2507 pct_decode_no_slash (str_len, 2508 str, 2509 r, 2510 &c)) 2511 r += 2u; 2512 if ('.' == c) 2513 { 2514 char c2; 2515 if (str_len == r + 1u) /* overflow-safe as 'str_len > r' */ 2516 { 2517 /* Found "/." at the end of the string */ 2518 ++r; /* Skip ".", leave bare '/' */ 2519 break; /* At the edge, stop */ 2520 } 2521 mhd_ASSUME (w <= r); 2522 c2 = str[r + 1u]; 2523 if ('/' == c2) 2524 { 2525 /* Found "/./" */ 2526 w = seg_start; /* Rewind output to the '/' at the start of the segment */ 2527 ++r; /* Skip "." */ 2528 continue; /* Go to the next "/", which will be written again */ 2529 } 2530 if (('%' == c2) && 2531 pct_decode_no_slash (str_len, 2532 str, 2533 r + 1u, 2534 &c2)) 2535 r += 2u; 2536 if ('.' == c2) 2537 { 2538 char c3; 2539 if (str_len == r + 2u) /* overflow-safe as 'str_len > r + 1 ' */ 2540 { 2541 /* Found "/.." at the end of the string */ 2542 w = seg_start; 2543 if (0 < w) 2544 do 2545 { /* Rewind output to the start of prev segment */ 2546 --w; 2547 } while (0 < w && '/' != str[w]); 2548 mhd_ASSUME (w < r); 2549 str[w++] = '/'; /* Replace prev segment with '/' */ 2550 r += 2u; /* Skip ".." */ 2551 break; /* At the edge, stop */ 2552 } 2553 mhd_ASSUME (w <= r); 2554 c3 = str[r + 2u]; 2555 if ('/' == c3) 2556 { 2557 /* Found "/../" */ 2558 w = seg_start; 2559 if (0 < w) 2560 do 2561 { /* Rewind output to the start of prev segment */ 2562 --w; 2563 } while (0 < w && '/' != str[w]); 2564 r += 2u; /* Skip ".."; put next '/' to the start of prev segment */ 2565 continue; 2566 } 2567 /* Do not write 'c3' as it has not been percent-decoded */ 2568 } 2569 str[w++] = c; 2570 str[w++] = c2; 2571 r += 2u; 2572 } 2573 else 2574 { 2575 str[w++] = c; 2576 r += 1u; 2577 } 2578 mhd_assert (seg_start < w); 2579 } 2580 for ((void) r; str_len > r && '/' != str[r]; ++r) 2581 { 2582 /* Process the end of the segment */ 2583 char c; 2584 mhd_ASSUME (w <= r); 2585 c = str[r]; 2586 if (('%' == c) && 2587 pct_decode_no_slash (str_len, 2588 str, 2589 r, 2590 &c)) 2591 r += 2u; 2592 mhd_ASSUME (w <= r); 2593 str[w++] = c; 2594 } 2595 mhd_assert (0u != w); 2596 } 2597 mhd_assert (r == str_len); 2598 2599 if (str_len > w) 2600 str[w] = '\0'; 2601 2602 return w; 2603 } 2604 2605 2606 #ifdef MHD_SUPPORT_AUTH_DIGEST 2607 2608 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ 2609 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_IN_SIZE_ (3,4) bool 2610 mhd_str_equal_quoted_bin_n (const char *quoted, 2611 size_t quoted_len, 2612 const char *unquoted, 2613 size_t unquoted_len) 2614 { 2615 size_t i; 2616 size_t j; 2617 if (unquoted_len < quoted_len / 2) 2618 return false; 2619 2620 j = 0; 2621 for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j) 2622 { 2623 if ('\\' == quoted[i]) 2624 { 2625 i++; /* Advance to the next character */ 2626 if (quoted_len == i) 2627 return false; /* No character after escaping backslash */ 2628 } 2629 if (quoted[i] != unquoted[j]) 2630 return false; /* Different characters */ 2631 } 2632 if ((quoted_len != i) || (unquoted_len != j)) 2633 return false; /* The strings have different length */ 2634 2635 return true; 2636 } 2637 2638 2639 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ 2640 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_IN_SIZE_ (3,4) bool 2641 mhd_str_equal_caseless_quoted_bin_n (const char *quoted, 2642 size_t quoted_len, 2643 const char *unquoted, 2644 size_t unquoted_len) 2645 { 2646 size_t i; 2647 size_t j; 2648 if (unquoted_len < quoted_len / 2) 2649 return false; 2650 2651 j = 0; 2652 for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j) 2653 { 2654 if ('\\' == quoted[i]) 2655 { 2656 i++; /* Advance to the next character */ 2657 if (quoted_len == i) 2658 return false; /* No character after escaping backslash */ 2659 } 2660 if (! charsequalcaseless (quoted[i], unquoted[j])) 2661 return false; /* Different characters */ 2662 } 2663 if ((quoted_len != i) || (unquoted_len != j)) 2664 return false; /* The strings have different length */ 2665 2666 return true; 2667 } 2668 2669 2670 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 2671 2672 #if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(MHD_SUPPORT_POST_PARSER) 2673 2674 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 2675 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_SIZE_ (3,2) size_t 2676 mhd_str_unquote (const char *quoted, 2677 size_t quoted_len, 2678 char *result) 2679 { 2680 size_t r; 2681 size_t w; 2682 2683 r = 0; 2684 w = 0; 2685 2686 while (quoted_len > r) 2687 { 2688 if ('\\' == quoted[r]) 2689 { 2690 ++r; 2691 if (quoted_len == r) 2692 return 0; /* Last backslash is not followed by char to unescape */ 2693 } 2694 result[w++] = quoted[r++]; 2695 } 2696 return w; 2697 } 2698 2699 2700 #endif /* MHD_SUPPORT_AUTH_DIGEST || MHD_SUPPORT_POST_PARSER */ 2701 2702 #if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(MHD_SUPPORT_AUTH_BASIC) 2703 2704 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 2705 MHD_FN_PAR_IN_SIZE_ (1,2) 2706 MHD_FN_PAR_OUT_SIZE_ (3,4) size_t 2707 mhd_str_quote (const char *unquoted, 2708 size_t unquoted_len, 2709 char *result, 2710 size_t buf_size) 2711 { 2712 size_t r; 2713 size_t w; 2714 2715 r = 0; 2716 w = 0; 2717 2718 #ifndef MHD_FAVOR_SMALL_CODE 2719 if (unquoted_len * 2 <= buf_size) 2720 { 2721 /* Fast loop: the output will fit the buffer with any input string content */ 2722 while (unquoted_len > r) 2723 { 2724 const char chr = unquoted[r++]; 2725 if (('\\' == chr) || ('\"' == chr)) 2726 result[w++] = '\\'; /* Escape current char */ 2727 result[w++] = chr; 2728 } 2729 } 2730 else 2731 { 2732 if (unquoted_len > buf_size) 2733 return 0; /* Quick fail: the output buffer is too small */ 2734 #else /* MHD_FAVOR_SMALL_CODE */ 2735 if (1) 2736 { 2737 #endif /* MHD_FAVOR_SMALL_CODE */ 2738 2739 while (unquoted_len > r) 2740 { 2741 if (buf_size <= w) 2742 return 0; /* The output buffer is too small */ 2743 else 2744 { 2745 const char chr = unquoted[r++]; 2746 if (('\\' == chr) || ('\"' == chr)) 2747 { 2748 result[w++] = '\\'; /* Escape current char */ 2749 if (buf_size <= w) 2750 return 0; /* The output buffer is too small */ 2751 } 2752 result[w++] = chr; 2753 } 2754 } 2755 } 2756 2757 mhd_assert (w >= r); 2758 mhd_assert (w <= r * 2); 2759 return w; 2760 } 2761 2762 2763 #endif /* MHD_SUPPORT_AUTH_DIGEST || MHD_SUPPORT_AUTH_BASIC */ 2764 2765 #ifdef MHD_SUPPORT_AUTH_BASIC 2766 2767 /* 2768 * MHD_BASE64_FUNC_VERSION 2769 * 1 = smallest, 2770 * 2 = medium, 2771 * 3 = fastest 2772 */ 2773 #ifndef MHD_BASE64_FUNC_VERSION 2774 #ifdef MHD_FAVOR_SMALL_CODE 2775 #define MHD_BASE64_FUNC_VERSION 1 2776 #else /* ! MHD_FAVOR_SMALL_CODE */ 2777 #define MHD_BASE64_FUNC_VERSION 3 2778 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2779 #endif /* ! MHD_BASE64_FUNC_VERSION */ 2780 2781 #if MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 2782 #error Wrong MHD_BASE64_FUNC_VERSION value 2783 #endif /* MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 */ 2784 2785 #if MHD_BASE64_FUNC_VERSION == 3 2786 #define mhd_base64_map_type int 2787 #else /* MHD_BASE64_FUNC_VERSION < 3 */ 2788 #define mhd_base64_map_type int8_t 2789 #endif /* MHD_BASE64_FUNC_VERSION < 3 */ 2790 2791 #if MHD_BASE64_FUNC_VERSION == 1 2792 static mhd_base64_map_type 2793 base64_char_to_value_ (uint8_t c) 2794 { 2795 if ('Z' >= c) 2796 { 2797 if ('A' <= c) 2798 return (mhd_base64_map_type) ((c - 'A') + 0); 2799 else if ('0' <= c) 2800 { 2801 if ('9' >= c) 2802 return (mhd_base64_map_type) ((c - '0') + 52); 2803 else if ('=' == c) 2804 return -2; 2805 else 2806 return -1; 2807 } 2808 else if ('+' == c) 2809 return 62; 2810 else if ('/' == c) 2811 return 63; 2812 else 2813 return -1; 2814 } 2815 else if (('z' >= c) && ('a' <= c)) 2816 return (mhd_base64_map_type) ((c - 'a') + 26); 2817 return -1; 2818 } 2819 2820 2821 #endif /* MHD_BASE64_FUNC_VERSION == 1 */ 2822 2823 2824 mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE 2825 2826 2827 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 2828 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_SIZE_ (3,4) size_t 2829 mhd_base64_to_bin_n (const char *base64, 2830 size_t base64_len, 2831 void *bin, 2832 size_t bin_size) 2833 { 2834 #if MHD_BASE64_FUNC_VERSION >= 2 2835 static const mhd_base64_map_type map[] = { 2836 /* -1 = invalid char, -2 = padding 2837 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 2838 NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, */ 2839 -1, -1, -1, -1, -1, -1, -1, -1, 2840 /* 2841 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 2842 BS, HT, LF, VT, FF, CR, SO, SI, */ 2843 -1, -1, -1, -1, -1, -1, -1, -1, 2844 /* 2845 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 2846 DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, */ 2847 -1, -1, -1, -1, -1, -1, -1, -1, 2848 /* 2849 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 2850 CAN, EM, SUB, ESC, FS, GS, RS, US, */ 2851 -1, -1, -1, -1, -1, -1, -1, -1, 2852 /* 2853 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 2854 ' ', '!', '"', '#', '$', '%', '&', '\'', */ 2855 -1, -1, -1, -1, -1, -1, -1, -1, 2856 /* 2857 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 2858 '(', ')', '*', '+', ',', '-', '.', '/', */ 2859 -1, -1, -1, 62, -1, -1, -1, 63, 2860 /* 2861 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 2862 '0', '1', '2', '3', '4', '5', '6', '7', */ 2863 52, 53, 54, 55, 56, 57, 58, 59, 2864 /* 2865 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 2866 '8', '9', ':', ';', '<', '=', '>', '?', */ 2867 60, 61, -1, -1, -1, -2, -1, -1, 2868 /* 2869 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 2870 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */ 2871 -1, 0, 1, 2, 3, 4, 5, 6, 2872 /* 2873 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 2874 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */ 2875 7, 8, 9, 10, 11, 12, 13, 14, 2876 /* 2877 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 2878 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */ 2879 15, 16, 17, 18, 19, 20, 21, 22, 2880 /* 2881 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 2882 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */ 2883 23, 24, 25, -1, -1, -1, -1, -1, 2884 /* 2885 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 2886 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */ 2887 -1, 26, 27, 28, 29, 30, 31, 32, 2888 /* 2889 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 2890 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */ 2891 33, 34, 35, 36, 37, 38, 39, 40, 2892 /* 2893 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 2894 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */ 2895 41, 42, 43, 44, 45, 46, 47, 48, 2896 /* 2897 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 2898 'x', 'y', 'z', '{', '|', '}', '~', DEL, */ 2899 49, 50, 51, -1, -1, -1, -1, -1 2900 2901 #if MHD_BASE64_FUNC_VERSION == 3 2902 , 2903 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80..8F */ 2904 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90..9F */ 2905 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0..AF */ 2906 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0..BF */ 2907 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0..CF */ 2908 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0..DF */ 2909 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0..EF */ 2910 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* F0..FF */ 2911 #endif /* ! MHD_BASE64_FUNC_VERSION == 3 */ 2912 }; 2913 #define base64_char_to_value_(c) map[(c)] 2914 #endif /* MHD_BASE64_FUNC_VERSION >= 2 */ 2915 const uint8_t *const in = (const uint8_t *) base64; 2916 uint8_t *const out = (uint8_t *) bin; 2917 size_t i; 2918 size_t j; 2919 if (0 == base64_len) 2920 return 0; /* Nothing to decode */ 2921 if (0 != base64_len % 4) 2922 return 0; /* Wrong input length */ 2923 if (base64_len / 4 * 3 - 2 > bin_size) 2924 return 0; 2925 2926 j = 0; 2927 for (i = 0; i < (base64_len - 4); i += 4) 2928 { 2929 #if MHD_BASE64_FUNC_VERSION == 2 2930 if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3]))) 2931 return 0; 2932 #endif /* MHD_BASE64_FUNC_VERSION == 2 */ 2933 if (1) 2934 { 2935 const mhd_base64_map_type v1 = base64_char_to_value_ (in[i + 0]); 2936 const mhd_base64_map_type v2 = base64_char_to_value_ (in[i + 1]); 2937 const mhd_base64_map_type v3 = base64_char_to_value_ (in[i + 2]); 2938 const mhd_base64_map_type v4 = base64_char_to_value_ (in[i + 3]); 2939 if ((0 > v1) || (0 > v2) || (0 > v3) || (0 > v4)) 2940 return 0; 2941 out[j + 0] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2)) 2942 | ((uint8_t) (((uint8_t) v2) >> 4))); 2943 out[j + 1] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4)) 2944 | ((uint8_t) (((uint8_t) v3) >> 2))); 2945 out[j + 2] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6)) 2946 | ((uint8_t) v4)); 2947 } 2948 j += 3; 2949 } 2950 #if MHD_BASE64_FUNC_VERSION == 2 2951 if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3]))) 2952 return 0; 2953 #endif /* MHD_BASE64_FUNC_VERSION == 2 */ 2954 if (1) 2955 { /* The last four chars block */ 2956 const mhd_base64_map_type v1 = base64_char_to_value_ (in[i + 0]); 2957 const mhd_base64_map_type v2 = base64_char_to_value_ (in[i + 1]); 2958 const mhd_base64_map_type v3 = base64_char_to_value_ (in[i + 2]); 2959 const mhd_base64_map_type v4 = base64_char_to_value_ (in[i + 3]); 2960 if ((0 > v1) || (0 > v2)) 2961 return 0; /* Invalid char or padding at first two positions */ 2962 mhd_assert (j < bin_size); 2963 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2)) 2964 | ((uint8_t) (((uint8_t) v2) >> 4))); 2965 if (0 > v3) 2966 { /* Third char is either padding or invalid */ 2967 if ((-2 != v3) || (-2 != v4)) 2968 return 0; /* Both two last chars must be padding */ 2969 if (0 != (uint8_t) (((uint8_t) v2) << 4)) 2970 return 0; /* Wrong last char */ 2971 return j; 2972 } 2973 if (j >= bin_size) 2974 return 0; /* Not enough space */ 2975 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4)) 2976 | ((uint8_t) (((uint8_t) v3) >> 2))); 2977 if (0 > v4) 2978 { /* Fourth char is either padding or invalid */ 2979 if (-2 != v4) 2980 return 0; /* The char must be padding */ 2981 if (0 != (uint8_t) (((uint8_t) v3) << 6)) 2982 return 0; /* Wrong last char */ 2983 return j; 2984 } 2985 if (j >= bin_size) 2986 return 0; /* Not enough space */ 2987 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6)) 2988 | ((uint8_t) v4)); 2989 } 2990 return j; 2991 #if MHD_BASE64_FUNC_VERSION >= 2 2992 #undef base64_char_to_value_ 2993 #endif /* MHD_BASE64_FUNC_VERSION >= 2 */ 2994 } 2995 2996 2997 mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE 2998 2999 3000 #undef mhd_base64_map_type 3001 3002 #endif /* MHD_SUPPORT_AUTH_BASIC */ 3003 3004 3005 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ bool 3006 mhd_str_starts_with_token_opt_param (const struct MHD_String *restrict str, 3007 const struct MHD_String *restrict token) 3008 { 3009 size_t i; 3010 3011 mhd_assert (0 != token->len); 3012 mhd_assert (NULL == memchr (token->cstr, '=', token->len)); 3013 mhd_assert (NULL == memchr (token->cstr, ' ', token->len)); 3014 mhd_assert (NULL == memchr (token->cstr, '\t', token->len)); 3015 3016 if (str->len < token->len) 3017 return false; /* The string is too short to match */ 3018 3019 if (! mhd_str_equal_caseless_bin_n (str->cstr, 3020 token->cstr, 3021 token->len)) 3022 return false; /* The string does not start with the token */ 3023 3024 for (i = token->len; i < str->len; ++i) 3025 { 3026 const char c = str->cstr[i]; 3027 if ((' ' == c) || ('\t' == c)) 3028 continue; 3029 if (';' == c) 3030 return true; /* Found the start of the token parameters */ 3031 return false; /* The initial part of the string does not fully match the token */ 3032 } 3033 mhd_assert (0 && "The string should not have whitespace at the end"); 3034 return true; 3035 } 3036 3037 3038 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 3039 MHD_FN_PAR_IN_ (1) MHD_FN_PAR_IN_ (2) MHD_FN_PAR_IN_ (3) 3040 MHD_FN_PAR_OUT_ (4) MHD_FN_PAR_OUT_ (5) enum mhd_StingStartsWithTokenResult 3041 mhd_str_starts_with_token_req_param ( 3042 const struct MHD_String *restrict str, 3043 const struct MHD_String *restrict token, 3044 const struct MHD_String *restrict par, 3045 struct mhd_BufferConst *restrict par_value, 3046 bool *restrict par_value_needs_unquote) 3047 { 3048 size_t i; 3049 const char *const restrict cstr = str->cstr; 3050 bool token_found; 3051 bool param_found; 3052 3053 mhd_assert (0 != token->len); 3054 mhd_assert (NULL == memchr (token->cstr, '=', token->len)); 3055 mhd_assert (NULL == memchr (token->cstr, ' ', token->len)); 3056 mhd_assert (NULL == memchr (token->cstr, '\t', token->len)); 3057 mhd_assert (NULL == memchr (par->cstr, '=', par->len)); 3058 mhd_assert (NULL == memchr (par->cstr, ' ', par->len)); 3059 mhd_assert (NULL == memchr (par->cstr, '\t', par->len)); 3060 3061 par_value->data = NULL; 3062 par_value->size = 0; 3063 3064 if (str->len < token->len) 3065 return mhd_STR_STARTS_W_TOKEN_NO_TOKEN; /* The string is too short to match */ 3066 3067 if (! mhd_str_equal_caseless_bin_n (cstr, 3068 token->cstr, 3069 token->len)) 3070 return mhd_STR_STARTS_W_TOKEN_NO_TOKEN; /* The string does not start with the token */ 3071 token_found = false; 3072 param_found = false; 3073 3074 i = token->len; 3075 do 3076 { 3077 /* Find start of the next parameter */ 3078 for ((void) 0; i < str->len; ++i) 3079 { 3080 const char c = cstr[i]; 3081 if ((' ' == c) || ('\t' == c)) 3082 continue; 3083 if (';' == c) 3084 { 3085 /* Found the start of the next token parameter */ 3086 if (param_found) 3087 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; 3088 ++i; /* Move to the next char */ 3089 break; 3090 } 3091 if (',' == c) 3092 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; /* Found the start of the next token */ 3093 3094 if (! token_found) 3095 { 3096 if (i == token->len) 3097 { 3098 /* The initial part of the string does not fully match the token or 3099 formatting is not correct */ 3100 return mhd_STR_STARTS_W_TOKEN_NO_TOKEN; 3101 } 3102 /* The string has garbage after the token and whitespace */ 3103 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN_BAD_FORMAT; 3104 } 3105 /* The garbage after the parameter */ 3106 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN_BAD_FORMAT; 3107 } 3108 token_found = true; 3109 3110 if (i == str->len) 3111 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; 3112 3113 /* 'i' is at the start of the parameter */ 3114 3115 while ((' ' == cstr[i]) || ('\t' == cstr[i])) 3116 { 3117 if (++i == str->len) 3118 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; 3119 } 3120 3121 /* 'i' is at the start of the parameter name */ 3122 3123 if (par->len > str->len - i - 1) 3124 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; /* the token is found, but the parameter is not */ 3125 else 3126 { /* Check the parameter */ 3127 bool val_needs_unquote; 3128 size_t j; 3129 const char *const prm_str = cstr + i; 3130 3131 for (j = 0; j < par->len; ++j) 3132 if (! charsequalcaseless (prm_str[j], 3133 par->cstr[j])) 3134 break; 3135 i += j; 3136 mhd_assert (str->len > i); 3137 if ((j == par->len) && 3138 ('=' == cstr[i])) 3139 { 3140 /* The parameter name matches required parameter */ 3141 param_found = true; 3142 par_value->data = cstr + i + 1; 3143 } 3144 else 3145 { 3146 /* i points to the char in the parameter name */ 3147 while ('=' != cstr[i]) 3148 { 3149 if ((';' == cstr[i]) /* end of the parameter */ 3150 || (',' == cstr[i]) /* end of the token */ 3151 || (str->len == ++i)) /* end of the field string */ 3152 { 3153 /* parameter without the value */ 3154 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN_BAD_FORMAT; 3155 } 3156 } 3157 } 3158 mhd_assert (str->len > i); 3159 mhd_assert ('=' == cstr[i]); 3160 3161 /* 'i' points to '=' between parameter name and parameter value */ 3162 3163 ++i; /* Advance to the first char in the parameter value */ 3164 if (str->len == i) 3165 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; /* Zero-length parameter value */ 3166 3167 val_needs_unquote = false; 3168 3169 /* 'i' points to the char after '=' */ 3170 3171 if ('"' == cstr[i]) 3172 { 3173 /* The value is quoted */ 3174 if (param_found) 3175 ++(par_value->data); /* Point to the first quoted char */ 3176 do 3177 { 3178 ++i; /* Advance to the next char */ 3179 if (str->len == i) 3180 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN_BAD_FORMAT; /* No closing quote */ 3181 if ('\\' == cstr[i]) 3182 { 3183 val_needs_unquote = true; 3184 ++i; /* Skip quoted char */ 3185 if (str->len == i) 3186 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN_BAD_FORMAT; /* No closing quote */ 3187 } 3188 } while ('"' != cstr[i]); 3189 if (param_found) 3190 { 3191 par_value->size = (size_t) ((cstr + i) - par_value->data); 3192 *par_value_needs_unquote = val_needs_unquote; 3193 } 3194 /* Complete value found */ 3195 /* Check for the garbage data at the end */ 3196 ++i; /* Advance to the next char */ 3197 } 3198 else 3199 { 3200 /* The value is not quoted */ 3201 while ((' ' != cstr[i]) && 3202 ('\t' != cstr[i])) 3203 { 3204 if ((';' == cstr[i]) /* end of the parameter */ 3205 || (',' == cstr[i]) /* end of the token */ 3206 || (str->len == ++i)) /* end of the field string */ 3207 break; 3208 } 3209 /* The end parameter value */ 3210 if (param_found) 3211 { 3212 par_value->size = (size_t) ((cstr + i) - par_value->data); 3213 *par_value_needs_unquote = false; 3214 } 3215 /* Check for the garbage data at the end */ 3216 } 3217 3218 /* 'i' points to the next char after end of the parameter value */ 3219 } 3220 } while (i < str->len); 3221 3222 mhd_assert (token_found); 3223 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; 3224 }