mhd_str.c (84551B)
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 if (0u == buf_size) 1915 return 0u; 1916 1917 pos = 0; 1918 digit = val / 100; 1919 if (0 == digit) 1920 { 1921 if (3 <= min_digits) 1922 buf[pos++] = '0'; 1923 } 1924 else 1925 { 1926 buf[pos++] = (char) ('0' + (char) digit); 1927 val %= 100; 1928 min_digits = 2; 1929 } 1930 1931 if (buf_size <= pos) 1932 return 0; 1933 digit = val / 10; 1934 if (0 == digit) 1935 { 1936 if (2 <= min_digits) 1937 buf[pos++] = '0'; 1938 } 1939 else 1940 { 1941 buf[pos++] = (char) ('0' + (char) digit); 1942 val %= 10; 1943 } 1944 1945 if (buf_size <= pos) 1946 return 0; 1947 buf[pos++] = (char) ('0' + (char) val); 1948 return pos; 1949 } 1950 1951 1952 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1953 MHD_FN_PAR_IN_SIZE_ (1, 2) MHD_FN_PAR_OUT_ (3) size_t 1954 mhd_bin_to_hex (const void *restrict bin, 1955 size_t size, 1956 char *restrict hex) 1957 { 1958 size_t i; 1959 1960 for (i = 0; i < size; ++i) 1961 { 1962 const uint8_t b = ((const uint8_t *) bin)[i]; 1963 #ifdef mhd_HAVE_UINT8TOTWOXDIGITS 1964 const char *two_xdigits = uint8totwoxdigits (b); 1965 hex[i * 2] = two_xdigits[0]; 1966 hex[i * 2 + 1] = two_xdigits[1]; 1967 #else /* ! mhd_HAVE_UINT8TOTWOXDIGITS */ 1968 hex[i * 2] = valuetoxdigit (b >> 4); 1969 hex[i * 2 + 1] = valuetoxdigit (b & 0x0Fu); 1970 #endif /* ! mhd_HAVE_UINT8TOTWOXDIGITS */ 1971 } 1972 return i * 2; 1973 } 1974 1975 1976 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1977 MHD_FN_PAR_IN_SIZE_ (1, 2) MHD_FN_PAR_OUT_ (3) size_t 1978 mhd_bin_to_hex_z (const void *restrict bin, 1979 size_t size, 1980 char *restrict hex) 1981 { 1982 size_t res; 1983 1984 res = mhd_bin_to_hex (bin, size, hex); 1985 hex[res] = 0; 1986 1987 return res; 1988 } 1989 1990 1991 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1992 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_ (3) size_t 1993 mhd_hex_to_bin (const char *restrict hex, 1994 size_t len, 1995 void *restrict bin) 1996 { 1997 size_t r; 1998 size_t w; 1999 2000 r = 0; 2001 w = 0; 2002 if (0 != len % 2) 2003 { 2004 /* Assume the first byte is encoded with single digit */ 2005 const char c2 = hex[r++]; 2006 const int l = xdigittovalue (c2); 2007 if (0 > l) 2008 return 0; 2009 ((uint8_t *) bin)[w++] = (uint8_t) ((unsigned int) l); 2010 } 2011 while (r < len) 2012 { 2013 const char c1 = hex[r++]; 2014 const char c2 = hex[r++]; 2015 const int h = xdigittovalue (c1); 2016 const int l = xdigittovalue (c2); 2017 if ((0 > h) || (0 > l)) 2018 return 0; 2019 ((uint8_t *) bin)[w++] = 2020 (uint8_t) ( ((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2021 | ((uint8_t) ((unsigned int) l)) ); 2022 } 2023 mhd_assert (len == r); 2024 mhd_assert ((len + 1) / 2 == w); 2025 return w; 2026 } 2027 2028 2029 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 2030 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_SIZE_ (3,4) size_t 2031 mhd_str_pct_decode_strict_n (const char *pct_encoded, 2032 size_t pct_encoded_len, 2033 char *decoded, 2034 size_t buf_size) 2035 { 2036 #ifdef MHD_FAVOR_SMALL_CODE 2037 bool broken; 2038 size_t res; 2039 2040 res = mhd_str_pct_decode_lenient_n (pct_encoded, pct_encoded_len, decoded, 2041 buf_size, &broken); 2042 if (broken) 2043 return 0; 2044 return res; 2045 #else /* ! MHD_FAVOR_SMALL_CODE */ 2046 size_t r; 2047 size_t w; 2048 r = 0; 2049 w = 0; 2050 2051 if (buf_size >= pct_encoded_len) 2052 { 2053 while (r < pct_encoded_len) 2054 { 2055 const char chr = pct_encoded[r]; 2056 if ('%' == chr) 2057 { 2058 if (2 >= pct_encoded_len - r) 2059 return 0; 2060 else 2061 { 2062 const char c1 = pct_encoded[++r]; 2063 const char c2 = pct_encoded[++r]; 2064 const int h = xdigittovalue (c1); 2065 const int l = xdigittovalue (c2); 2066 unsigned char out; 2067 if ((0 > h) || (0 > l)) 2068 return 0; 2069 out = 2070 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2071 | ((uint8_t) ((unsigned int) l))); 2072 decoded[w] = (char) out; 2073 } 2074 } 2075 else 2076 decoded[w] = chr; 2077 ++r; 2078 ++w; 2079 } 2080 return w; 2081 } 2082 2083 while (r < pct_encoded_len) 2084 { 2085 const char chr = pct_encoded[r]; 2086 if (w >= buf_size) 2087 return 0; 2088 if ('%' == chr) 2089 { 2090 if (2 >= pct_encoded_len - r) 2091 return 0; 2092 else 2093 { 2094 const char c1 = pct_encoded[++r]; 2095 const char c2 = pct_encoded[++r]; 2096 const int h = xdigittovalue (c1); 2097 const int l = xdigittovalue (c2); 2098 unsigned char out; 2099 if ((0 > h) || (0 > l)) 2100 return 0; 2101 out = 2102 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2103 | ((uint8_t) ((unsigned int) l))); 2104 decoded[w] = (char) out; 2105 } 2106 } 2107 else 2108 decoded[w] = chr; 2109 ++r; 2110 ++w; 2111 } 2112 return w; 2113 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2114 } 2115 2116 2117 MHD_INTERNAL 2118 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) 2119 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_SIZE_ (3,4) size_t 2120 mhd_str_pct_decode_lenient_n (const char *pct_encoded, 2121 size_t pct_encoded_len, 2122 char *decoded, 2123 size_t buf_size, 2124 bool *restrict broken_encoding) 2125 { 2126 size_t r; 2127 size_t w; 2128 r = 0; 2129 w = 0; 2130 if (NULL != broken_encoding) 2131 *broken_encoding = false; 2132 #ifndef MHD_FAVOR_SMALL_CODE 2133 if (buf_size >= pct_encoded_len) 2134 { 2135 while (r < pct_encoded_len) 2136 { 2137 const char chr = pct_encoded[r]; 2138 if ('%' == chr) 2139 { 2140 if (2 >= pct_encoded_len - r) 2141 { 2142 if (NULL != broken_encoding) 2143 *broken_encoding = true; 2144 decoded[w] = chr; /* Copy "as is" */ 2145 } 2146 else 2147 { 2148 const char c1 = pct_encoded[++r]; 2149 const char c2 = pct_encoded[++r]; 2150 const int h = xdigittovalue (c1); 2151 const int l = xdigittovalue (c2); 2152 unsigned char out; 2153 if ((0 > h) || (0 > l)) 2154 { 2155 r -= 2; 2156 if (NULL != broken_encoding) 2157 *broken_encoding = true; 2158 decoded[w] = chr; /* Copy "as is" */ 2159 } 2160 else 2161 { 2162 out = 2163 (unsigned char) 2164 (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2165 | ((uint8_t) ((unsigned int) l))); 2166 decoded[w] = (char) out; 2167 } 2168 } 2169 } 2170 else 2171 decoded[w] = chr; 2172 ++r; 2173 ++w; 2174 } 2175 return w; 2176 } 2177 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2178 while (r < pct_encoded_len) 2179 { 2180 const char chr = pct_encoded[r]; 2181 if (w >= buf_size) 2182 return 0; 2183 if ('%' == chr) 2184 { 2185 if (2 >= pct_encoded_len - r) 2186 { 2187 if (NULL != broken_encoding) 2188 *broken_encoding = true; 2189 decoded[w] = chr; /* Copy "as is" */ 2190 } 2191 else 2192 { 2193 const char c1 = pct_encoded[++r]; 2194 const char c2 = pct_encoded[++r]; 2195 const int h = xdigittovalue (c1); 2196 const int l = xdigittovalue (c2); 2197 if ((0 > h) || (0 > l)) 2198 { 2199 r -= 2; 2200 if (NULL != broken_encoding) 2201 *broken_encoding = true; 2202 decoded[w] = chr; /* Copy "as is" */ 2203 } 2204 else 2205 { 2206 unsigned char out; 2207 out = 2208 (unsigned char) 2209 (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2210 | ((uint8_t) ((unsigned int) l))); 2211 decoded[w] = (char) out; 2212 } 2213 } 2214 } 2215 else 2216 decoded[w] = chr; 2217 ++r; 2218 ++w; 2219 } 2220 return w; 2221 } 2222 2223 2224 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 2225 MHD_FN_PAR_CSTR_ (1) size_t 2226 mhd_str_pct_decode_in_place_strict (char *str) 2227 { 2228 #ifdef MHD_FAVOR_SMALL_CODE 2229 size_t res; 2230 bool broken; 2231 2232 res = mhd_str_pct_decode_in_place_lenient (str, &broken); 2233 if (broken) 2234 { 2235 res = 0; 2236 str[0] = 0; 2237 } 2238 return res; 2239 #else /* ! MHD_FAVOR_SMALL_CODE */ 2240 size_t r; 2241 size_t w; 2242 r = 0; 2243 w = 0; 2244 2245 while (0 != str[r]) 2246 { 2247 const char chr = str[r++]; 2248 if ('%' == chr) 2249 { 2250 const char d1 = str[r++]; 2251 if (0 == d1) 2252 return 0; 2253 else 2254 { 2255 const char d2 = str[r++]; 2256 if (0 == d2) 2257 return 0; 2258 else 2259 { 2260 const int h = xdigittovalue (d1); 2261 const int l = xdigittovalue (d2); 2262 unsigned char out; 2263 if ((0 > h) || (0 > l)) 2264 return 0; 2265 out = 2266 (unsigned char) 2267 (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2268 | ((uint8_t) ((unsigned int) l))); 2269 str[w++] = (char) out; 2270 } 2271 } 2272 } 2273 else 2274 str[w++] = chr; 2275 } 2276 str[w] = 0; 2277 return w; 2278 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2279 } 2280 2281 2282 MHD_INTERNAL 2283 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (1) size_t 2284 mhd_str_pct_decode_in_place_lenient (char *restrict str, 2285 bool *restrict broken_encoding) 2286 { 2287 #ifdef MHD_FAVOR_SMALL_CODE 2288 size_t len; 2289 size_t res; 2290 2291 len = strlen (str); 2292 res = mhd_str_pct_decode_lenient_n (str, len, str, len, broken_encoding); 2293 str[res] = 0; 2294 2295 return res; 2296 #else /* ! MHD_FAVOR_SMALL_CODE */ 2297 size_t r; 2298 size_t w; 2299 if (NULL != broken_encoding) 2300 *broken_encoding = false; 2301 r = 0; 2302 w = 0; 2303 while (0 != str[r]) 2304 { 2305 const char chr = str[r++]; 2306 if ('%' == chr) 2307 { 2308 const char d1 = str[r++]; 2309 if (0 == d1) 2310 { 2311 if (NULL != broken_encoding) 2312 *broken_encoding = true; 2313 str[w++] = chr; /* Copy "as is" */ 2314 str[w] = 0; 2315 return w; 2316 } 2317 else 2318 { 2319 const char d2 = str[r++]; 2320 if (0 == d2) 2321 { 2322 if (NULL != broken_encoding) 2323 *broken_encoding = true; 2324 str[w++] = chr; /* Copy "as is" */ 2325 str[w++] = d1; /* Copy "as is" */ 2326 str[w] = 0; 2327 return w; 2328 } 2329 else 2330 { 2331 const int h = xdigittovalue (d1); 2332 const int l = xdigittovalue (d2); 2333 unsigned char out; 2334 if ((0 > h) || (0 > l)) 2335 { 2336 if (NULL != broken_encoding) 2337 *broken_encoding = true; 2338 str[w++] = chr; /* Copy "as is" */ 2339 str[w++] = d1; 2340 str[w++] = d2; 2341 continue; 2342 } 2343 out = 2344 (unsigned char) 2345 (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2346 | ((uint8_t) ((unsigned int) l))); 2347 str[w++] = (char) out; 2348 continue; 2349 } 2350 } 2351 } 2352 str[w++] = chr; 2353 } 2354 str[w] = 0; 2355 return w; 2356 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2357 } 2358 2359 2360 mhd_static_inline MHD_FN_PAR_NONNULL_ALL_ 2361 MHD_FN_PAR_IN_SIZE_ (2, 1) bool 2362 pct_decode_no_slash (const size_t str_len, 2363 const char *restrict str, 2364 const size_t chr_pos, 2365 char *restrict chr) 2366 { 2367 mhd_assert ('%' == *chr); 2368 mhd_assert (*chr == str[chr_pos]); 2369 mhd_ASSUME (str_len > chr_pos); 2370 2371 if ((str_len - chr_pos) <= 2u) /* Overflow-safe check */ 2372 return false; /* The string tail has less than two chars */ 2373 else 2374 { 2375 const char d1 = str[chr_pos + 1u]; 2376 const char d2 = str[chr_pos + 2u]; 2377 const int h = xdigittovalue (d1); 2378 const int l = xdigittovalue (d2); 2379 2380 if ((0 <= h) && (0 <= l)) 2381 { 2382 char dec; 2383 mhd_ASSUME (15 >= h); 2384 mhd_ASSUME (15 >= l); 2385 dec = (char) ((((unsigned char) h) << 4u) | ((unsigned char) l)); 2386 if ('/' != dec) 2387 { 2388 *chr = dec; 2389 return true; 2390 } 2391 } 2392 } 2393 /* No valid hex-number or a slash character (must not be encoded!) */ 2394 return false; 2395 } 2396 2397 2398 MHD_INTERNAL 2399 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_INOUT_SIZE_ (2,1) size_t 2400 mhd_str_dec_norm_uri_path (size_t str_len, 2401 char *restrict str) 2402 { 2403 size_t r; /**< "read" position */ 2404 size_t w; /**< "write" position */ 2405 2406 w = 0u; 2407 r = 0u; 2408 while (str_len > r) 2409 { 2410 /* Process all segments not started with "/" (if any) */ 2411 char c; 2412 mhd_ASSUME (w <= r); 2413 c = str[r]; 2414 if ('/' == c) 2415 break; /* Processed after this loop */ 2416 if (('%' == c) && 2417 pct_decode_no_slash (str_len, 2418 str, 2419 r, 2420 &c)) 2421 r += 2u; 2422 if ('.' == c) 2423 { 2424 char c2; 2425 if (str_len == r + 1u) /* overflow-safe as 'str_len > r' */ 2426 { 2427 /* The complete string is "." */ 2428 ++r; /* Skip "." */ 2429 break; /* At the edge, stop */ 2430 } 2431 mhd_ASSUME (w <= r); 2432 c2 = str[r + 1u]; 2433 if ('/' == c2) 2434 { 2435 /* Found "./" at the start of the string */ 2436 r += 2u; /* Skip "./" */ 2437 continue; 2438 } 2439 if (('%' == c2) && 2440 pct_decode_no_slash (str_len, 2441 str, 2442 r + 1u, 2443 &c2)) 2444 r += 2u; 2445 if ('.' == c2) 2446 { 2447 char c3; 2448 if (str_len == r + 2u) /* overflow-safe as 'str_len > r + 1 ' */ 2449 { 2450 /* The complete string is ".." */ 2451 r += 2u; /* Skip ".." */ 2452 break; /* At the edge, stop */ 2453 } 2454 mhd_ASSUME (w <= r); 2455 c3 = str[r + 2u]; 2456 if ('/' == c3) 2457 { 2458 /* Found "../" at the start of the string */ 2459 r += 3u; /* Skip "../" */ 2460 continue; 2461 } 2462 /* Do not write 'c3' as it has not been percent-decoded */ 2463 } 2464 str[w++] = c; 2465 str[w++] = c2; 2466 r += 2u; 2467 } 2468 else 2469 { 2470 str[w++] = c; 2471 r += 1u; 2472 } 2473 break; 2474 } 2475 2476 mhd_ASSUME (w <= r); 2477 /* Found first segment which is not "../" and is not "./" OR the end of the string */ 2478 for ((void) r; str_len > r && '/' != str[r]; ++r) 2479 { 2480 char c; 2481 mhd_ASSUME (w <= r); 2482 c = str[r]; 2483 if (('%' == c) && 2484 pct_decode_no_slash (str_len, 2485 str, 2486 r, 2487 &c)) 2488 r += 2u; 2489 mhd_ASSUME (w <= r); 2490 str[w++] = c; 2491 } 2492 2493 /* Found first '/' which is not skipped OR the end of the string */ 2494 while (str_len > r) 2495 { 2496 /* Start of a "/segment" */ 2497 char slash_chr = str[r]; 2498 const size_t seg_start = w; 2499 mhd_ASSUME ('/' == slash_chr); 2500 str[w++] = slash_chr; 2501 ++r; 2502 if (str_len > r) 2503 { 2504 char c; 2505 mhd_ASSUME (w <= r); 2506 c = str[r]; 2507 if ('/' == c) 2508 continue; 2509 if (('%' == c) && 2510 pct_decode_no_slash (str_len, 2511 str, 2512 r, 2513 &c)) 2514 r += 2u; 2515 if ('.' == c) 2516 { 2517 char c2; 2518 if (str_len == r + 1u) /* overflow-safe as 'str_len > r' */ 2519 { 2520 /* Found "/." at the end of the string */ 2521 ++r; /* Skip ".", leave bare '/' */ 2522 break; /* At the edge, stop */ 2523 } 2524 mhd_ASSUME (w <= r); 2525 c2 = str[r + 1u]; 2526 if ('/' == c2) 2527 { 2528 /* Found "/./" */ 2529 w = seg_start; /* Rewind output to the '/' at the start of the segment */ 2530 ++r; /* Skip "." */ 2531 continue; /* Go to the next "/", which will be written again */ 2532 } 2533 if (('%' == c2) && 2534 pct_decode_no_slash (str_len, 2535 str, 2536 r + 1u, 2537 &c2)) 2538 r += 2u; 2539 if ('.' == c2) 2540 { 2541 char c3; 2542 if (str_len == r + 2u) /* overflow-safe as 'str_len > r + 1 ' */ 2543 { 2544 /* Found "/.." at the end of the string */ 2545 w = seg_start; 2546 if (0 < w) 2547 do 2548 { /* Rewind output to the start of prev segment */ 2549 --w; 2550 } while (0 < w && '/' != str[w]); 2551 mhd_ASSUME (w < r); 2552 str[w++] = '/'; /* Replace prev segment with '/' */ 2553 r += 2u; /* Skip ".." */ 2554 break; /* At the edge, stop */ 2555 } 2556 mhd_ASSUME (w <= r); 2557 c3 = str[r + 2u]; 2558 if ('/' == c3) 2559 { 2560 /* Found "/../" */ 2561 w = seg_start; 2562 if (0 < w) 2563 do 2564 { /* Rewind output to the start of prev segment */ 2565 --w; 2566 } while (0 < w && '/' != str[w]); 2567 r += 2u; /* Skip ".."; put next '/' to the start of prev segment */ 2568 continue; 2569 } 2570 /* Do not write 'c3' as it has not been percent-decoded */ 2571 } 2572 str[w++] = c; 2573 str[w++] = c2; 2574 r += 2u; 2575 } 2576 else 2577 { 2578 str[w++] = c; 2579 r += 1u; 2580 } 2581 mhd_assert (seg_start < w); 2582 } 2583 for ((void) r; str_len > r && '/' != str[r]; ++r) 2584 { 2585 /* Process the end of the segment */ 2586 char c; 2587 mhd_ASSUME (w <= r); 2588 c = str[r]; 2589 if (('%' == c) && 2590 pct_decode_no_slash (str_len, 2591 str, 2592 r, 2593 &c)) 2594 r += 2u; 2595 mhd_ASSUME (w <= r); 2596 str[w++] = c; 2597 } 2598 mhd_assert (0u != w); 2599 } 2600 mhd_assert (r == str_len); 2601 2602 if (str_len > w) 2603 str[w] = '\0'; 2604 2605 return w; 2606 } 2607 2608 2609 #ifdef MHD_SUPPORT_AUTH_DIGEST 2610 2611 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ 2612 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_IN_SIZE_ (3,4) bool 2613 mhd_str_equal_quoted_bin_n (const char *quoted, 2614 size_t quoted_len, 2615 const char *unquoted, 2616 size_t unquoted_len) 2617 { 2618 size_t i; 2619 size_t j; 2620 if (unquoted_len < quoted_len / 2) 2621 return false; 2622 2623 j = 0; 2624 for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j) 2625 { 2626 if ('\\' == quoted[i]) 2627 { 2628 i++; /* Advance to the next character */ 2629 if (quoted_len == i) 2630 return false; /* No character after escaping backslash */ 2631 } 2632 if (quoted[i] != unquoted[j]) 2633 return false; /* Different characters */ 2634 } 2635 if ((quoted_len != i) || (unquoted_len != j)) 2636 return false; /* The strings have different length */ 2637 2638 return true; 2639 } 2640 2641 2642 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ 2643 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_IN_SIZE_ (3,4) bool 2644 mhd_str_equal_caseless_quoted_bin_n (const char *quoted, 2645 size_t quoted_len, 2646 const char *unquoted, 2647 size_t unquoted_len) 2648 { 2649 size_t i; 2650 size_t j; 2651 if (unquoted_len < quoted_len / 2) 2652 return false; 2653 2654 j = 0; 2655 for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j) 2656 { 2657 if ('\\' == quoted[i]) 2658 { 2659 i++; /* Advance to the next character */ 2660 if (quoted_len == i) 2661 return false; /* No character after escaping backslash */ 2662 } 2663 if (! charsequalcaseless (quoted[i], unquoted[j])) 2664 return false; /* Different characters */ 2665 } 2666 if ((quoted_len != i) || (unquoted_len != j)) 2667 return false; /* The strings have different length */ 2668 2669 return true; 2670 } 2671 2672 2673 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 2674 2675 #if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(MHD_SUPPORT_POST_PARSER) 2676 2677 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 2678 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_SIZE_ (3,2) size_t 2679 mhd_str_unquote (const char *quoted, 2680 size_t quoted_len, 2681 char *result) 2682 { 2683 size_t r; 2684 size_t w; 2685 2686 r = 0; 2687 w = 0; 2688 2689 while (quoted_len > r) 2690 { 2691 if ('\\' == quoted[r]) 2692 { 2693 ++r; 2694 if (quoted_len == r) 2695 return 0; /* Last backslash is not followed by char to unescape */ 2696 } 2697 result[w++] = quoted[r++]; 2698 } 2699 return w; 2700 } 2701 2702 2703 #endif /* MHD_SUPPORT_AUTH_DIGEST || MHD_SUPPORT_POST_PARSER */ 2704 2705 #if defined(MHD_SUPPORT_AUTH_DIGEST) || defined(MHD_SUPPORT_AUTH_BASIC) 2706 2707 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 2708 MHD_FN_PAR_IN_SIZE_ (1,2) 2709 MHD_FN_PAR_OUT_SIZE_ (3,4) size_t 2710 mhd_str_quote (const char *unquoted, 2711 size_t unquoted_len, 2712 char *result, 2713 size_t buf_size) 2714 { 2715 size_t r; 2716 size_t w; 2717 2718 r = 0; 2719 w = 0; 2720 2721 #ifndef MHD_FAVOR_SMALL_CODE 2722 if (unquoted_len * 2 <= buf_size) 2723 { 2724 /* Fast loop: the output will fit the buffer with any input string content */ 2725 while (unquoted_len > r) 2726 { 2727 const char chr = unquoted[r++]; 2728 if (('\\' == chr) || ('\"' == chr)) 2729 result[w++] = '\\'; /* Escape current char */ 2730 result[w++] = chr; 2731 } 2732 } 2733 else 2734 { 2735 if (unquoted_len > buf_size) 2736 return 0; /* Quick fail: the output buffer is too small */ 2737 #else /* MHD_FAVOR_SMALL_CODE */ 2738 if (1) 2739 { 2740 #endif /* MHD_FAVOR_SMALL_CODE */ 2741 2742 while (unquoted_len > r) 2743 { 2744 if (buf_size <= w) 2745 return 0; /* The output buffer is too small */ 2746 else 2747 { 2748 const char chr = unquoted[r++]; 2749 if (('\\' == chr) || ('\"' == chr)) 2750 { 2751 result[w++] = '\\'; /* Escape current char */ 2752 if (buf_size <= w) 2753 return 0; /* The output buffer is too small */ 2754 } 2755 result[w++] = chr; 2756 } 2757 } 2758 } 2759 2760 mhd_assert (w >= r); 2761 mhd_assert (w <= r * 2); 2762 return w; 2763 } 2764 2765 2766 #endif /* MHD_SUPPORT_AUTH_DIGEST || MHD_SUPPORT_AUTH_BASIC */ 2767 2768 #ifdef MHD_SUPPORT_AUTH_BASIC 2769 2770 /* 2771 * MHD_BASE64_FUNC_VERSION 2772 * 1 = smallest, 2773 * 2 = medium, 2774 * 3 = fastest 2775 */ 2776 #ifndef MHD_BASE64_FUNC_VERSION 2777 #ifdef MHD_FAVOR_SMALL_CODE 2778 #define MHD_BASE64_FUNC_VERSION 1 2779 #else /* ! MHD_FAVOR_SMALL_CODE */ 2780 #define MHD_BASE64_FUNC_VERSION 3 2781 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2782 #endif /* ! MHD_BASE64_FUNC_VERSION */ 2783 2784 #if MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 2785 #error Wrong MHD_BASE64_FUNC_VERSION value 2786 #endif /* MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 */ 2787 2788 #if MHD_BASE64_FUNC_VERSION == 3 2789 #define mhd_base64_map_type int 2790 #else /* MHD_BASE64_FUNC_VERSION < 3 */ 2791 #define mhd_base64_map_type int8_t 2792 #endif /* MHD_BASE64_FUNC_VERSION < 3 */ 2793 2794 #if MHD_BASE64_FUNC_VERSION == 1 2795 static mhd_base64_map_type 2796 base64_char_to_value_ (uint8_t c) 2797 { 2798 if ('Z' >= c) 2799 { 2800 if ('A' <= c) 2801 return (mhd_base64_map_type) ((c - 'A') + 0); 2802 else if ('0' <= c) 2803 { 2804 if ('9' >= c) 2805 return (mhd_base64_map_type) ((c - '0') + 52); 2806 else if ('=' == c) 2807 return -2; 2808 else 2809 return -1; 2810 } 2811 else if ('+' == c) 2812 return 62; 2813 else if ('/' == c) 2814 return 63; 2815 else 2816 return -1; 2817 } 2818 else if (('z' >= c) && ('a' <= c)) 2819 return (mhd_base64_map_type) ((c - 'a') + 26); 2820 return -1; 2821 } 2822 2823 2824 #endif /* MHD_BASE64_FUNC_VERSION == 1 */ 2825 2826 2827 mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE 2828 2829 2830 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 2831 MHD_FN_PAR_IN_SIZE_ (1,2) MHD_FN_PAR_OUT_SIZE_ (3,4) size_t 2832 mhd_base64_to_bin_n (const char *base64, 2833 size_t base64_len, 2834 void *bin, 2835 size_t bin_size) 2836 { 2837 #if MHD_BASE64_FUNC_VERSION >= 2 2838 static const mhd_base64_map_type map[] = { 2839 /* -1 = invalid char, -2 = padding 2840 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 2841 NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, */ 2842 -1, -1, -1, -1, -1, -1, -1, -1, 2843 /* 2844 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 2845 BS, HT, LF, VT, FF, CR, SO, SI, */ 2846 -1, -1, -1, -1, -1, -1, -1, -1, 2847 /* 2848 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 2849 DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, */ 2850 -1, -1, -1, -1, -1, -1, -1, -1, 2851 /* 2852 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 2853 CAN, EM, SUB, ESC, FS, GS, RS, US, */ 2854 -1, -1, -1, -1, -1, -1, -1, -1, 2855 /* 2856 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 2857 ' ', '!', '"', '#', '$', '%', '&', '\'', */ 2858 -1, -1, -1, -1, -1, -1, -1, -1, 2859 /* 2860 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 2861 '(', ')', '*', '+', ',', '-', '.', '/', */ 2862 -1, -1, -1, 62, -1, -1, -1, 63, 2863 /* 2864 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 2865 '0', '1', '2', '3', '4', '5', '6', '7', */ 2866 52, 53, 54, 55, 56, 57, 58, 59, 2867 /* 2868 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 2869 '8', '9', ':', ';', '<', '=', '>', '?', */ 2870 60, 61, -1, -1, -1, -2, -1, -1, 2871 /* 2872 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 2873 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */ 2874 -1, 0, 1, 2, 3, 4, 5, 6, 2875 /* 2876 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 2877 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */ 2878 7, 8, 9, 10, 11, 12, 13, 14, 2879 /* 2880 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 2881 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */ 2882 15, 16, 17, 18, 19, 20, 21, 22, 2883 /* 2884 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 2885 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */ 2886 23, 24, 25, -1, -1, -1, -1, -1, 2887 /* 2888 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 2889 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */ 2890 -1, 26, 27, 28, 29, 30, 31, 32, 2891 /* 2892 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 2893 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */ 2894 33, 34, 35, 36, 37, 38, 39, 40, 2895 /* 2896 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 2897 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */ 2898 41, 42, 43, 44, 45, 46, 47, 48, 2899 /* 2900 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 2901 'x', 'y', 'z', '{', '|', '}', '~', DEL, */ 2902 49, 50, 51, -1, -1, -1, -1, -1 2903 2904 #if MHD_BASE64_FUNC_VERSION == 3 2905 , 2906 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80..8F */ 2907 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90..9F */ 2908 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0..AF */ 2909 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0..BF */ 2910 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0..CF */ 2911 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0..DF */ 2912 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0..EF */ 2913 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* F0..FF */ 2914 #endif /* ! MHD_BASE64_FUNC_VERSION == 3 */ 2915 }; 2916 #define base64_char_to_value_(c) map[(c)] 2917 #endif /* MHD_BASE64_FUNC_VERSION >= 2 */ 2918 const uint8_t *const in = (const uint8_t *) base64; 2919 uint8_t *const out = (uint8_t *) bin; 2920 size_t i; 2921 size_t j; 2922 if (0 == base64_len) 2923 return 0; /* Nothing to decode */ 2924 if (0 != base64_len % 4) 2925 return 0; /* Wrong input length */ 2926 if (base64_len / 4 * 3 - 2 > bin_size) 2927 return 0; 2928 2929 j = 0; 2930 for (i = 0; i < (base64_len - 4); i += 4) 2931 { 2932 #if MHD_BASE64_FUNC_VERSION == 2 2933 if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3]))) 2934 return 0; 2935 #endif /* MHD_BASE64_FUNC_VERSION == 2 */ 2936 if (1) 2937 { 2938 const mhd_base64_map_type v1 = base64_char_to_value_ (in[i + 0]); 2939 const mhd_base64_map_type v2 = base64_char_to_value_ (in[i + 1]); 2940 const mhd_base64_map_type v3 = base64_char_to_value_ (in[i + 2]); 2941 const mhd_base64_map_type v4 = base64_char_to_value_ (in[i + 3]); 2942 if ((0 > v1) || (0 > v2) || (0 > v3) || (0 > v4)) 2943 return 0; 2944 out[j + 0] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2)) 2945 | ((uint8_t) (((uint8_t) v2) >> 4))); 2946 out[j + 1] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4)) 2947 | ((uint8_t) (((uint8_t) v3) >> 2))); 2948 out[j + 2] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6)) 2949 | ((uint8_t) v4)); 2950 } 2951 j += 3; 2952 } 2953 #if MHD_BASE64_FUNC_VERSION == 2 2954 if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3]))) 2955 return 0; 2956 #endif /* MHD_BASE64_FUNC_VERSION == 2 */ 2957 if (1) 2958 { /* The last four chars block */ 2959 const mhd_base64_map_type v1 = base64_char_to_value_ (in[i + 0]); 2960 const mhd_base64_map_type v2 = base64_char_to_value_ (in[i + 1]); 2961 const mhd_base64_map_type v3 = base64_char_to_value_ (in[i + 2]); 2962 const mhd_base64_map_type v4 = base64_char_to_value_ (in[i + 3]); 2963 if ((0 > v1) || (0 > v2)) 2964 return 0; /* Invalid char or padding at first two positions */ 2965 mhd_assert (j < bin_size); 2966 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2)) 2967 | ((uint8_t) (((uint8_t) v2) >> 4))); 2968 if (0 > v3) 2969 { /* Third char is either padding or invalid */ 2970 if ((-2 != v3) || (-2 != v4)) 2971 return 0; /* Both two last chars must be padding */ 2972 if (0 != (uint8_t) (((uint8_t) v2) << 4)) 2973 return 0; /* Wrong last char */ 2974 return j; 2975 } 2976 if (j >= bin_size) 2977 return 0; /* Not enough space */ 2978 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4)) 2979 | ((uint8_t) (((uint8_t) v3) >> 2))); 2980 if (0 > v4) 2981 { /* Fourth char is either padding or invalid */ 2982 if (-2 != v4) 2983 return 0; /* The char must be padding */ 2984 if (0 != (uint8_t) (((uint8_t) v3) << 6)) 2985 return 0; /* Wrong last char */ 2986 return j; 2987 } 2988 if (j >= bin_size) 2989 return 0; /* Not enough space */ 2990 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6)) 2991 | ((uint8_t) v4)); 2992 } 2993 return j; 2994 #if MHD_BASE64_FUNC_VERSION >= 2 2995 #undef base64_char_to_value_ 2996 #endif /* MHD_BASE64_FUNC_VERSION >= 2 */ 2997 } 2998 2999 3000 mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE 3001 3002 3003 #undef mhd_base64_map_type 3004 3005 #endif /* MHD_SUPPORT_AUTH_BASIC */ 3006 3007 3008 MHD_INTERNAL MHD_FN_PURE_ MHD_FN_PAR_NONNULL_ALL_ bool 3009 mhd_str_starts_with_token_opt_param (const struct MHD_String *restrict str, 3010 const struct MHD_String *restrict token) 3011 { 3012 size_t i; 3013 3014 mhd_assert (0 != token->len); 3015 mhd_assert (NULL == memchr (token->cstr, '=', token->len)); 3016 mhd_assert (NULL == memchr (token->cstr, ' ', token->len)); 3017 mhd_assert (NULL == memchr (token->cstr, '\t', token->len)); 3018 3019 if (str->len < token->len) 3020 return false; /* The string is too short to match */ 3021 3022 if (! mhd_str_equal_caseless_bin_n (str->cstr, 3023 token->cstr, 3024 token->len)) 3025 return false; /* The string does not start with the token */ 3026 3027 for (i = token->len; i < str->len; ++i) 3028 { 3029 const char c = str->cstr[i]; 3030 if ((' ' == c) || ('\t' == c)) 3031 continue; 3032 if (';' == c) 3033 return true; /* Found the start of the token parameters */ 3034 return false; /* The initial part of the string does not fully match the token */ 3035 } 3036 mhd_assert (0 && "The string should not have whitespace at the end"); 3037 return true; 3038 } 3039 3040 3041 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 3042 MHD_FN_PAR_IN_ (1) MHD_FN_PAR_IN_ (2) MHD_FN_PAR_IN_ (3) 3043 MHD_FN_PAR_OUT_ (4) MHD_FN_PAR_OUT_ (5) enum mhd_StingStartsWithTokenResult 3044 mhd_str_starts_with_token_req_param ( 3045 const struct MHD_String *restrict str, 3046 const struct MHD_String *restrict token, 3047 const struct MHD_String *restrict par, 3048 struct mhd_BufferConst *restrict par_value, 3049 bool *restrict par_value_needs_unquote) 3050 { 3051 size_t i; 3052 const char *const restrict cstr = str->cstr; 3053 bool token_found; 3054 bool param_found; 3055 3056 mhd_assert (0 != token->len); 3057 mhd_assert (NULL == memchr (token->cstr, '=', token->len)); 3058 mhd_assert (NULL == memchr (token->cstr, ' ', token->len)); 3059 mhd_assert (NULL == memchr (token->cstr, '\t', token->len)); 3060 mhd_assert (NULL == memchr (par->cstr, '=', par->len)); 3061 mhd_assert (NULL == memchr (par->cstr, ' ', par->len)); 3062 mhd_assert (NULL == memchr (par->cstr, '\t', par->len)); 3063 3064 par_value->data = NULL; 3065 par_value->size = 0; 3066 3067 if (str->len < token->len) 3068 return mhd_STR_STARTS_W_TOKEN_NO_TOKEN; /* The string is too short to match */ 3069 3070 if (! mhd_str_equal_caseless_bin_n (cstr, 3071 token->cstr, 3072 token->len)) 3073 return mhd_STR_STARTS_W_TOKEN_NO_TOKEN; /* The string does not start with the token */ 3074 token_found = false; 3075 param_found = false; 3076 3077 i = token->len; 3078 do 3079 { 3080 /* Find start of the next parameter */ 3081 for ((void) 0; i < str->len; ++i) 3082 { 3083 const char c = cstr[i]; 3084 if ((' ' == c) || ('\t' == c)) 3085 continue; 3086 if (';' == c) 3087 { 3088 /* Found the start of the next token parameter */ 3089 if (param_found) 3090 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; 3091 ++i; /* Move to the next char */ 3092 break; 3093 } 3094 if (',' == c) 3095 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; /* Found the start of the next token */ 3096 3097 if (! token_found) 3098 { 3099 if (i == token->len) 3100 { 3101 /* The initial part of the string does not fully match the token or 3102 formatting is not correct */ 3103 return mhd_STR_STARTS_W_TOKEN_NO_TOKEN; 3104 } 3105 /* The string has garbage after the token and whitespace */ 3106 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN_BAD_FORMAT; 3107 } 3108 /* The garbage after the parameter */ 3109 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN_BAD_FORMAT; 3110 } 3111 token_found = true; 3112 3113 if (i == str->len) 3114 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; 3115 3116 /* 'i' is at the start of the parameter */ 3117 3118 while ((' ' == cstr[i]) || ('\t' == cstr[i])) 3119 { 3120 if (++i == str->len) 3121 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; 3122 } 3123 3124 /* 'i' is at the start of the parameter name */ 3125 3126 if (par->len > str->len - i - 1) 3127 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; /* the token is found, but the parameter is not */ 3128 else 3129 { /* Check the parameter */ 3130 bool val_needs_unquote; 3131 size_t j; 3132 const char *const prm_str = cstr + i; 3133 3134 for (j = 0; j < par->len; ++j) 3135 if (! charsequalcaseless (prm_str[j], 3136 par->cstr[j])) 3137 break; 3138 i += j; 3139 mhd_assert (str->len > i); 3140 if ((j == par->len) && 3141 ('=' == cstr[i])) 3142 { 3143 /* The parameter name matches required parameter */ 3144 param_found = true; 3145 par_value->data = cstr + i + 1; 3146 } 3147 else 3148 { 3149 /* i points to the char in the parameter name */ 3150 while ('=' != cstr[i]) 3151 { 3152 if ((';' == cstr[i]) /* end of the parameter */ 3153 || (',' == cstr[i]) /* end of the token */ 3154 || (str->len == ++i)) /* end of the field string */ 3155 { 3156 /* parameter without the value */ 3157 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN_BAD_FORMAT; 3158 } 3159 } 3160 } 3161 mhd_assert (str->len > i); 3162 mhd_assert ('=' == cstr[i]); 3163 3164 /* 'i' points to '=' between parameter name and parameter value */ 3165 3166 ++i; /* Advance to the first char in the parameter value */ 3167 if (str->len == i) 3168 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; /* Zero-length parameter value */ 3169 3170 val_needs_unquote = false; 3171 3172 /* 'i' points to the char after '=' */ 3173 3174 if ('"' == cstr[i]) 3175 { 3176 /* The value is quoted */ 3177 if (param_found) 3178 ++(par_value->data); /* Point to the first quoted char */ 3179 do 3180 { 3181 ++i; /* Advance to the next char */ 3182 if (str->len == i) 3183 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN_BAD_FORMAT; /* No closing quote */ 3184 if ('\\' == cstr[i]) 3185 { 3186 val_needs_unquote = true; 3187 ++i; /* Skip quoted char */ 3188 if (str->len == i) 3189 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN_BAD_FORMAT; /* No closing quote */ 3190 } 3191 } while ('"' != cstr[i]); 3192 if (param_found) 3193 { 3194 par_value->size = (size_t) ((cstr + i) - par_value->data); 3195 *par_value_needs_unquote = val_needs_unquote; 3196 } 3197 /* Complete value found */ 3198 /* Check for the garbage data at the end */ 3199 ++i; /* Advance to the next char */ 3200 } 3201 else 3202 { 3203 /* The value is not quoted */ 3204 while ((' ' != cstr[i]) && 3205 ('\t' != cstr[i])) 3206 { 3207 if ((';' == cstr[i]) /* end of the parameter */ 3208 || (',' == cstr[i]) /* end of the token */ 3209 || (str->len == ++i)) /* end of the field string */ 3210 break; 3211 } 3212 /* The end parameter value */ 3213 if (param_found) 3214 { 3215 par_value->size = (size_t) ((cstr + i) - par_value->data); 3216 *par_value_needs_unquote = false; 3217 } 3218 /* Check for the garbage data at the end */ 3219 } 3220 3221 /* 'i' points to the next char after end of the parameter value */ 3222 } 3223 } while (i < str->len); 3224 3225 mhd_assert (token_found); 3226 return mhd_STR_STARTS_W_TOKEN_HAS_TOKEN; 3227 }