mhd_str.c (65755B)
1 /* 2 This file is part of libmicrohttpd 3 Copyright (C) 2015-2024 Karlson2k (Evgeny Grin) 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /** 21 * @file microhttpd/mhd_str.c 22 * @brief Functions implementations for string manipulating 23 * @author Karlson2k (Evgeny Grin) 24 */ 25 26 #include "mhd_str.h" 27 28 #ifdef HAVE_STDBOOL_H 29 #include <stdbool.h> 30 #endif /* HAVE_STDBOOL_H */ 31 #include <string.h> 32 33 #include "mhd_assert.h" 34 #include "mhd_limits.h" 35 #include "mhd_assert.h" 36 37 #ifdef MHD_FAVOR_SMALL_CODE 38 #ifdef _MHD_static_inline 39 #undef _MHD_static_inline 40 #endif /* _MHD_static_inline */ 41 /* Do not force inlining and do not use macro functions, use normal static 42 functions instead. 43 This may give more flexibility for size optimizations. */ 44 #define _MHD_static_inline static 45 #ifndef HAVE_INLINE_FUNCS 46 #define HAVE_INLINE_FUNCS 1 47 #endif /* !INLINE_FUNC */ 48 #endif /* MHD_FAVOR_SMALL_CODE */ 49 50 /* 51 * Block of functions/macros that use US-ASCII charset as required by HTTP 52 * standards. Not affected by current locale settings. 53 */ 54 55 #ifdef HAVE_INLINE_FUNCS 56 57 #if 0 /* Disable unused functions. */ 58 /** 59 * Check whether character is lower case letter in US-ASCII 60 * 61 * @param c character to check 62 * @return non-zero if character is lower case letter, zero otherwise 63 */ 64 _MHD_static_inline bool 65 isasciilower (char c) 66 { 67 return (c >= 'a') && (c <= 'z'); 68 } 69 70 71 #endif /* Disable unused functions. */ 72 73 74 /** 75 * Check whether character is upper case letter in US-ASCII 76 * 77 * @param c character to check 78 * @return non-zero if character is upper case letter, zero otherwise 79 */ 80 _MHD_static_inline bool 81 isasciiupper (char c) 82 { 83 return (c >= 'A') && (c <= 'Z'); 84 } 85 86 87 #if 0 /* Disable unused functions. */ 88 /** 89 * Check whether character is letter in US-ASCII 90 * 91 * @param c character to check 92 * @return non-zero if character is letter in US-ASCII, zero otherwise 93 */ 94 _MHD_static_inline bool 95 isasciialpha (char c) 96 { 97 return isasciilower (c) || isasciiupper (c); 98 } 99 100 101 #endif /* Disable unused functions. */ 102 103 104 /** 105 * Check whether character is decimal digit in US-ASCII 106 * 107 * @param c character to check 108 * @return non-zero if character is decimal digit, zero otherwise 109 */ 110 _MHD_static_inline bool 111 isasciidigit (char c) 112 { 113 return (c >= '0') && (c <= '9'); 114 } 115 116 117 #if 0 /* Disable unused functions. */ 118 /** 119 * Check whether character is hexadecimal digit in US-ASCII 120 * 121 * @param c character to check 122 * @return non-zero if character is decimal digit, zero otherwise 123 */ 124 _MHD_static_inline bool 125 isasciixdigit (char c) 126 { 127 return isasciidigit (c) || 128 ( (c >= 'A') && (c <= 'F') ) || 129 ( (c >= 'a') && (c <= 'f') ); 130 } 131 132 133 /** 134 * Check whether character is decimal digit or letter in US-ASCII 135 * 136 * @param c character to check 137 * @return non-zero if character is decimal digit or letter, zero otherwise 138 */ 139 _MHD_static_inline bool 140 isasciialnum (char c) 141 { 142 return isasciialpha (c) || isasciidigit (c); 143 } 144 145 146 #endif /* Disable unused functions. */ 147 148 149 #if 0 /* Disable unused functions. */ 150 /** 151 * Convert US-ASCII character to lower case. 152 * If character is upper case letter in US-ASCII than it's converted to lower 153 * case analog. If character is NOT upper case letter than it's returned 154 * unmodified. 155 * 156 * @param c character to convert 157 * @return converted to lower case character 158 */ 159 _MHD_static_inline char 160 toasciilower (char c) 161 { 162 return isasciiupper (c) ? (c - 'A' + 'a') : c; 163 } 164 165 166 /** 167 * Convert US-ASCII character to upper case. 168 * If character is lower case letter in US-ASCII than it's converted to upper 169 * case analog. If character is NOT lower case letter than it's returned 170 * unmodified. 171 * 172 * @param c character to convert 173 * @return converted to upper case character 174 */ 175 _MHD_static_inline char 176 toasciiupper (char c) 177 { 178 return isasciilower (c) ? (c - 'a' + 'A') : c; 179 } 180 181 182 #endif /* Disable unused functions. */ 183 184 185 #if defined(MHD_FAVOR_SMALL_CODE) /* Used only in MHD_str_to_uvalue_n_() */ 186 /** 187 * Convert US-ASCII decimal digit to its value. 188 * 189 * @param c character to convert 190 * @return value of decimal digit or -1 if @ c is not decimal digit 191 */ 192 _MHD_static_inline int 193 todigitvalue (char c) 194 { 195 if (isasciidigit (c)) 196 return (unsigned char) (c - '0'); 197 198 return -1; 199 } 200 201 202 #endif /* MHD_FAVOR_SMALL_CODE */ 203 204 205 /** 206 * Convert US-ASCII hexadecimal digit to its value. 207 * 208 * @param c character to convert 209 * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit 210 */ 211 _MHD_static_inline int 212 toxdigitvalue (char c) 213 { 214 #if ! defined(MHD_FAVOR_SMALL_CODE) 215 switch ((unsigned char) c) 216 { 217 #if 0 /* Disabled to give the compiler a hint about low probability */ 218 case 0x00U: /* NUL */ 219 case 0x01U: /* SOH */ 220 case 0x02U: /* STX */ 221 case 0x03U: /* ETX */ 222 case 0x04U: /* EOT */ 223 case 0x05U: /* ENQ */ 224 case 0x06U: /* ACK */ 225 case 0x07U: /* BEL */ 226 case 0x08U: /* BS */ 227 case 0x09U: /* HT */ 228 case 0x0AU: /* LF */ 229 case 0x0BU: /* VT */ 230 case 0x0CU: /* FF */ 231 case 0x0DU: /* CR */ 232 case 0x0EU: /* SO */ 233 case 0x0FU: /* SI */ 234 case 0x10U: /* DLE */ 235 case 0x11U: /* DC1 */ 236 case 0x12U: /* DC2 */ 237 case 0x13U: /* DC3 */ 238 case 0x14U: /* DC4 */ 239 case 0x15U: /* NAK */ 240 case 0x16U: /* SYN */ 241 case 0x17U: /* ETB */ 242 case 0x18U: /* CAN */ 243 case 0x19U: /* EM */ 244 case 0x1AU: /* SUB */ 245 case 0x1BU: /* ESC */ 246 case 0x1CU: /* FS */ 247 case 0x1DU: /* GS */ 248 case 0x1EU: /* RS */ 249 case 0x1FU: /* US */ 250 case 0x20U: /* ' ' */ 251 case 0x21U: /* '!' */ 252 case 0x22U: /* '"' */ 253 case 0x23U: /* '#' */ 254 case 0x24U: /* '$' */ 255 case 0x25U: /* '%' */ 256 case 0x26U: /* '&' */ 257 case 0x27U: /* '\'' */ 258 case 0x28U: /* '(' */ 259 case 0x29U: /* ')' */ 260 case 0x2AU: /* '*' */ 261 case 0x2BU: /* '+' */ 262 case 0x2CU: /* ',' */ 263 case 0x2DU: /* '-' */ 264 case 0x2EU: /* '.' */ 265 case 0x2FU: /* '/' */ 266 return -1; 267 #endif 268 case 0x30U: /* '0' */ 269 return 0; 270 case 0x31U: /* '1' */ 271 return 1; 272 case 0x32U: /* '2' */ 273 return 2; 274 case 0x33U: /* '3' */ 275 return 3; 276 case 0x34U: /* '4' */ 277 return 4; 278 case 0x35U: /* '5' */ 279 return 5; 280 case 0x36U: /* '6' */ 281 return 6; 282 case 0x37U: /* '7' */ 283 return 7; 284 case 0x38U: /* '8' */ 285 return 8; 286 case 0x39U: /* '9' */ 287 return 9; 288 #if 0 /* Disabled to give the compiler a hint about low probability */ 289 case 0x3AU: /* ':' */ 290 case 0x3BU: /* ';' */ 291 case 0x3CU: /* '<' */ 292 case 0x3DU: /* '=' */ 293 case 0x3EU: /* '>' */ 294 case 0x3FU: /* '?' */ 295 case 0x40U: /* '@' */ 296 return -1; 297 #endif 298 case 0x41U: /* 'A' */ 299 return 0xAU; 300 case 0x42U: /* 'B' */ 301 return 0xBU; 302 case 0x43U: /* 'C' */ 303 return 0xCU; 304 case 0x44U: /* 'D' */ 305 return 0xDU; 306 case 0x45U: /* 'E' */ 307 return 0xEU; 308 case 0x46U: /* 'F' */ 309 return 0xFU; 310 #if 0 /* Disabled to give the compiler a hint about low probability */ 311 case 0x47U: /* 'G' */ 312 case 0x48U: /* 'H' */ 313 case 0x49U: /* 'I' */ 314 case 0x4AU: /* 'J' */ 315 case 0x4BU: /* 'K' */ 316 case 0x4CU: /* 'L' */ 317 case 0x4DU: /* 'M' */ 318 case 0x4EU: /* 'N' */ 319 case 0x4FU: /* 'O' */ 320 case 0x50U: /* 'P' */ 321 case 0x51U: /* 'Q' */ 322 case 0x52U: /* 'R' */ 323 case 0x53U: /* 'S' */ 324 case 0x54U: /* 'T' */ 325 case 0x55U: /* 'U' */ 326 case 0x56U: /* 'V' */ 327 case 0x57U: /* 'W' */ 328 case 0x58U: /* 'X' */ 329 case 0x59U: /* 'Y' */ 330 case 0x5AU: /* 'Z' */ 331 case 0x5BU: /* '[' */ 332 case 0x5CU: /* '\' */ 333 case 0x5DU: /* ']' */ 334 case 0x5EU: /* '^' */ 335 case 0x5FU: /* '_' */ 336 case 0x60U: /* '`' */ 337 return -1; 338 #endif 339 case 0x61U: /* 'a' */ 340 return 0xAU; 341 case 0x62U: /* 'b' */ 342 return 0xBU; 343 case 0x63U: /* 'c' */ 344 return 0xCU; 345 case 0x64U: /* 'd' */ 346 return 0xDU; 347 case 0x65U: /* 'e' */ 348 return 0xEU; 349 case 0x66U: /* 'f' */ 350 return 0xFU; 351 #if 0 /* Disabled to give the compiler a hint about low probability */ 352 case 0x67U: /* 'g' */ 353 case 0x68U: /* 'h' */ 354 case 0x69U: /* 'i' */ 355 case 0x6AU: /* 'j' */ 356 case 0x6BU: /* 'k' */ 357 case 0x6CU: /* 'l' */ 358 case 0x6DU: /* 'm' */ 359 case 0x6EU: /* 'n' */ 360 case 0x6FU: /* 'o' */ 361 case 0x70U: /* 'p' */ 362 case 0x71U: /* 'q' */ 363 case 0x72U: /* 'r' */ 364 case 0x73U: /* 's' */ 365 case 0x74U: /* 't' */ 366 case 0x75U: /* 'u' */ 367 case 0x76U: /* 'v' */ 368 case 0x77U: /* 'w' */ 369 case 0x78U: /* 'x' */ 370 case 0x79U: /* 'y' */ 371 case 0x7AU: /* 'z' */ 372 case 0x7BU: /* '{' */ 373 case 0x7CU: /* '|' */ 374 case 0x7DU: /* '}' */ 375 case 0x7EU: /* '~' */ 376 case 0x7FU: /* DEL */ 377 case 0x80U: /* EXT */ 378 case 0x81U: /* EXT */ 379 case 0x82U: /* EXT */ 380 case 0x83U: /* EXT */ 381 case 0x84U: /* EXT */ 382 case 0x85U: /* EXT */ 383 case 0x86U: /* EXT */ 384 case 0x87U: /* EXT */ 385 case 0x88U: /* EXT */ 386 case 0x89U: /* EXT */ 387 case 0x8AU: /* EXT */ 388 case 0x8BU: /* EXT */ 389 case 0x8CU: /* EXT */ 390 case 0x8DU: /* EXT */ 391 case 0x8EU: /* EXT */ 392 case 0x8FU: /* EXT */ 393 case 0x90U: /* EXT */ 394 case 0x91U: /* EXT */ 395 case 0x92U: /* EXT */ 396 case 0x93U: /* EXT */ 397 case 0x94U: /* EXT */ 398 case 0x95U: /* EXT */ 399 case 0x96U: /* EXT */ 400 case 0x97U: /* EXT */ 401 case 0x98U: /* EXT */ 402 case 0x99U: /* EXT */ 403 case 0x9AU: /* EXT */ 404 case 0x9BU: /* EXT */ 405 case 0x9CU: /* EXT */ 406 case 0x9DU: /* EXT */ 407 case 0x9EU: /* EXT */ 408 case 0x9FU: /* EXT */ 409 case 0xA0U: /* EXT */ 410 case 0xA1U: /* EXT */ 411 case 0xA2U: /* EXT */ 412 case 0xA3U: /* EXT */ 413 case 0xA4U: /* EXT */ 414 case 0xA5U: /* EXT */ 415 case 0xA6U: /* EXT */ 416 case 0xA7U: /* EXT */ 417 case 0xA8U: /* EXT */ 418 case 0xA9U: /* EXT */ 419 case 0xAAU: /* EXT */ 420 case 0xABU: /* EXT */ 421 case 0xACU: /* EXT */ 422 case 0xADU: /* EXT */ 423 case 0xAEU: /* EXT */ 424 case 0xAFU: /* EXT */ 425 case 0xB0U: /* EXT */ 426 case 0xB1U: /* EXT */ 427 case 0xB2U: /* EXT */ 428 case 0xB3U: /* EXT */ 429 case 0xB4U: /* EXT */ 430 case 0xB5U: /* EXT */ 431 case 0xB6U: /* EXT */ 432 case 0xB7U: /* EXT */ 433 case 0xB8U: /* EXT */ 434 case 0xB9U: /* EXT */ 435 case 0xBAU: /* EXT */ 436 case 0xBBU: /* EXT */ 437 case 0xBCU: /* EXT */ 438 case 0xBDU: /* EXT */ 439 case 0xBEU: /* EXT */ 440 case 0xBFU: /* EXT */ 441 case 0xC0U: /* EXT */ 442 case 0xC1U: /* EXT */ 443 case 0xC2U: /* EXT */ 444 case 0xC3U: /* EXT */ 445 case 0xC4U: /* EXT */ 446 case 0xC5U: /* EXT */ 447 case 0xC6U: /* EXT */ 448 case 0xC7U: /* EXT */ 449 case 0xC8U: /* EXT */ 450 case 0xC9U: /* EXT */ 451 case 0xCAU: /* EXT */ 452 case 0xCBU: /* EXT */ 453 case 0xCCU: /* EXT */ 454 case 0xCDU: /* EXT */ 455 case 0xCEU: /* EXT */ 456 case 0xCFU: /* EXT */ 457 case 0xD0U: /* EXT */ 458 case 0xD1U: /* EXT */ 459 case 0xD2U: /* EXT */ 460 case 0xD3U: /* EXT */ 461 case 0xD4U: /* EXT */ 462 case 0xD5U: /* EXT */ 463 case 0xD6U: /* EXT */ 464 case 0xD7U: /* EXT */ 465 case 0xD8U: /* EXT */ 466 case 0xD9U: /* EXT */ 467 case 0xDAU: /* EXT */ 468 case 0xDBU: /* EXT */ 469 case 0xDCU: /* EXT */ 470 case 0xDDU: /* EXT */ 471 case 0xDEU: /* EXT */ 472 case 0xDFU: /* EXT */ 473 case 0xE0U: /* EXT */ 474 case 0xE1U: /* EXT */ 475 case 0xE2U: /* EXT */ 476 case 0xE3U: /* EXT */ 477 case 0xE4U: /* EXT */ 478 case 0xE5U: /* EXT */ 479 case 0xE6U: /* EXT */ 480 case 0xE7U: /* EXT */ 481 case 0xE8U: /* EXT */ 482 case 0xE9U: /* EXT */ 483 case 0xEAU: /* EXT */ 484 case 0xEBU: /* EXT */ 485 case 0xECU: /* EXT */ 486 case 0xEDU: /* EXT */ 487 case 0xEEU: /* EXT */ 488 case 0xEFU: /* EXT */ 489 case 0xF0U: /* EXT */ 490 case 0xF1U: /* EXT */ 491 case 0xF2U: /* EXT */ 492 case 0xF3U: /* EXT */ 493 case 0xF4U: /* EXT */ 494 case 0xF5U: /* EXT */ 495 case 0xF6U: /* EXT */ 496 case 0xF7U: /* EXT */ 497 case 0xF8U: /* EXT */ 498 case 0xF9U: /* EXT */ 499 case 0xFAU: /* EXT */ 500 case 0xFBU: /* EXT */ 501 case 0xFCU: /* EXT */ 502 case 0xFDU: /* EXT */ 503 case 0xFEU: /* EXT */ 504 case 0xFFU: /* EXT */ 505 return -1; 506 default: 507 mhd_assert (0); 508 break; /* Should be unreachable */ 509 #else 510 default: 511 break; 512 #endif 513 } 514 return -1; 515 #else /* MHD_FAVOR_SMALL_CODE */ 516 if (isasciidigit (c)) 517 return (unsigned char) (c - '0'); 518 if ( (c >= 'A') && (c <= 'F') ) 519 return (unsigned char) (c - 'A' + 10); 520 if ( (c >= 'a') && (c <= 'f') ) 521 return (unsigned char) (c - 'a' + 10); 522 523 return -1; 524 #endif /* MHD_FAVOR_SMALL_CODE */ 525 } 526 527 528 /** 529 * Caseless compare two characters. 530 * 531 * @param c1 the first char to compare 532 * @param c2 the second char to compare 533 * @return boolean 'true' if chars are caseless equal, false otherwise 534 */ 535 _MHD_static_inline bool 536 charsequalcaseless (const char c1, const char c2) 537 { 538 return ( (c1 == c2) || 539 (isasciiupper (c1) ? 540 ((c1 - 'A' + 'a') == c2) : 541 ((c1 == (c2 - 'A' + 'a')) && isasciiupper (c2))) ); 542 } 543 544 545 #else /* !INLINE_FUNC */ 546 547 548 /** 549 * Checks whether character is lower case letter in US-ASCII 550 * 551 * @param c character to check 552 * @return boolean true if character is lower case letter, 553 * boolean false otherwise 554 */ 555 #define isasciilower(c) (((char) (c)) >= 'a' && ((char) (c)) <= 'z') 556 557 558 /** 559 * Checks whether character is upper case letter in US-ASCII 560 * 561 * @param c character to check 562 * @return boolean true if character is upper case letter, 563 * boolean false otherwise 564 */ 565 #define isasciiupper(c) (((char) (c)) >= 'A' && ((char) (c)) <= 'Z') 566 567 568 /** 569 * Checks whether character is letter in US-ASCII 570 * 571 * @param c character to check 572 * @return boolean true if character is letter, boolean false 573 * otherwise 574 */ 575 #define isasciialpha(c) (isasciilower (c) || isasciiupper (c)) 576 577 578 /** 579 * Check whether character is decimal digit in US-ASCII 580 * 581 * @param c character to check 582 * @return boolean true if character is decimal digit, boolean false 583 * otherwise 584 */ 585 #define isasciidigit(c) (((char) (c)) >= '0' && ((char) (c)) <= '9') 586 587 588 /** 589 * Check whether character is hexadecimal digit in US-ASCII 590 * 591 * @param c character to check 592 * @return boolean true if character is hexadecimal digit, 593 * boolean false otherwise 594 */ 595 #define isasciixdigit(c) (isasciidigit ((c)) || \ 596 (((char) (c)) >= 'A' && ((char) (c)) <= 'F') || \ 597 (((char) (c)) >= 'a' && ((char) (c)) <= 'f') ) 598 599 600 /** 601 * Check whether character is decimal digit or letter in US-ASCII 602 * 603 * @param c character to check 604 * @return boolean true if character is decimal digit or letter, 605 * boolean false otherwise 606 */ 607 #define isasciialnum(c) (isasciialpha (c) || isasciidigit (c)) 608 609 610 /** 611 * Convert US-ASCII character to lower case. 612 * If character is upper case letter in US-ASCII than it's converted to lower 613 * case analog. If character is NOT upper case letter than it's returned 614 * unmodified. 615 * 616 * @param c character to convert 617 * @return converted to lower case character 618 */ 619 #define toasciilower(c) ((isasciiupper (c)) ? (((char) (c)) - 'A' + 'a') : \ 620 ((char) (c))) 621 622 623 /** 624 * Convert US-ASCII character to upper case. 625 * If character is lower case letter in US-ASCII than it's converted to upper 626 * case analog. If character is NOT lower case letter than it's returned 627 * unmodified. 628 * 629 * @param c character to convert 630 * @return converted to upper case character 631 */ 632 #define toasciiupper(c) ((isasciilower (c)) ? (((char) (c)) - 'a' + 'A') : \ 633 ((char) (c))) 634 635 636 /** 637 * Convert US-ASCII decimal digit to its value. 638 * 639 * @param c character to convert 640 * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit 641 */ 642 #define todigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \ 643 (int) (-1)) 644 645 646 /** 647 * Convert US-ASCII hexadecimal digit to its value. 648 * @param c character to convert 649 * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit 650 */ 651 #define toxdigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \ 652 ( (((char) (c)) >= 'A' && ((char) (c)) <= 'F') ? \ 653 (int) (((unsigned char) (c)) - 'A' + 10) : \ 654 ( (((char) (c)) >= 'a' && ((char) (c)) <= 'f') ? \ 655 (int) (((unsigned char) (c)) - 'a' + 10) : \ 656 (int) (-1) ))) 657 658 /** 659 * Caseless compare two characters. 660 * 661 * @param c1 the first char to compare 662 * @param c2 the second char to compare 663 * @return boolean 'true' if chars are caseless equal, false otherwise 664 */ 665 #define charsequalcaseless(c1, c2) \ 666 ( ((c1) == (c2)) || \ 667 (isasciiupper (c1) ? \ 668 (((c1) - 'A' + 'a') == (c2)) : \ 669 (((c1) == ((c2) - 'A' + 'a')) && isasciiupper (c2))) ) 670 671 #endif /* !HAVE_INLINE_FUNCS */ 672 673 674 #ifndef MHD_FAVOR_SMALL_CODE 675 /** 676 * Check two strings for equality, ignoring case of US-ASCII letters. 677 * 678 * @param str1 first string to compare 679 * @param str2 second string to compare 680 * @return non-zero if two strings are equal, zero otherwise. 681 */ 682 int 683 MHD_str_equal_caseless_ (const char *str1, 684 const char *str2) 685 { 686 while (0 != (*str1)) 687 { 688 const char c1 = *str1; 689 const char c2 = *str2; 690 if (charsequalcaseless (c1, c2)) 691 { 692 str1++; 693 str2++; 694 } 695 else 696 return 0; 697 } 698 return 0 == (*str2); 699 } 700 701 702 #endif /* ! MHD_FAVOR_SMALL_CODE */ 703 704 705 /** 706 * Check two string for equality, ignoring case of US-ASCII letters and 707 * checking not more than @a maxlen characters. 708 * Compares up to first terminating null character, but not more than 709 * first @a maxlen characters. 710 * 711 * @param str1 first string to compare 712 * @param str2 second string to compare 713 * @param maxlen maximum number of characters to compare 714 * @return non-zero if two strings are equal, zero otherwise. 715 */ 716 int 717 MHD_str_equal_caseless_n_ (const char *const str1, 718 const char *const str2, 719 size_t maxlen) 720 { 721 size_t i; 722 723 for (i = 0; i < maxlen; ++i) 724 { 725 const char c1 = str1[i]; 726 const char c2 = str2[i]; 727 if (0 == c2) 728 return 0 == c1; 729 if (charsequalcaseless (c1, c2)) 730 continue; 731 else 732 return 0; 733 } 734 return ! 0; 735 } 736 737 738 /** 739 * Check two string for equality, ignoring case of US-ASCII letters and 740 * checking not more than @a len bytes. 741 * Compares not more first than @a len bytes, including binary zero characters. 742 * Comparison stops at first unmatched byte. 743 * @param str1 first string to compare 744 * @param str2 second string to compare 745 * @param len number of characters to compare 746 * @return non-zero if @a len bytes are equal, zero otherwise. 747 */ 748 bool 749 MHD_str_equal_caseless_bin_n_ (const char *const str1, 750 const char *const str2, 751 size_t len) 752 { 753 size_t i; 754 755 for (i = 0; i < len; ++i) 756 { 757 const char c1 = str1[i]; 758 const char c2 = str2[i]; 759 if (charsequalcaseless (c1, c2)) 760 continue; 761 else 762 return 0; 763 } 764 return ! 0; 765 } 766 767 768 /** 769 * Check whether @a str has case-insensitive @a token. 770 * Token could be surrounded by spaces and tabs and delimited by comma. 771 * Match succeed if substring between start, end (of string) or comma 772 * contains only case-insensitive token and optional spaces and tabs. 773 * @warning token must not contain null-characters except optional 774 * terminating null-character. 775 * @param str the string to check 776 * @param token the token to find 777 * @param token_len length of token, not including optional terminating 778 * null-character. 779 * @return non-zero if two strings are equal, zero otherwise. 780 */ 781 bool 782 MHD_str_has_token_caseless_ (const char *str, 783 const char *const token, 784 size_t token_len) 785 { 786 if (0 == token_len) 787 return false; 788 789 while (0 != *str) 790 { 791 size_t i; 792 /* Skip all whitespaces and empty tokens. */ 793 while (' ' == *str || '\t' == *str || ',' == *str) 794 str++; 795 796 /* Check for token match. */ 797 i = 0; 798 while (1) 799 { 800 const char sc = *(str++); 801 const char tc = token[i++]; 802 803 if (0 == sc) 804 return false; 805 if (! charsequalcaseless (sc, tc)) 806 break; 807 if (i >= token_len) 808 { 809 /* Check whether substring match token fully or 810 * has additional unmatched chars at tail. */ 811 while (' ' == *str || '\t' == *str) 812 str++; 813 /* End of (sub)string? */ 814 if ((0 == *str) || (',' == *str) ) 815 return true; 816 /* Unmatched chars at end of substring. */ 817 break; 818 } 819 } 820 /* Find next substring. */ 821 while (0 != *str && ',' != *str) 822 str++; 823 } 824 return false; 825 } 826 827 828 /** 829 * Remove case-insensitive @a token from the @a str and put result 830 * to the output @a buf. 831 * 832 * Tokens in @a str could be surrounded by spaces and tabs and delimited by 833 * comma. The token match succeed if substring between start, end (of string) 834 * or comma contains only case-insensitive token and optional spaces and tabs. 835 * The quoted strings and comments are not supported by this function. 836 * 837 * The output string is normalised: empty tokens and repeated whitespaces 838 * are removed, no whitespaces before commas, exactly one space is used after 839 * each comma. 840 * 841 * @param str the string to process 842 * @param str_len the length of the @a str, not including optional 843 * terminating null-character. 844 * @param token the token to find 845 * @param token_len the length of @a token, not including optional 846 * terminating null-character. 847 * @param[out] buf the output buffer, not null-terminated. 848 * @param[in,out] buf_size pointer to the size variable, at input it 849 * is the size of allocated buffer, at output 850 * it is the size of the resulting string (can 851 * be up to 50% larger than input) or negative value 852 * if there is not enough space for the result 853 * @return 'true' if token has been removed, 854 * 'false' otherwise. 855 */ 856 bool 857 MHD_str_remove_token_caseless_ (const char *str, 858 size_t str_len, 859 const char *const token, 860 const size_t token_len, 861 char *buf, 862 ssize_t *buf_size) 863 { 864 const char *s1; /**< the "input" string / character */ 865 char *s2; /**< the "output" string / character */ 866 size_t t_pos; /**< position of matched character in the token */ 867 bool token_removed; 868 869 mhd_assert (NULL == memchr (token, 0, token_len)); 870 mhd_assert (NULL == memchr (token, ' ', token_len)); 871 mhd_assert (NULL == memchr (token, '\t', token_len)); 872 mhd_assert (NULL == memchr (token, ',', token_len)); 873 mhd_assert (0 <= *buf_size); 874 875 if ((str_len / 2) >= (((size_t) SSIZE_MAX - 1) / 3)) 876 { 877 /* The return value may overflow, refuse */ 878 *buf_size = (ssize_t) -1; 879 return false; 880 } 881 s1 = str; 882 s2 = buf; 883 token_removed = false; 884 885 while ((size_t) (s1 - str) < str_len) 886 { 887 const char *cur_token; /**< the first char of current token */ 888 size_t copy_size; 889 890 /* Skip any initial whitespaces and empty tokens */ 891 while ( ((size_t) (s1 - str) < str_len) && 892 ((' ' == *s1) || ('\t' == *s1) || (',' == *s1)) ) 893 s1++; 894 895 /* 's1' points to the first char of token in the input string or 896 * points just beyond the end of the input string */ 897 898 if ((size_t) (s1 - str) >= str_len) 899 break; /* Nothing to copy, end of the input string */ 900 901 /* 's1' points to the first char of token in the input string */ 902 903 cur_token = s1; /* the first char of input token */ 904 905 /* Check the token with case-insensetive match */ 906 t_pos = 0; 907 while ( ((size_t) (s1 - str) < str_len) && (token_len > t_pos) && 908 (charsequalcaseless (*s1, token[t_pos])) ) 909 { 910 s1++; 911 t_pos++; 912 } 913 /* s1 may point just beyond the end of the input string */ 914 if ( (token_len == t_pos) && (0 != token_len) ) 915 { 916 /* 'token' matched, check that current input token does not have 917 * any suffixes */ 918 while ( ((size_t) (s1 - str) < str_len) && 919 ((' ' == *s1) || ('\t' == *s1)) ) 920 s1++; 921 /* 's1' points to the first non-whitespace char after the token matched 922 * requested token or points just beyond the end of the input string after 923 * the requested token */ 924 if (((size_t) (s1 - str) == str_len) || (',' == *s1)) 925 {/* full token match, do not copy current token to the output */ 926 token_removed = true; 927 continue; 928 } 929 } 930 931 /* 's1' points to first non-whitespace char, to some char after 932 * first non-whitespace char in the token in the input string, to 933 * the ',', or just beyond the end of the input string */ 934 /* The current token in the input string does not match the token 935 * to exclude, it must be copied to the output string */ 936 /* the current token size excluding leading whitespaces and current char */ 937 copy_size = (size_t) (s1 - cur_token); 938 if (buf == s2) 939 { /* The first token to copy to the output */ 940 if ((size_t) *buf_size < copy_size) 941 { /* Not enough space in the output buffer */ 942 *buf_size = (ssize_t) -1; 943 return false; 944 } 945 } 946 else 947 { /* Some token was already copied to the output buffer */ 948 mhd_assert (s2 > buf); 949 if ((size_t) *buf_size < ((size_t) (s2 - buf)) + copy_size + 2) 950 { /* Not enough space in the output buffer */ 951 *buf_size = (ssize_t) -1; 952 return false; 953 } 954 *(s2++) = ','; 955 *(s2++) = ' '; 956 } 957 /* Copy non-matched token to the output */ 958 if (0 != copy_size) 959 { 960 memcpy (s2, cur_token, copy_size); 961 s2 += copy_size; 962 } 963 964 while ( ((size_t) (s1 - str) < str_len) && (',' != *s1)) 965 { 966 /* 's1' points to first non-whitespace char, to some char after 967 * first non-whitespace char in the token in the input string */ 968 /* Copy all non-whitespace chars from the current token in 969 * the input string */ 970 while ( ((size_t) (s1 - str) < str_len) && 971 (',' != *s1) && (' ' != *s1) && ('\t' != *s1) ) 972 { 973 mhd_assert (s2 >= buf); 974 if ((size_t) *buf_size <= (size_t) (s2 - buf)) /* '<= s2' equals '< s2 + 1' */ 975 { /* Not enough space in the output buffer */ 976 *buf_size = (ssize_t) -1; 977 return false; 978 } 979 *(s2++) = *(s1++); 980 } 981 /* 's1' points to some whitespace char in the token in the input 982 * string, to the ',', or just beyond the end of the input string */ 983 /* Skip all whitespaces */ 984 while ( ((size_t) (s1 - str) < str_len) && 985 ((' ' == *s1) || ('\t' == *s1)) ) 986 s1++; 987 988 /* 's1' points to the first non-whitespace char in the input string 989 * after whitespace chars, to the ',', or just beyond the end of 990 * the input string */ 991 if (((size_t) (s1 - str) < str_len) && (',' != *s1)) 992 { /* Not the end of the current token */ 993 mhd_assert (s2 >= buf); 994 if ((size_t) *buf_size <= (size_t) (s2 - buf)) /* '<= s2' equals '< s2 + 1' */ 995 { /* Not enough space in the output buffer */ 996 *buf_size = (ssize_t) -1; 997 return false; 998 } 999 *(s2++) = ' '; 1000 } 1001 } 1002 } 1003 mhd_assert (((ssize_t) (s2 - buf)) <= *buf_size); 1004 *buf_size = (ssize_t) (s2 - buf); 1005 return token_removed; 1006 } 1007 1008 1009 /** 1010 * Perform in-place case-insensitive removal of @a tokens from the @a str. 1011 * 1012 * Token could be surrounded by spaces and tabs and delimited by comma. 1013 * The token match succeed if substring between start, end (of the string), or 1014 * comma contains only case-insensitive token and optional spaces and tabs. 1015 * The quoted strings and comments are not supported by this function. 1016 * 1017 * The input string must be normalised: empty tokens and repeated whitespaces 1018 * are removed, no whitespaces before commas, exactly one space is used after 1019 * each comma. The string is updated in-place. 1020 * 1021 * Behavior is undefined is the input string in not normalised. 1022 * 1023 * @param[in,out] str the string to update 1024 * @param[in,out] str_len the length of the @a str, not including optional 1025 * terminating null-character, not null-terminated 1026 * @param tokens the token to find 1027 * @param tokens_len the length of @a tokens, not including optional 1028 * terminating null-character. 1029 * @return 'true' if any token has been removed, 1030 * 'false' otherwise. 1031 */ 1032 bool 1033 MHD_str_remove_tokens_caseless_ (char *str, 1034 size_t *str_len, 1035 const char *const tokens, 1036 const size_t tokens_len) 1037 { 1038 const char *const t = tokens; /**< a short alias for @a tokens */ 1039 size_t pt; /**< position in @a tokens */ 1040 bool token_removed; 1041 1042 mhd_assert (NULL == memchr (tokens, 0, tokens_len)); 1043 1044 token_removed = false; 1045 pt = 0; 1046 1047 while (pt < tokens_len && *str_len != 0) 1048 { 1049 const char *tkn; /**< the current token */ 1050 size_t tkn_len; 1051 1052 /* Skip any initial whitespaces and empty tokens in 'tokens' */ 1053 while ( (pt < tokens_len) && 1054 ((' ' == t[pt]) || ('\t' == t[pt]) || (',' == t[pt])) ) 1055 pt++; 1056 1057 if (pt >= tokens_len) 1058 break; /* No more tokens, nothing to remove */ 1059 1060 /* Found non-whitespace char which is not a comma */ 1061 tkn = t + pt; 1062 do 1063 { 1064 do 1065 { 1066 pt++; 1067 } while (pt < tokens_len && 1068 (' ' != t[pt] && '\t' != t[pt] && ',' != t[pt])); 1069 /* Found end of the token string, space, tab, or comma */ 1070 tkn_len = pt - (size_t) (tkn - t); 1071 1072 /* Skip all spaces and tabs */ 1073 while (pt < tokens_len && (' ' == t[pt] || '\t' == t[pt])) 1074 pt++; 1075 /* Found end of the token string or non-whitespace char */ 1076 } while (pt < tokens_len && ',' != t[pt]); 1077 1078 /* 'tkn' is the input token with 'tkn_len' chars */ 1079 mhd_assert (0 != tkn_len); 1080 1081 if (*str_len == tkn_len) 1082 { 1083 if (MHD_str_equal_caseless_bin_n_ (str, tkn, tkn_len)) 1084 { 1085 *str_len = 0; 1086 token_removed = true; 1087 } 1088 continue; 1089 } 1090 /* 'tkn' cannot match part of 'str' if length of 'tkn' is larger 1091 * than length of 'str'. 1092 * It's know that 'tkn' is not equal to the 'str' (was checked previously). 1093 * As 'str' is normalized when 'tkn' is not equal to the 'str' 1094 * it is required that 'str' to be at least 3 chars larger then 'tkn' 1095 * (the comma, the space and at least one additional character for the next 1096 * token) to remove 'tkn' from the 'str'. */ 1097 if (*str_len > tkn_len + 2) 1098 { /* Remove 'tkn' from the input string */ 1099 size_t pr; /**< the 'read' position in the @a str */ 1100 size_t pw; /**< the 'write' position in the @a str */ 1101 1102 pr = 0; 1103 pw = 0; 1104 1105 do 1106 { 1107 mhd_assert (pr >= pw); 1108 mhd_assert ((*str_len) >= (pr + tkn_len)); 1109 if ( ( ((*str_len) == (pr + tkn_len)) || (',' == str[pr + tkn_len]) ) && 1110 MHD_str_equal_caseless_bin_n_ (str + pr, tkn, tkn_len) ) 1111 { 1112 /* current token in the input string matches the 'tkn', skip it */ 1113 mhd_assert ((*str_len == pr + tkn_len) || \ 1114 (' ' == str[pr + tkn_len + 1])); /* 'str' must be normalized */ 1115 token_removed = true; 1116 /* Advance to the next token in the input string or beyond 1117 * the end of the input string. */ 1118 pr += tkn_len + 2; 1119 } 1120 else 1121 { 1122 /* current token in the input string does not match the 'tkn', 1123 * copy to the output */ 1124 if (0 != pw) 1125 { /* not the first output token, add ", " to separate */ 1126 if (pr != pw + 2) 1127 { 1128 str[pw++] = ','; 1129 str[pw++] = ' '; 1130 } 1131 else 1132 pw += 2; /* 'str' is not yet modified in this round */ 1133 } 1134 do 1135 { 1136 if (pr != pw) 1137 str[pw] = str[pr]; 1138 pr++; 1139 pw++; 1140 } while (pr < *str_len && ',' != str[pr]); 1141 /* Advance to the next token in the input string or beyond 1142 * the end of the input string. */ 1143 pr += 2; 1144 } 1145 /* 'pr' should point to the next token in the input string or beyond 1146 * the end of the input string */ 1147 if ((*str_len) < (pr + tkn_len)) 1148 { /* The rest of the 'str + pr' is too small to match 'tkn' */ 1149 if ((*str_len) > pr) 1150 { /* Copy the rest of the string */ 1151 size_t copy_size; 1152 copy_size = *str_len - pr; 1153 if (0 != pw) 1154 { /* not the first output token, add ", " to separate */ 1155 if (pr != pw + 2) 1156 { 1157 str[pw++] = ','; 1158 str[pw++] = ' '; 1159 } 1160 else 1161 pw += 2; /* 'str' is not yet modified in this round */ 1162 } 1163 if (pr != pw) 1164 memmove (str + pw, str + pr, copy_size); 1165 pw += copy_size; 1166 } 1167 *str_len = pw; 1168 break; 1169 } 1170 mhd_assert ((' ' != str[0]) && ('\t' != str[0])); 1171 mhd_assert ((0 == pr) || (3 <= pr)); 1172 mhd_assert ((0 == pr) || (' ' == str[pr - 1])); 1173 mhd_assert ((0 == pr) || (',' == str[pr - 2])); 1174 } while (1); 1175 } 1176 } 1177 1178 return token_removed; 1179 } 1180 1181 1182 #ifndef MHD_FAVOR_SMALL_CODE 1183 /* Use individual function for each case */ 1184 1185 /** 1186 * Convert decimal US-ASCII digits in string to number in uint64_t. 1187 * Conversion stopped at first non-digit character. 1188 * 1189 * @param str string to convert 1190 * @param[out] out_val pointer to uint64_t to store result of conversion 1191 * @return non-zero number of characters processed on succeed, 1192 * zero if no digit is found, resulting value is larger 1193 * then possible to store in uint64_t or @a out_val is NULL 1194 */ 1195 size_t 1196 MHD_str_to_uint64_ (const char *str, 1197 uint64_t *out_val) 1198 { 1199 const char *const start = str; 1200 uint64_t res; 1201 1202 if (! str || ! out_val || ! isasciidigit (str[0])) 1203 return 0; 1204 1205 res = 0; 1206 do 1207 { 1208 const int digit = (unsigned char) (*str) - '0'; 1209 if ( (res > (UINT64_MAX / 10)) || 1210 ( (res == (UINT64_MAX / 10)) && 1211 ((uint64_t) digit > (UINT64_MAX % 10)) ) ) 1212 return 0; 1213 1214 res *= 10; 1215 res += (unsigned int) digit; 1216 str++; 1217 } while (isasciidigit (*str)); 1218 1219 *out_val = res; 1220 return (size_t) (str - start); 1221 } 1222 1223 1224 /** 1225 * Convert not more then @a maxlen decimal US-ASCII digits in string to 1226 * number in uint64_t. 1227 * Conversion stopped at first non-digit character or after @a maxlen 1228 * digits. 1229 * 1230 * @param str string to convert 1231 * @param maxlen maximum number of characters to process 1232 * @param[out] out_val pointer to uint64_t to store result of conversion 1233 * @return non-zero number of characters processed on succeed, 1234 * zero if no digit is found, resulting value is larger 1235 * then possible to store in uint64_t or @a out_val is NULL 1236 */ 1237 size_t 1238 MHD_str_to_uint64_n_ (const char *str, 1239 size_t maxlen, 1240 uint64_t *out_val) 1241 { 1242 uint64_t res; 1243 size_t i; 1244 1245 if (! str || ! maxlen || ! out_val || ! isasciidigit (str[0])) 1246 return 0; 1247 1248 res = 0; 1249 i = 0; 1250 do 1251 { 1252 const int digit = (unsigned char) str[i] - '0'; 1253 1254 if ( (res > (UINT64_MAX / 10)) || 1255 ( (res == (UINT64_MAX / 10)) && 1256 ((uint64_t) digit > (UINT64_MAX % 10)) ) ) 1257 return 0; 1258 1259 res *= 10; 1260 res += (unsigned int) digit; 1261 i++; 1262 } while ( (i < maxlen) && 1263 isasciidigit (str[i]) ); 1264 1265 *out_val = res; 1266 return i; 1267 } 1268 1269 1270 /** 1271 * Convert hexadecimal US-ASCII digits in string to number in uint32_t. 1272 * Conversion stopped at first non-digit character. 1273 * 1274 * @param str string to convert 1275 * @param[out] out_val pointer to uint32_t to store result of conversion 1276 * @return non-zero number of characters processed on succeed, 1277 * zero if no digit is found, resulting value is larger 1278 * then possible to store in uint32_t or @a out_val is NULL 1279 */ 1280 size_t 1281 MHD_strx_to_uint32_ (const char *str, 1282 uint32_t *out_val) 1283 { 1284 const char *const start = str; 1285 uint32_t res; 1286 int digit; 1287 1288 if (! str || ! out_val) 1289 return 0; 1290 1291 res = 0; 1292 digit = toxdigitvalue (*str); 1293 while (digit >= 0) 1294 { 1295 if ( (res < (UINT32_MAX / 16)) || 1296 ((res == (UINT32_MAX / 16)) && 1297 ( (uint32_t) digit <= (UINT32_MAX % 16)) ) ) 1298 { 1299 res *= 16; 1300 res += (unsigned int) digit; 1301 } 1302 else 1303 return 0; 1304 str++; 1305 digit = toxdigitvalue (*str); 1306 } 1307 1308 if (str - start > 0) 1309 *out_val = res; 1310 return (size_t) (str - start); 1311 } 1312 1313 1314 /** 1315 * Convert not more then @a maxlen hexadecimal US-ASCII digits in string 1316 * to number in uint32_t. 1317 * Conversion stopped at first non-digit character or after @a maxlen 1318 * digits. 1319 * 1320 * @param str string to convert 1321 * @param maxlen maximum number of characters to process 1322 * @param[out] out_val pointer to uint32_t to store result of conversion 1323 * @return non-zero number of characters processed on succeed, 1324 * zero if no digit is found, resulting value is larger 1325 * then possible to store in uint32_t or @a out_val is NULL 1326 */ 1327 size_t 1328 MHD_strx_to_uint32_n_ (const char *str, 1329 size_t maxlen, 1330 uint32_t *out_val) 1331 { 1332 size_t i; 1333 uint32_t res; 1334 int digit; 1335 if (! str || ! out_val) 1336 return 0; 1337 1338 res = 0; 1339 i = 0; 1340 while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0) 1341 { 1342 if ( (res > (UINT32_MAX / 16)) || 1343 ((res == (UINT32_MAX / 16)) && 1344 ( (uint32_t) digit > (UINT32_MAX % 16)) ) ) 1345 return 0; 1346 1347 res *= 16; 1348 res += (unsigned int) digit; 1349 i++; 1350 } 1351 1352 if (i) 1353 *out_val = res; 1354 return i; 1355 } 1356 1357 1358 /** 1359 * Convert hexadecimal US-ASCII digits in string to number in uint64_t. 1360 * Conversion stopped at first non-digit character. 1361 * 1362 * @param str string to convert 1363 * @param[out] out_val pointer to uint64_t to store result of conversion 1364 * @return non-zero number of characters processed on succeed, 1365 * zero if no digit is found, resulting value is larger 1366 * then possible to store in uint64_t or @a out_val is NULL 1367 */ 1368 size_t 1369 MHD_strx_to_uint64_ (const char *str, 1370 uint64_t *out_val) 1371 { 1372 const char *const start = str; 1373 uint64_t res; 1374 int digit; 1375 if (! str || ! out_val) 1376 return 0; 1377 1378 res = 0; 1379 digit = toxdigitvalue (*str); 1380 while (digit >= 0) 1381 { 1382 if ( (res < (UINT64_MAX / 16)) || 1383 ((res == (UINT64_MAX / 16)) && 1384 ( (uint64_t) digit <= (UINT64_MAX % 16)) ) ) 1385 { 1386 res *= 16; 1387 res += (unsigned int) digit; 1388 } 1389 else 1390 return 0; 1391 str++; 1392 digit = toxdigitvalue (*str); 1393 } 1394 1395 if (str - start > 0) 1396 *out_val = res; 1397 return (size_t) (str - start); 1398 } 1399 1400 1401 /** 1402 * Convert not more then @a maxlen hexadecimal US-ASCII digits in string 1403 * to number in uint64_t. 1404 * Conversion stopped at first non-digit character or after @a maxlen 1405 * digits. 1406 * 1407 * @param str string to convert 1408 * @param maxlen maximum number of characters to process 1409 * @param[out] out_val pointer to uint64_t to store result of conversion 1410 * @return non-zero number of characters processed on succeed, 1411 * zero if no digit is found, resulting value is larger 1412 * then possible to store in uint64_t or @a out_val is NULL 1413 */ 1414 size_t 1415 MHD_strx_to_uint64_n_ (const char *str, 1416 size_t maxlen, 1417 uint64_t *out_val) 1418 { 1419 size_t i; 1420 uint64_t res; 1421 int digit; 1422 if (! str || ! out_val) 1423 return 0; 1424 1425 res = 0; 1426 i = 0; 1427 while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0) 1428 { 1429 if ( (res > (UINT64_MAX / 16)) || 1430 ((res == (UINT64_MAX / 16)) && 1431 ( (uint64_t) digit > (UINT64_MAX % 16)) ) ) 1432 return 0; 1433 1434 res *= 16; 1435 res += (unsigned int) digit; 1436 i++; 1437 } 1438 1439 if (i) 1440 *out_val = res; 1441 return i; 1442 } 1443 1444 1445 #else /* MHD_FAVOR_SMALL_CODE */ 1446 1447 /** 1448 * Generic function for converting not more then @a maxlen 1449 * hexadecimal or decimal US-ASCII digits in string to number. 1450 * Conversion stopped at first non-digit character or after @a maxlen 1451 * digits. 1452 * To be used only within macro. 1453 * 1454 * @param str the string to convert 1455 * @param maxlen the maximum number of characters to process 1456 * @param out_val the pointer to variable to store result of conversion 1457 * @param val_size the size of variable pointed by @a out_val, in bytes, 4 or 8 1458 * @param max_val the maximum decoded number 1459 * @param base the numeric base, 10 or 16 1460 * @return non-zero number of characters processed on succeed, 1461 * zero if no digit is found, resulting value is larger 1462 * then @a max_val, @a val_size is not 4/8 or @a out_val is NULL 1463 */ 1464 size_t 1465 MHD_str_to_uvalue_n_ (const char *str, 1466 size_t maxlen, 1467 void *out_val, 1468 size_t val_size, 1469 uint64_t max_val, 1470 unsigned int base) 1471 { 1472 size_t i; 1473 uint64_t res; 1474 const uint64_t max_v_div_b = max_val / base; 1475 const uint64_t max_v_mod_b = max_val % base; 1476 1477 if (! str || ! out_val || 1478 ((base != 16) && (base != 10)) ) 1479 return 0; 1480 1481 res = 0; 1482 i = 0; 1483 while (maxlen > i) 1484 { 1485 const int digit = (base == 16) ? 1486 toxdigitvalue (str[i]) : todigitvalue (str[i]); 1487 1488 if (0 > digit) 1489 break; 1490 if ( ((max_v_div_b) < res) || 1491 (( (max_v_div_b) == res) && ( (max_v_mod_b) < (uint64_t) digit) ) ) 1492 return 0; 1493 1494 res *= base; 1495 res += (unsigned int) digit; 1496 i++; 1497 } 1498 1499 if (i) 1500 { 1501 if (8 == val_size) 1502 *(uint64_t *) out_val = res; 1503 else if (4 == val_size) 1504 *(uint32_t *) out_val = (uint32_t) res; 1505 else 1506 return 0; 1507 } 1508 return i; 1509 } 1510 1511 1512 #endif /* MHD_FAVOR_SMALL_CODE */ 1513 1514 1515 size_t 1516 MHD_uint32_to_strx (uint32_t val, 1517 char *buf, 1518 size_t buf_size) 1519 { 1520 size_t o_pos = 0; /**< position of the output character */ 1521 int digit_pos = 8; /** zero-based, digit position in @a 'val' */ 1522 int digit; 1523 1524 /* Skip leading zeros */ 1525 do 1526 { 1527 digit_pos--; 1528 digit = (int) (val >> 28); 1529 val <<= 4; 1530 } while ((0 == digit) && (0 != digit_pos)); 1531 1532 while (o_pos < buf_size) 1533 { 1534 buf[o_pos++] = 1535 (char) ((digit <= 9) ? 1536 ('0' + (char) digit) : 1537 ('A' + (char) digit - 10)); 1538 if (0 == digit_pos) 1539 return o_pos; 1540 digit_pos--; 1541 digit = (int) (val >> 28); 1542 val <<= 4; 1543 } 1544 return 0; /* The buffer is too small */ 1545 } 1546 1547 1548 #ifndef MHD_FAVOR_SMALL_CODE 1549 size_t 1550 MHD_uint16_to_str (uint16_t val, 1551 char *buf, 1552 size_t buf_size) 1553 { 1554 char *chr; /**< pointer to the current printed digit */ 1555 /* The biggest printable number is 65535 */ 1556 uint16_t divisor = UINT16_C (10000); 1557 int digit; 1558 1559 chr = buf; 1560 digit = (int) (val / divisor); 1561 mhd_assert (digit < 10); 1562 1563 /* Do not print leading zeros */ 1564 while ((0 == digit) && (1 < divisor)) 1565 { 1566 divisor /= 10; 1567 digit = (int) (val / divisor); 1568 mhd_assert (digit < 10); 1569 } 1570 1571 while (0 != buf_size) 1572 { 1573 *chr = (char) ((char) digit + '0'); 1574 chr++; 1575 buf_size--; 1576 if (1 == divisor) 1577 return (size_t) (chr - buf); 1578 val = (uint16_t) (val % divisor); 1579 divisor /= 10; 1580 digit = (int) (val / divisor); 1581 mhd_assert (digit < 10); 1582 } 1583 return 0; /* The buffer is too small */ 1584 } 1585 1586 1587 #endif /* !MHD_FAVOR_SMALL_CODE */ 1588 1589 1590 size_t 1591 MHD_uint64_to_str (uint64_t val, 1592 char *buf, 1593 size_t buf_size) 1594 { 1595 char *chr; /**< pointer to the current printed digit */ 1596 /* The biggest printable number is 18446744073709551615 */ 1597 uint64_t divisor = UINT64_C (10000000000000000000); 1598 int digit; 1599 1600 chr = buf; 1601 digit = (int) (val / divisor); 1602 mhd_assert (digit < 10); 1603 1604 /* Do not print leading zeros */ 1605 while ((0 == digit) && (1 < divisor)) 1606 { 1607 divisor /= 10; 1608 digit = (int) (val / divisor); 1609 mhd_assert (digit < 10); 1610 } 1611 1612 while (0 != buf_size) 1613 { 1614 *chr = (char) ((char) digit + '0'); 1615 chr++; 1616 buf_size--; 1617 if (1 == divisor) 1618 return (size_t) (chr - buf); 1619 val %= divisor; 1620 divisor /= 10; 1621 digit = (int) (val / divisor); 1622 mhd_assert (digit < 10); 1623 } 1624 return 0; /* The buffer is too small */ 1625 } 1626 1627 1628 size_t 1629 MHD_uint8_to_str_pad (uint8_t val, 1630 uint8_t min_digits, 1631 char *buf, 1632 size_t buf_size) 1633 { 1634 size_t pos; /**< the position of the current printed digit */ 1635 int digit; 1636 mhd_assert (3 >= min_digits); 1637 if (0 == buf_size) 1638 return 0; 1639 1640 pos = 0; 1641 digit = val / 100; 1642 if (0 == digit) 1643 { 1644 if (3 <= min_digits) 1645 buf[pos++] = '0'; 1646 } 1647 else 1648 { 1649 buf[pos++] = (char) ('0' + (char) digit); 1650 val %= 100; 1651 min_digits = 2; 1652 } 1653 1654 if (buf_size <= pos) 1655 return 0; 1656 digit = val / 10; 1657 if (0 == digit) 1658 { 1659 if (2 <= min_digits) 1660 buf[pos++] = '0'; 1661 } 1662 else 1663 { 1664 buf[pos++] = (char) ('0' + (char) digit); 1665 val %= 10; 1666 } 1667 1668 if (buf_size <= pos) 1669 return 0; 1670 buf[pos++] = (char) ('0' + (char) val); 1671 return pos; 1672 } 1673 1674 1675 size_t 1676 MHD_bin_to_hex (const void *bin, 1677 size_t size, 1678 char *hex) 1679 { 1680 size_t i; 1681 1682 for (i = 0; i < size; ++i) 1683 { 1684 uint8_t j; 1685 const uint8_t b = ((const uint8_t *) bin)[i]; 1686 j = b >> 4; 1687 hex[i * 2] = (char) ((j < 10) ? (j + '0') : (j - 10 + 'a')); 1688 j = b & 0x0f; 1689 hex[i * 2 + 1] = (char) ((j < 10) ? (j + '0') : (j - 10 + 'a')); 1690 } 1691 return i * 2; 1692 } 1693 1694 1695 size_t 1696 MHD_bin_to_hex_z (const void *bin, 1697 size_t size, 1698 char *hex) 1699 { 1700 size_t res; 1701 1702 res = MHD_bin_to_hex (bin, size, hex); 1703 hex[res] = 0; 1704 1705 return res; 1706 } 1707 1708 1709 size_t 1710 MHD_hex_to_bin (const char *hex, 1711 size_t len, 1712 void *bin) 1713 { 1714 uint8_t *const out = (uint8_t *) bin; 1715 size_t r; 1716 size_t w; 1717 1718 if (0 == len) 1719 return 0; 1720 r = 0; 1721 w = 0; 1722 if (0 != len % 2) 1723 { 1724 /* Assume the first byte is encoded with single digit */ 1725 const char c2 = hex[r++]; 1726 const int l = toxdigitvalue (c2); 1727 if (0 > l) 1728 return 0; 1729 out[w++] = (uint8_t) ((unsigned int) l); 1730 } 1731 while (r < len) 1732 { 1733 const char c1 = hex[r++]; 1734 const char c2 = hex[r++]; 1735 const int h = toxdigitvalue (c1); 1736 const int l = toxdigitvalue (c2); 1737 if ((0 > h) || (0 > l)) 1738 return 0; 1739 out[w++] = (uint8_t) ( ((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 1740 | ((uint8_t) ((unsigned int) l)) ); 1741 } 1742 mhd_assert (len == r); 1743 mhd_assert ((len + 1) / 2 == w); 1744 return w; 1745 } 1746 1747 1748 size_t 1749 MHD_str_pct_decode_strict_n_ (const char *pct_encoded, 1750 size_t pct_encoded_len, 1751 char *decoded, 1752 size_t buf_size) 1753 { 1754 #ifdef MHD_FAVOR_SMALL_CODE 1755 bool broken; 1756 size_t res; 1757 1758 res = MHD_str_pct_decode_lenient_n_ (pct_encoded, pct_encoded_len, decoded, 1759 buf_size, &broken); 1760 if (broken) 1761 return 0; 1762 return res; 1763 #else /* ! MHD_FAVOR_SMALL_CODE */ 1764 size_t r; 1765 size_t w; 1766 r = 0; 1767 w = 0; 1768 1769 if (buf_size >= pct_encoded_len) 1770 { 1771 while (r < pct_encoded_len) 1772 { 1773 const char chr = pct_encoded[r]; 1774 if ('%' == chr) 1775 { 1776 if (3 > pct_encoded_len - r) 1777 return 0; 1778 { 1779 const char c1 = pct_encoded[++r]; 1780 const char c2 = pct_encoded[++r]; 1781 const int h = toxdigitvalue (c1); 1782 const int l = toxdigitvalue (c2); 1783 unsigned char out; 1784 if ((0 > h) || (0 > l)) 1785 return 0; 1786 out = 1787 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 1788 | ((uint8_t) ((unsigned int) l))); 1789 decoded[w] = (char) out; 1790 } 1791 } 1792 else 1793 decoded[w] = chr; 1794 ++r; 1795 ++w; 1796 } 1797 return w; 1798 } 1799 1800 while (r < pct_encoded_len) 1801 { 1802 const char chr = pct_encoded[r]; 1803 if (w >= buf_size) 1804 return 0; 1805 if ('%' == chr) 1806 { 1807 if (3 > pct_encoded_len - r) 1808 return 0; 1809 { 1810 const char c1 = pct_encoded[++r]; 1811 const char c2 = pct_encoded[++r]; 1812 const int h = toxdigitvalue (c1); 1813 const int l = toxdigitvalue (c2); 1814 unsigned char out; 1815 if ((0 > h) || (0 > l)) 1816 return 0; 1817 out = 1818 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 1819 | ((uint8_t) ((unsigned int) l))); 1820 decoded[w] = (char) out; 1821 } 1822 } 1823 else 1824 decoded[w] = chr; 1825 ++r; 1826 ++w; 1827 } 1828 return w; 1829 #endif /* ! MHD_FAVOR_SMALL_CODE */ 1830 } 1831 1832 1833 size_t 1834 MHD_str_pct_decode_lenient_n_ (const char *pct_encoded, 1835 size_t pct_encoded_len, 1836 char *decoded, 1837 size_t buf_size, 1838 bool *broken_encoding) 1839 { 1840 size_t r; 1841 size_t w; 1842 r = 0; 1843 w = 0; 1844 if (NULL != broken_encoding) 1845 *broken_encoding = false; 1846 #ifndef MHD_FAVOR_SMALL_CODE 1847 if (buf_size >= pct_encoded_len) 1848 { 1849 while (r < pct_encoded_len) 1850 { 1851 const char chr = pct_encoded[r]; 1852 if ('%' == chr) 1853 { 1854 if (3 > pct_encoded_len - r) 1855 { 1856 if (NULL != broken_encoding) 1857 *broken_encoding = true; 1858 decoded[w] = chr; /* Copy "as is" */ 1859 } 1860 else 1861 { 1862 const char c1 = pct_encoded[++r]; 1863 const char c2 = pct_encoded[++r]; 1864 const int h = toxdigitvalue (c1); 1865 const int l = toxdigitvalue (c2); 1866 unsigned char out; 1867 if ((0 > h) || (0 > l)) 1868 { 1869 r -= 2; 1870 if (NULL != broken_encoding) 1871 *broken_encoding = true; 1872 decoded[w] = chr; /* Copy "as is" */ 1873 } 1874 else 1875 { 1876 out = 1877 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 1878 | ((uint8_t) ((unsigned int) l))); 1879 decoded[w] = (char) out; 1880 } 1881 } 1882 } 1883 else 1884 decoded[w] = chr; 1885 ++r; 1886 ++w; 1887 } 1888 return w; 1889 } 1890 #endif /* ! MHD_FAVOR_SMALL_CODE */ 1891 while (r < pct_encoded_len) 1892 { 1893 const char chr = pct_encoded[r]; 1894 if (w >= buf_size) 1895 return 0; 1896 if ('%' == chr) 1897 { 1898 if (3 > pct_encoded_len - r) 1899 { 1900 if (NULL != broken_encoding) 1901 *broken_encoding = true; 1902 decoded[w] = chr; /* Copy "as is" */ 1903 } 1904 else 1905 { 1906 const char c1 = pct_encoded[++r]; 1907 const char c2 = pct_encoded[++r]; 1908 const int h = toxdigitvalue (c1); 1909 const int l = toxdigitvalue (c2); 1910 if ((0 > h) || (0 > l)) 1911 { 1912 r -= 2; 1913 if (NULL != broken_encoding) 1914 *broken_encoding = true; 1915 decoded[w] = chr; /* Copy "as is" */ 1916 } 1917 else 1918 { 1919 unsigned char out; 1920 out = 1921 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 1922 | ((uint8_t) ((unsigned int) l))); 1923 decoded[w] = (char) out; 1924 } 1925 } 1926 } 1927 else 1928 decoded[w] = chr; 1929 ++r; 1930 ++w; 1931 } 1932 return w; 1933 } 1934 1935 1936 size_t 1937 MHD_str_pct_decode_in_place_strict_ (char *str) 1938 { 1939 #ifdef MHD_FAVOR_SMALL_CODE 1940 size_t res; 1941 bool broken; 1942 1943 res = MHD_str_pct_decode_in_place_lenient_ (str, &broken); 1944 if (broken) 1945 { 1946 res = 0; 1947 str[0] = 0; 1948 } 1949 return res; 1950 #else /* ! MHD_FAVOR_SMALL_CODE */ 1951 size_t r; 1952 size_t w; 1953 r = 0; 1954 w = 0; 1955 1956 while (0 != str[r]) 1957 { 1958 const char chr = str[r++]; 1959 if ('%' == chr) 1960 { 1961 const char d1 = str[r++]; 1962 if (0 == d1) 1963 return 0; 1964 else 1965 { 1966 const char d2 = str[r++]; 1967 if (0 == d2) 1968 return 0; 1969 else 1970 { 1971 const int h = toxdigitvalue (d1); 1972 const int l = toxdigitvalue (d2); 1973 unsigned char out; 1974 if ((0 > h) || (0 > l)) 1975 return 0; 1976 out = 1977 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 1978 | ((uint8_t) ((unsigned int) l))); 1979 str[w++] = (char) out; 1980 } 1981 } 1982 } 1983 else 1984 str[w++] = chr; 1985 } 1986 str[w] = 0; 1987 return w; 1988 #endif /* ! MHD_FAVOR_SMALL_CODE */ 1989 } 1990 1991 1992 size_t 1993 MHD_str_pct_decode_in_place_lenient_ (char *str, 1994 bool *broken_encoding) 1995 { 1996 #ifdef MHD_FAVOR_SMALL_CODE 1997 size_t len; 1998 size_t res; 1999 2000 len = strlen (str); 2001 res = MHD_str_pct_decode_lenient_n_ (str, len, str, len, broken_encoding); 2002 str[res] = 0; 2003 2004 return res; 2005 #else /* ! MHD_FAVOR_SMALL_CODE */ 2006 size_t r; 2007 size_t w; 2008 if (NULL != broken_encoding) 2009 *broken_encoding = false; 2010 r = 0; 2011 w = 0; 2012 while (0 != str[r]) 2013 { 2014 const char chr = str[r++]; 2015 if ('%' == chr) 2016 { 2017 const char d1 = str[r++]; 2018 if (0 == d1) 2019 { 2020 if (NULL != broken_encoding) 2021 *broken_encoding = true; 2022 str[w++] = chr; /* Copy "as is" */ 2023 str[w] = 0; 2024 return w; 2025 } 2026 else 2027 { 2028 const char d2 = str[r++]; 2029 if (0 == d2) 2030 { 2031 if (NULL != broken_encoding) 2032 *broken_encoding = true; 2033 str[w++] = chr; /* Copy "as is" */ 2034 str[w++] = d1; /* Copy "as is" */ 2035 str[w] = 0; 2036 return w; 2037 } 2038 else 2039 { 2040 const int h = toxdigitvalue (d1); 2041 const int l = toxdigitvalue (d2); 2042 unsigned char out; 2043 if ((0 > h) || (0 > l)) 2044 { 2045 if (NULL != broken_encoding) 2046 *broken_encoding = true; 2047 str[w++] = chr; /* Copy "as is" */ 2048 str[w++] = d1; 2049 str[w++] = d2; 2050 continue; 2051 } 2052 out = 2053 (unsigned char) (((uint8_t) (((uint8_t) ((unsigned int) h)) << 4)) 2054 | ((uint8_t) ((unsigned int) l))); 2055 str[w++] = (char) out; 2056 continue; 2057 } 2058 } 2059 } 2060 str[w++] = chr; 2061 } 2062 str[w] = 0; 2063 return w; 2064 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2065 } 2066 2067 2068 #ifdef DAUTH_SUPPORT 2069 bool 2070 MHD_str_equal_quoted_bin_n (const char *quoted, 2071 size_t quoted_len, 2072 const char *unquoted, 2073 size_t unquoted_len) 2074 { 2075 size_t i; 2076 size_t j; 2077 if (unquoted_len < quoted_len / 2) 2078 return false; 2079 2080 j = 0; 2081 for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j) 2082 { 2083 if ('\\' == quoted[i]) 2084 { 2085 i++; /* Advance to the next character */ 2086 if (quoted_len == i) 2087 return false; /* No character after escaping backslash */ 2088 } 2089 if (quoted[i] != unquoted[j]) 2090 return false; /* Different characters */ 2091 } 2092 if ((quoted_len != i) || (unquoted_len != j)) 2093 return false; /* The strings have different length */ 2094 2095 return true; 2096 } 2097 2098 2099 bool 2100 MHD_str_equal_caseless_quoted_bin_n (const char *quoted, 2101 size_t quoted_len, 2102 const char *unquoted, 2103 size_t unquoted_len) 2104 { 2105 size_t i; 2106 size_t j; 2107 if (unquoted_len < quoted_len / 2) 2108 return false; 2109 2110 j = 0; 2111 for (i = 0; quoted_len > i && unquoted_len > j; ++i, ++j) 2112 { 2113 if ('\\' == quoted[i]) 2114 { 2115 i++; /* Advance to the next character */ 2116 if (quoted_len == i) 2117 return false; /* No character after escaping backslash */ 2118 } 2119 if (! charsequalcaseless (quoted[i], unquoted[j])) 2120 return false; /* Different characters */ 2121 } 2122 if ((quoted_len != i) || (unquoted_len != j)) 2123 return false; /* The strings have different length */ 2124 2125 return true; 2126 } 2127 2128 2129 size_t 2130 MHD_str_unquote (const char *quoted, 2131 size_t quoted_len, 2132 char *result) 2133 { 2134 size_t r; 2135 size_t w; 2136 2137 r = 0; 2138 w = 0; 2139 2140 while (quoted_len > r) 2141 { 2142 if ('\\' == quoted[r]) 2143 { 2144 ++r; 2145 if (quoted_len == r) 2146 return 0; /* Last backslash is not followed by char to unescape */ 2147 } 2148 result[w++] = quoted[r++]; 2149 } 2150 return w; 2151 } 2152 2153 2154 #endif /* DAUTH_SUPPORT */ 2155 2156 #if defined(DAUTH_SUPPORT) || defined(BAUTH_SUPPORT) 2157 2158 size_t 2159 MHD_str_quote (const char *unquoted, 2160 size_t unquoted_len, 2161 char *result, 2162 size_t buf_size) 2163 { 2164 size_t r; 2165 size_t w; 2166 2167 r = 0; 2168 w = 0; 2169 2170 #ifndef MHD_FAVOR_SMALL_CODE 2171 if (unquoted_len * 2 <= buf_size) 2172 { 2173 /* Fast loop: the output will fit the buffer with any input string content */ 2174 while (unquoted_len > r) 2175 { 2176 const char chr = unquoted[r++]; 2177 if (('\\' == chr) || ('\"' == chr)) 2178 result[w++] = '\\'; /* Escape current char */ 2179 result[w++] = chr; 2180 } 2181 } 2182 else 2183 { 2184 if (unquoted_len > buf_size) 2185 return 0; /* Quick fail: the output buffer is too small */ 2186 #else /* MHD_FAVOR_SMALL_CODE */ 2187 if (1) 2188 { 2189 #endif /* MHD_FAVOR_SMALL_CODE */ 2190 2191 while (unquoted_len > r) 2192 { 2193 if (buf_size <= w) 2194 return 0; /* The output buffer is too small */ 2195 else 2196 { 2197 const char chr = unquoted[r++]; 2198 if (('\\' == chr) || ('\"' == chr)) 2199 { 2200 result[w++] = '\\'; /* Escape current char */ 2201 if (buf_size <= w) 2202 return 0; /* The output buffer is too small */ 2203 } 2204 result[w++] = chr; 2205 } 2206 } 2207 } 2208 2209 mhd_assert (w >= r); 2210 mhd_assert (w <= r * 2); 2211 return w; 2212 } 2213 2214 2215 #endif /* DAUTH_SUPPORT || BAUTH_SUPPORT */ 2216 2217 #ifdef BAUTH_SUPPORT 2218 2219 /* 2220 * MHD_BASE64_FUNC_VERSION 2221 * 1 = smallest, 2222 * 2 = medium, 2223 * 3 = fastest 2224 */ 2225 #ifndef MHD_BASE64_FUNC_VERSION 2226 #ifdef MHD_FAVOR_SMALL_CODE 2227 #define MHD_BASE64_FUNC_VERSION 1 2228 #else /* ! MHD_FAVOR_SMALL_CODE */ 2229 #define MHD_BASE64_FUNC_VERSION 3 2230 #endif /* ! MHD_FAVOR_SMALL_CODE */ 2231 #endif /* ! MHD_BASE64_FUNC_VERSION */ 2232 2233 #if MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 2234 #error Wrong MHD_BASE64_FUNC_VERSION value 2235 #endif /* MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 */ 2236 2237 #if MHD_BASE64_FUNC_VERSION == 3 2238 #define MHD_base64_map_type_ int 2239 #else /* MHD_BASE64_FUNC_VERSION < 3 */ 2240 #define MHD_base64_map_type_ int8_t 2241 #endif /* MHD_BASE64_FUNC_VERSION < 3 */ 2242 2243 #if MHD_BASE64_FUNC_VERSION == 1 2244 static MHD_base64_map_type_ 2245 base64_char_to_value_ (uint8_t c) 2246 { 2247 if ('Z' >= c) 2248 { 2249 if ('A' <= c) 2250 return (MHD_base64_map_type_) ((c - 'A') + 0); 2251 if ('0' <= c) 2252 { 2253 if ('9' >= c) 2254 return (MHD_base64_map_type_) ((c - '0') + 52); 2255 if ('=' == c) 2256 return -2; 2257 return -1; 2258 } 2259 if ('+' == c) 2260 return 62; 2261 if ('/' == c) 2262 return 63; 2263 return -1; 2264 } 2265 if (('z' >= c) && ('a' <= c)) 2266 return (MHD_base64_map_type_) ((c - 'a') + 26); 2267 return -1; 2268 } 2269 2270 2271 #endif /* MHD_BASE64_FUNC_VERSION == 1 */ 2272 2273 2274 MHD_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE_ 2275 2276 2277 size_t 2278 MHD_base64_to_bin_n (const char *base64, 2279 size_t base64_len, 2280 void *bin, 2281 size_t bin_size) 2282 { 2283 #if MHD_BASE64_FUNC_VERSION >= 2 2284 static const MHD_base64_map_type_ map[] = { 2285 /* -1 = invalid char, -2 = padding 2286 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 2287 NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, */ 2288 -1, -1, -1, -1, -1, -1, -1, -1, 2289 /* 2290 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 2291 BS, HT, LF, VT, FF, CR, SO, SI, */ 2292 -1, -1, -1, -1, -1, -1, -1, -1, 2293 /* 2294 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 2295 DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, */ 2296 -1, -1, -1, -1, -1, -1, -1, -1, 2297 /* 2298 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 2299 CAN, EM, SUB, ESC, FS, GS, RS, US, */ 2300 -1, -1, -1, -1, -1, -1, -1, -1, 2301 /* 2302 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 2303 ' ', '!', '"', '#', '$', '%', '&', '\'', */ 2304 -1, -1, -1, -1, -1, -1, -1, -1, 2305 /* 2306 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 2307 '(', ')', '*', '+', ',', '-', '.', '/', */ 2308 -1, -1, -1, 62, -1, -1, -1, 63, 2309 /* 2310 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 2311 '0', '1', '2', '3', '4', '5', '6', '7', */ 2312 52, 53, 54, 55, 56, 57, 58, 59, 2313 /* 2314 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 2315 '8', '9', ':', ';', '<', '=', '>', '?', */ 2316 60, 61, -1, -1, -1, -2, -1, -1, 2317 /* 2318 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 2319 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */ 2320 -1, 0, 1, 2, 3, 4, 5, 6, 2321 /* 2322 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 2323 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */ 2324 7, 8, 9, 10, 11, 12, 13, 14, 2325 /* 2326 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 2327 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */ 2328 15, 16, 17, 18, 19, 20, 21, 22, 2329 /* 2330 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 2331 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */ 2332 23, 24, 25, -1, -1, -1, -1, -1, 2333 /* 2334 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 2335 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */ 2336 -1, 26, 27, 28, 29, 30, 31, 32, 2337 /* 2338 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 2339 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */ 2340 33, 34, 35, 36, 37, 38, 39, 40, 2341 /* 2342 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 2343 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */ 2344 41, 42, 43, 44, 45, 46, 47, 48, 2345 /* 2346 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 2347 'x', 'y', 'z', '{', '|', '}', '~', DEL, */ 2348 49, 50, 51, -1, -1, -1, -1, -1 2349 2350 #if MHD_BASE64_FUNC_VERSION == 3 2351 , 2352 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80..8F */ 2353 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90..9F */ 2354 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0..AF */ 2355 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0..BF */ 2356 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0..CF */ 2357 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0..DF */ 2358 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0..EF */ 2359 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* F0..FF */ 2360 #endif /* ! MHD_BASE64_FUNC_VERSION == 3 */ 2361 }; 2362 #define base64_char_to_value_(c) map[(c)] 2363 #endif /* MHD_BASE64_FUNC_VERSION >= 2 */ 2364 const uint8_t *const in = (const uint8_t *) base64; 2365 uint8_t *const out = (uint8_t *) bin; 2366 size_t i; 2367 size_t j; 2368 if (0 == base64_len) 2369 return 0; /* Nothing to decode */ 2370 if (0 != base64_len % 4) 2371 return 0; /* Wrong input length */ 2372 if (base64_len / 4 * 3 - 2 > bin_size) 2373 return 0; 2374 2375 j = 0; 2376 for (i = 0; i < (base64_len - 4); i += 4) 2377 { 2378 #if MHD_BASE64_FUNC_VERSION == 2 2379 if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3]))) 2380 return 0; 2381 #endif /* MHD_BASE64_FUNC_VERSION == 2 */ 2382 if (1) 2383 { 2384 const MHD_base64_map_type_ v1 = base64_char_to_value_ (in[i + 0]); 2385 const MHD_base64_map_type_ v2 = base64_char_to_value_ (in[i + 1]); 2386 const MHD_base64_map_type_ v3 = base64_char_to_value_ (in[i + 2]); 2387 const MHD_base64_map_type_ v4 = base64_char_to_value_ (in[i + 3]); 2388 if ((0 > v1) || (0 > v2) || (0 > v3) || (0 > v4)) 2389 return 0; 2390 out[j + 0] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2)) 2391 | ((uint8_t) (((uint8_t) v2) >> 4))); 2392 out[j + 1] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4)) 2393 | ((uint8_t) (((uint8_t) v3) >> 2))); 2394 out[j + 2] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6)) 2395 | ((uint8_t) v4)); 2396 } 2397 j += 3; 2398 } 2399 #if MHD_BASE64_FUNC_VERSION == 2 2400 if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3]))) 2401 return 0; 2402 #endif /* MHD_BASE64_FUNC_VERSION == 2 */ 2403 if (1) 2404 { /* The last four chars block */ 2405 const MHD_base64_map_type_ v1 = base64_char_to_value_ (in[i + 0]); 2406 const MHD_base64_map_type_ v2 = base64_char_to_value_ (in[i + 1]); 2407 const MHD_base64_map_type_ v3 = base64_char_to_value_ (in[i + 2]); 2408 const MHD_base64_map_type_ v4 = base64_char_to_value_ (in[i + 3]); 2409 if ((0 > v1) || (0 > v2)) 2410 return 0; /* Invalid char or padding at first two positions */ 2411 mhd_assert (j < bin_size); 2412 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v1) << 2)) 2413 | ((uint8_t) (((uint8_t) v2) >> 4))); 2414 if (0 > v3) 2415 { /* Third char is either padding or invalid */ 2416 if ((-2 != v3) || (-2 != v4)) 2417 return 0; /* Both two last chars must be padding */ 2418 if (0 != (uint8_t) (((uint8_t) v2) << 4)) 2419 return 0; /* Wrong last char */ 2420 return j; 2421 } 2422 if (j >= bin_size) 2423 return 0; /* Not enough space */ 2424 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v2) << 4)) 2425 | ((uint8_t) (((uint8_t) v3) >> 2))); 2426 if (0 > v4) 2427 { /* Fourth char is either padding or invalid */ 2428 if (-2 != v4) 2429 return 0; /* The char must be padding */ 2430 if (0 != (uint8_t) (((uint8_t) v3) << 6)) 2431 return 0; /* Wrong last char */ 2432 return j; 2433 } 2434 if (j >= bin_size) 2435 return 0; /* Not enough space */ 2436 out[j++] = (uint8_t) (((uint8_t) (((uint8_t) v3) << 6)) 2437 | ((uint8_t) v4)); 2438 } 2439 return j; 2440 #if MHD_BASE64_FUNC_VERSION >= 2 2441 #undef base64_char_to_value_ 2442 #endif /* MHD_BASE64_FUNC_VERSION >= 2 */ 2443 } 2444 2445 2446 MHD_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE_ 2447 2448 2449 #undef MHD_base64_map_type_ 2450 2451 #endif /* BAUTH_SUPPORT */