test_parse_cookies.c (39088B)
1 /* 2 This file is part of GNU libmicrohttpd 3 Copyright (C) 2007 Christian Grothoff 4 Copyright (C) 2016-2022 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published 8 by the Free Software Foundation; either version 2, or (at your 9 option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with libmicrohttpd; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 Boston, MA 02110-1301, USA. 20 */ 21 22 /** 23 * @file test_parse_cookies.c 24 * @brief Testcase for HTTP cookie parsing 25 * @author Karlson2k (Evgeny Grin) 26 * @author Christian Grothoff 27 */ 28 29 #include "mhd_options.h" 30 #include "platform.h" 31 #include <curl/curl.h> 32 #include <microhttpd.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <time.h> 36 #include <errno.h> 37 38 #ifndef _WIN32 39 #include <sys/socket.h> 40 #include <unistd.h> 41 #endif 42 43 #include "mhd_has_param.h" 44 #include "mhd_has_in_name.h" 45 46 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this 47 test into a marked, classifiable test error (TESTING.md, P5). */ 48 #include "mhd_panic_tripwire.h" 49 50 #ifndef MHD_STATICSTR_LEN_ 51 /** 52 * Determine length of static string / macro strings at compile time. 53 */ 54 #define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) 55 #endif /* ! MHD_STATICSTR_LEN_ */ 56 57 #ifndef CURL_VERSION_BITS 58 #define CURL_VERSION_BITS(x,y,z) ((x) << 16 | (y) << 8 | (z)) 59 #endif /* ! CURL_VERSION_BITS */ 60 #ifndef CURL_AT_LEAST_VERSION 61 #define CURL_AT_LEAST_VERSION(x,y,z) \ 62 (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS (x, y, z)) 63 #endif /* ! CURL_AT_LEAST_VERSION */ 64 65 #ifndef _MHD_INSTRMACRO 66 /* Quoted macro parameter */ 67 #define _MHD_INSTRMACRO(a) #a 68 #endif /* ! _MHD_INSTRMACRO */ 69 #ifndef _MHD_STRMACRO 70 /* Quoted expanded macro parameter */ 71 #define _MHD_STRMACRO(a) _MHD_INSTRMACRO (a) 72 #endif /* ! _MHD_STRMACRO */ 73 74 #if defined(HAVE___FUNC__) 75 #define externalErrorExit(ignore) \ 76 _externalErrorExit_func (NULL, __func__, __LINE__) 77 #define externalErrorExitDesc(errDesc) \ 78 _externalErrorExit_func (errDesc, __func__, __LINE__) 79 #define libcurlErrorExit(ignore) \ 80 _libcurlErrorExit_func (NULL, __func__, __LINE__) 81 #define libcurlErrorExitDesc(errDesc) \ 82 _libcurlErrorExit_func (errDesc, __func__, __LINE__) 83 #define mhdErrorExit(ignore) \ 84 _mhdErrorExit_func (NULL, __func__, __LINE__) 85 #define mhdErrorExitDesc(errDesc) \ 86 _mhdErrorExit_func (errDesc, __func__, __LINE__) 87 #define checkCURLE_OK(libcurlcall) \ 88 _checkCURLE_OK_func ((libcurlcall), _MHD_STRMACRO (libcurlcall), \ 89 __func__, __LINE__) 90 #elif defined(HAVE___FUNCTION__) 91 #define externalErrorExit(ignore) \ 92 _externalErrorExit_func (NULL, __FUNCTION__, __LINE__) 93 #define externalErrorExitDesc(errDesc) \ 94 _externalErrorExit_func (errDesc, __FUNCTION__, __LINE__) 95 #define libcurlErrorExit(ignore) \ 96 _libcurlErrorExit_func (NULL, __FUNCTION__, __LINE__) 97 #define libcurlErrorExitDesc(errDesc) \ 98 _libcurlErrorExit_func (errDesc, __FUNCTION__, __LINE__) 99 #define mhdErrorExit(ignore) \ 100 _mhdErrorExit_func (NULL, __FUNCTION__, __LINE__) 101 #define mhdErrorExitDesc(errDesc) \ 102 _mhdErrorExit_func (errDesc, __FUNCTION__, __LINE__) 103 #define checkCURLE_OK(libcurlcall) \ 104 _checkCURLE_OK_func ((libcurlcall), _MHD_STRMACRO (libcurlcall), \ 105 __FUNCTION__, __LINE__) 106 #else 107 #define externalErrorExit(ignore) _externalErrorExit_func (NULL, NULL, __LINE__) 108 #define externalErrorExitDesc(errDesc) \ 109 _externalErrorExit_func (errDesc, NULL, __LINE__) 110 #define libcurlErrorExit(ignore) _libcurlErrorExit_func (NULL, NULL, __LINE__) 111 #define libcurlErrorExitDesc(errDesc) \ 112 _libcurlErrorExit_func (errDesc, NULL, __LINE__) 113 #define mhdErrorExit(ignore) _mhdErrorExit_func (NULL, NULL, __LINE__) 114 #define mhdErrorExitDesc(errDesc) _mhdErrorExit_func (errDesc, NULL, __LINE__) 115 #define checkCURLE_OK(libcurlcall) \ 116 _checkCURLE_OK_func ((libcurlcall), _MHD_STRMACRO (libcurlcall), NULL, \ 117 __LINE__) 118 #endif 119 120 121 _MHD_NORETURN static void 122 _externalErrorExit_func (const char *errDesc, const char *funcName, int lineNum) 123 { 124 fflush (stdout); 125 if ((NULL != errDesc) && (0 != errDesc[0])) 126 fprintf (stderr, "%s", errDesc); 127 else 128 fprintf (stderr, "System or external library call failed"); 129 if ((NULL != funcName) && (0 != funcName[0])) 130 fprintf (stderr, " in %s", funcName); 131 if (0 < lineNum) 132 fprintf (stderr, " at line %d", lineNum); 133 134 fprintf (stderr, ".\nLast errno value: %d (%s)\n", (int) errno, 135 strerror (errno)); 136 #ifdef MHD_WINSOCK_SOCKETS 137 fprintf (stderr, "WSAGetLastError() value: %d\n", (int) WSAGetLastError ()); 138 #endif /* MHD_WINSOCK_SOCKETS */ 139 fflush (stderr); 140 exit (99); 141 } 142 143 144 static char libcurl_errbuf[CURL_ERROR_SIZE] = ""; 145 146 _MHD_NORETURN static void 147 _libcurlErrorExit_func (const char *errDesc, const char *funcName, int lineNum) 148 { 149 fflush (stdout); 150 if ((NULL != errDesc) && (0 != errDesc[0])) 151 fprintf (stderr, "%s", errDesc); 152 else 153 fprintf (stderr, "CURL library call failed"); 154 if ((NULL != funcName) && (0 != funcName[0])) 155 fprintf (stderr, " in %s", funcName); 156 if (0 < lineNum) 157 fprintf (stderr, " at line %d", lineNum); 158 159 fprintf (stderr, ".\nLast errno value: %d (%s)\n", (int) errno, 160 strerror (errno)); 161 #ifdef MHD_WINSOCK_SOCKETS 162 fprintf (stderr, "WSAGetLastError() value: %d\n", (int) WSAGetLastError ()); 163 #endif /* MHD_WINSOCK_SOCKETS */ 164 if (0 != libcurl_errbuf[0]) 165 fprintf (stderr, "Last libcurl error description: %s\n", libcurl_errbuf); 166 167 fflush (stderr); 168 exit (99); 169 } 170 171 172 _MHD_NORETURN static void 173 _mhdErrorExit_func (const char *errDesc, const char *funcName, int lineNum) 174 { 175 fflush (stdout); 176 if ((NULL != errDesc) && (0 != errDesc[0])) 177 fprintf (stderr, "%s", errDesc); 178 else 179 fprintf (stderr, "MHD unexpected error"); 180 if ((NULL != funcName) && (0 != funcName[0])) 181 fprintf (stderr, " in %s", funcName); 182 if (0 < lineNum) 183 fprintf (stderr, " at line %d", lineNum); 184 185 fprintf (stderr, ".\nLast errno value: %d (%s)\n", (int) errno, 186 strerror (errno)); 187 #ifdef MHD_WINSOCK_SOCKETS 188 fprintf (stderr, "WSAGetLastError() value: %d\n", (int) WSAGetLastError ()); 189 #endif /* MHD_WINSOCK_SOCKETS */ 190 191 fflush (stderr); 192 exit (8); 193 } 194 195 196 /* Could be increased to facilitate debugging */ 197 #define TIMEOUTS_VAL 500000 198 199 #define EXPECTED_URI_BASE_PATH "/" 200 201 #define URL_SCHEME "http:/" "/" 202 203 #define URL_HOST "127.0.0.1" 204 205 #define URL_SCHEME_HOST URL_SCHEME URL_HOST 206 207 #define PAGE \ 208 "<html><head><title>libmicrohttpd test page</title></head>" \ 209 "<body>Success!</body></html>" 210 211 #define PAGE_ERROR \ 212 "<html><body>Cookies parsing error</body></html>" 213 214 215 #ifndef MHD_STATICSTR_LEN_ 216 /** 217 * Determine length of static string / macro strings at compile time. 218 */ 219 #define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) 220 #endif /* ! MHD_STATICSTR_LEN_ */ 221 222 223 struct strct_str_len 224 { 225 const char *str; 226 const size_t len; 227 }; 228 229 #define STR_LEN_(str) {str, MHD_STATICSTR_LEN_ (str)} 230 #define STR_NULL_ {NULL, 0} 231 232 struct strct_cookie 233 { 234 struct strct_str_len name; 235 struct strct_str_len value; 236 }; 237 238 #define COOKIE_(name,value) {STR_LEN_ (name), STR_LEN_ (value)} 239 #define COOKIE_NULL {STR_NULL_, STR_NULL_} 240 241 struct strct_test_data 242 { 243 unsigned int line_num; 244 const char *header_str; 245 unsigned int num_cookies_strict_p2; 246 unsigned int num_cookies_strict_p1; 247 unsigned int num_cookies_strict_zero; 248 unsigned int num_cookies_strict_n2; 249 unsigned int num_cookies_strict_n3; 250 struct strct_cookie cookies[5]; 251 }; 252 253 static const struct strct_test_data test_data[] = { 254 { 255 __LINE__, 256 "name1=value1", 257 1, 258 1, 259 1, 260 1, 261 1, 262 { 263 COOKIE_ ("name1", "value1"), 264 COOKIE_NULL, 265 COOKIE_NULL, 266 COOKIE_NULL, 267 COOKIE_NULL 268 } 269 }, 270 { 271 __LINE__, 272 "name1=value1;", 273 0, 274 1, 275 1, 276 1, 277 1, 278 { 279 COOKIE_ ("name1", "value1"), 280 COOKIE_NULL, 281 COOKIE_NULL, 282 COOKIE_NULL, 283 COOKIE_NULL 284 } 285 }, 286 { 287 __LINE__, 288 "name1=value1; ", 289 0, 290 1, 291 1, 292 1, 293 1, 294 { 295 COOKIE_ ("name1", "value1"), 296 COOKIE_NULL, 297 COOKIE_NULL, 298 COOKIE_NULL, 299 COOKIE_NULL 300 } 301 }, 302 { 303 __LINE__, 304 "; name1=value1", 305 0, 306 0, 307 1, 308 1, 309 1, 310 { 311 COOKIE_ ("name1", "value1"), 312 COOKIE_NULL, 313 COOKIE_NULL, 314 COOKIE_NULL, 315 COOKIE_NULL 316 } 317 }, 318 { 319 __LINE__, 320 ";name1=value1", 321 0, 322 0, 323 1, 324 1, 325 1, 326 { 327 COOKIE_ ("name1", "value1"), 328 COOKIE_NULL, 329 COOKIE_NULL, 330 COOKIE_NULL, 331 COOKIE_NULL 332 } 333 }, 334 { 335 __LINE__, 336 "name1=value1 ", 337 1, 338 1, 339 1, 340 1, 341 1, 342 { 343 COOKIE_ ("name1", "value1"), 344 COOKIE_NULL, 345 COOKIE_NULL, 346 COOKIE_NULL, 347 COOKIE_NULL 348 } 349 }, 350 { 351 __LINE__, 352 "name1=value1 ;", 353 0, 354 0, 355 1, 356 1, 357 1, 358 { 359 COOKIE_ ("name1", "value1"), 360 COOKIE_NULL, 361 COOKIE_NULL, 362 COOKIE_NULL, 363 COOKIE_NULL 364 } 365 }, 366 { 367 __LINE__, 368 "name1=value1 ; ", 369 0, 370 0, 371 1, 372 1, 373 1, 374 { 375 COOKIE_ ("name1", "value1"), 376 COOKIE_NULL, 377 COOKIE_NULL, 378 COOKIE_NULL, 379 COOKIE_NULL 380 } 381 }, 382 { 383 __LINE__, 384 "name2=\"value 2\"", 385 0, 386 0, 387 0, 388 1, 389 1, 390 { 391 COOKIE_ ("name2", "value 2"), 392 COOKIE_NULL, 393 COOKIE_NULL, 394 COOKIE_NULL, 395 COOKIE_NULL 396 } 397 }, 398 { 399 __LINE__, 400 "name1=value1;\tname2=value2", 401 0, 402 1, 403 2, 404 2, 405 2, 406 { 407 COOKIE_ ("name1", "value1"), 408 COOKIE_ ("name2", "value2"), 409 COOKIE_NULL, 410 COOKIE_NULL, 411 COOKIE_NULL 412 } 413 }, 414 { 415 __LINE__, 416 "name1=value1; name1=value1", 417 2, 418 2, 419 2, 420 2, 421 2, 422 { 423 COOKIE_ ("name1", "value1"), 424 COOKIE_ ("name1", "value1"), /* The second value is not checked actually */ 425 COOKIE_NULL, 426 COOKIE_NULL, 427 COOKIE_NULL 428 } 429 }, 430 { 431 __LINE__, 432 "name1=value1; name2=value2", 433 2, 434 2, 435 2, 436 2, 437 2, 438 { 439 COOKIE_ ("name1", "value1"), 440 COOKIE_ ("name2", "value2"), 441 COOKIE_NULL, 442 COOKIE_NULL, 443 COOKIE_NULL 444 } 445 }, 446 { 447 __LINE__, 448 "name1=value1; name2=value2 ", 449 2, 450 2, 451 2, 452 2, 453 2, 454 { 455 COOKIE_ ("name1", "value1"), 456 COOKIE_ ("name2", "value2"), 457 COOKIE_NULL, 458 COOKIE_NULL, 459 COOKIE_NULL 460 } 461 }, 462 { 463 __LINE__, 464 "name1=value1; name2=value2", 465 0, 466 1, 467 2, 468 2, 469 2, 470 { 471 COOKIE_ ("name1", "value1"), 472 COOKIE_ ("name2", "value2"), 473 COOKIE_NULL, 474 COOKIE_NULL, 475 COOKIE_NULL 476 } 477 }, 478 { 479 __LINE__, 480 "name1=value1;name2=value2", 481 0, 482 1, 483 2, 484 2, 485 2, 486 { 487 COOKIE_ ("name1", "value1"), 488 COOKIE_ ("name2", "value2"), 489 COOKIE_NULL, 490 COOKIE_NULL, 491 COOKIE_NULL 492 } 493 }, 494 { 495 __LINE__, 496 "name1=value1;\tname2=value2", 497 0, 498 1, 499 2, 500 2, 501 2, 502 { 503 COOKIE_ ("name1", "value1"), 504 COOKIE_ ("name2", "value2"), 505 COOKIE_NULL, 506 COOKIE_NULL, 507 COOKIE_NULL 508 } 509 }, 510 { 511 __LINE__, 512 "name1=value1 ; name2=value2", 513 0, 514 0, 515 2, 516 2, 517 2, 518 { 519 COOKIE_ ("name1", "value1"), 520 COOKIE_ ("name2", "value2"), 521 COOKIE_NULL, 522 COOKIE_NULL, 523 COOKIE_NULL 524 } 525 }, 526 { 527 __LINE__, 528 " name1=value1; name2=value2", 529 2, 530 2, 531 2, 532 2, 533 2, 534 { 535 COOKIE_ ("name1", "value1"), 536 COOKIE_ ("name2", "value2"), 537 COOKIE_NULL, 538 COOKIE_NULL, 539 COOKIE_NULL 540 } 541 }, 542 { 543 __LINE__, 544 "name1=var1; name2=var2; name3=; " \ 545 "name4=\"var4 with spaces\"; " \ 546 "name5=var_with_=_char", 547 0, 548 3, 549 3, 550 5, 551 5, 552 { 553 COOKIE_ ("name1", "var1"), 554 COOKIE_ ("name2", "var2"), 555 COOKIE_ ("name3", ""), 556 COOKIE_ ("name4", "var4 with spaces"), 557 COOKIE_ ("name5", "var_with_=_char") 558 } 559 }, 560 { 561 __LINE__, 562 "name1=var1;name2=var2;name3=;" \ 563 "name4=\"var4 with spaces\";" \ 564 "name5=var_with_=_char", 565 0, 566 1, 567 3, 568 5, 569 5, 570 { 571 COOKIE_ ("name1", "var1"), 572 COOKIE_ ("name2", "var2"), 573 COOKIE_ ("name3", ""), 574 COOKIE_ ("name4", "var4 with spaces"), 575 COOKIE_ ("name5", "var_with_=_char") 576 } 577 }, 578 { 579 __LINE__, 580 "name1=var1; name2=var2; name3=; " \ 581 "name4=\"var4 with spaces\"; " \ 582 "name5=var_with_=_char\t \t", 583 0, 584 1, 585 3, 586 5, 587 5, 588 { 589 COOKIE_ ("name1", "var1"), 590 COOKIE_ ("name2", "var2"), 591 COOKIE_ ("name3", ""), 592 COOKIE_ ("name4", "var4 with spaces"), 593 COOKIE_ ("name5", "var_with_=_char") 594 } 595 }, 596 { 597 __LINE__, 598 "name1=var1;;name2=var2;;name3=;;" \ 599 "name4=\"var4 with spaces\";;" \ 600 "name5=var_with_=_char;\t \t", 601 0, 602 1, 603 3, 604 5, 605 5, 606 { 607 COOKIE_ ("name1", "var1"), 608 COOKIE_ ("name2", "var2"), 609 COOKIE_ ("name3", ""), 610 COOKIE_ ("name4", "var4 with spaces"), 611 COOKIE_ ("name5", "var_with_=_char") 612 } 613 }, 614 { 615 __LINE__, 616 "name3=; name1=var1; name2=var2; " \ 617 "name5=var_with_=_char;" \ 618 "name4=\"var4 with spaces\"", 619 0, 620 4, 621 4, 622 5, 623 5, 624 { 625 COOKIE_ ("name1", "var1"), 626 COOKIE_ ("name2", "var2"), 627 COOKIE_ ("name3", ""), 628 COOKIE_ ("name5", "var_with_=_char"), 629 COOKIE_ ("name4", "var4 with spaces") 630 } 631 }, 632 { 633 __LINE__, 634 "name2=var2; name1=var1; " \ 635 "name5=var_with_=_char; name3=; " \ 636 "name4=\"var4 with spaces\";", 637 0, 638 4, 639 4, 640 5, 641 5, 642 { 643 COOKIE_ ("name1", "var1"), 644 COOKIE_ ("name2", "var2"), 645 COOKIE_ ("name3", ""), 646 COOKIE_ ("name5", "var_with_=_char"), 647 COOKIE_ ("name4", "var4 with spaces") 648 } 649 }, 650 { 651 __LINE__, 652 "name2=var2; name1=var1; " \ 653 "name5=var_with_=_char; " \ 654 "name4=\"var4 with spaces\"; name3=", 655 0, 656 3, 657 3, 658 5, 659 5, 660 { 661 COOKIE_ ("name1", "var1"), 662 COOKIE_ ("name2", "var2"), 663 COOKIE_ ("name5", "var_with_=_char"), 664 COOKIE_ ("name3", ""), 665 COOKIE_ ("name4", "var4 with spaces") 666 } 667 }, 668 { 669 __LINE__, 670 "name2=var2; name1=var1; " \ 671 "name4=\"var4 with spaces\"; " \ 672 "name5=var_with_=_char; name3=;", 673 0, 674 2, 675 2, 676 5, 677 5, 678 { 679 COOKIE_ ("name1", "var1"), 680 COOKIE_ ("name2", "var2"), 681 COOKIE_ ("name3", ""), 682 COOKIE_ ("name4", "var4 with spaces"), 683 COOKIE_ ("name5", "var_with_=_char") 684 } 685 }, 686 { 687 __LINE__, 688 ";;;;;;;;name1=var1; name2=var2; name3=; " \ 689 "name4=\"var4 with spaces\"; " \ 690 "name5=var_with_=_char", 691 0, 692 0, 693 3, 694 5, 695 5, 696 { 697 COOKIE_ ("name1", "var1"), 698 COOKIE_ ("name2", "var2"), 699 COOKIE_ ("name3", ""), 700 COOKIE_ ("name4", "var4 with spaces"), 701 COOKIE_ ("name5", "var_with_=_char") 702 } 703 }, 704 { 705 __LINE__, 706 "name1=var1; name2=var2; name3=; " \ 707 "name4=\"var4 with spaces\"; ; ; ; ; " \ 708 "name5=var_with_=_char", 709 0, 710 3, 711 3, 712 5, 713 5, 714 { 715 COOKIE_ ("name1", "var1"), 716 COOKIE_ ("name2", "var2"), 717 COOKIE_ ("name3", ""), 718 COOKIE_ ("name4", "var4 with spaces"), 719 COOKIE_ ("name5", "var_with_=_char") 720 } 721 }, 722 { 723 __LINE__, 724 "name1=var1; name2=var2; name3=; " \ 725 "name4=\"var4 with spaces\"; " \ 726 "name5=var_with_=_char;;;;;;;;", 727 0, 728 3, 729 3, 730 5, 731 5, 732 { 733 COOKIE_ ("name1", "var1"), 734 COOKIE_ ("name2", "var2"), 735 COOKIE_ ("name3", ""), 736 COOKIE_ ("name4", "var4 with spaces"), 737 COOKIE_ ("name5", "var_with_=_char") 738 } 739 }, 740 { 741 __LINE__, 742 "name1=var1; name2=var2; " \ 743 "name4=\"var4 with spaces\";" \ 744 "name5=var_with_=_char; ; ; ; ; name3=", 745 0, 746 2, 747 2, 748 5, 749 5, 750 { 751 COOKIE_ ("name1", "var1"), 752 COOKIE_ ("name2", "var2"), 753 COOKIE_ ("name5", "var_with_=_char"), 754 COOKIE_ ("name3", ""), 755 COOKIE_ ("name4", "var4 with spaces") 756 } 757 }, 758 { 759 __LINE__, 760 "name5=var_with_=_char ;" \ 761 "name1=var1; name2=var2; name3=; " \ 762 "name4=\"var4 with spaces\" ", 763 0, 764 0, 765 4, 766 5, 767 5, 768 { 769 COOKIE_ ("name1", "var1"), 770 COOKIE_ ("name2", "var2"), 771 COOKIE_ ("name3", ""), 772 COOKIE_ ("name5", "var_with_=_char"), 773 COOKIE_ ("name4", "var4 with spaces") 774 } 775 }, 776 { 777 __LINE__, 778 "name5=var_with_=_char; name4=\"var4 with spaces\";" \ 779 "name1=var1; name2=var2; name3=", 780 0, 781 1, 782 1, 783 5, 784 5, 785 { 786 COOKIE_ ("name5", "var_with_=_char"), 787 COOKIE_ ("name1", "var1"), 788 COOKIE_ ("name2", "var2"), 789 COOKIE_ ("name3", ""), 790 COOKIE_ ("name4", "var4 with spaces") 791 } 792 }, 793 { 794 __LINE__, 795 "name5=var_with_=_char; name4=\"var4_without_spaces\"; " \ 796 "name1=var1; name2=var2; name3=", 797 5, 798 5, 799 5, 800 5, 801 5, 802 { 803 COOKIE_ ("name5", "var_with_=_char"), 804 COOKIE_ ("name1", "var1"), 805 COOKIE_ ("name2", "var2"), 806 COOKIE_ ("name3", ""), 807 COOKIE_ ("name4", "var4_without_spaces") 808 } 809 }, 810 { 811 __LINE__, 812 "name1 = value1", 813 0, 814 0, 815 0, 816 0, 817 1, 818 { 819 COOKIE_ ("name1", "value1"), 820 COOKIE_NULL, 821 COOKIE_NULL, 822 COOKIE_NULL, 823 COOKIE_NULL 824 } 825 }, 826 { 827 __LINE__, 828 "name1\t=\tvalue1", 829 0, 830 0, 831 0, 832 0, 833 1, 834 { 835 COOKIE_ ("name1", "value1"), 836 COOKIE_NULL, 837 COOKIE_NULL, 838 COOKIE_NULL, 839 COOKIE_NULL 840 } 841 }, 842 { 843 __LINE__, 844 "name1\t = \tvalue1", 845 0, 846 0, 847 0, 848 0, 849 1, 850 { 851 COOKIE_ ("name1", "value1"), 852 COOKIE_NULL, 853 COOKIE_NULL, 854 COOKIE_NULL, 855 COOKIE_NULL 856 } 857 }, 858 { 859 __LINE__, 860 "name1 = value1; name2 =\tvalue2", 861 0, 862 0, 863 0, 864 0, 865 2, 866 { 867 COOKIE_ ("name1", "value1"), 868 COOKIE_ ("name2", "value2"), 869 COOKIE_NULL, 870 COOKIE_NULL, 871 COOKIE_NULL 872 } 873 }, 874 { 875 __LINE__, 876 "name1=value1; name2 =\tvalue2", 877 0, 878 1, 879 1, 880 1, 881 2, 882 { 883 COOKIE_ ("name1", "value1"), 884 COOKIE_ ("name2", "value2"), 885 COOKIE_NULL, 886 COOKIE_NULL, 887 COOKIE_NULL 888 } 889 }, 890 { 891 __LINE__, 892 "name1 = value1; name2=value2", 893 0, 894 0, 895 0, 896 0, 897 2, 898 { 899 COOKIE_ ("name1", "value1"), 900 COOKIE_ ("name2", "value2"), 901 COOKIE_NULL, 902 COOKIE_NULL, 903 COOKIE_NULL 904 } 905 }, 906 { 907 __LINE__, 908 "", 909 0, 910 0, 911 0, 912 0, 913 0, 914 { 915 COOKIE_NULL, 916 COOKIE_NULL, 917 COOKIE_NULL, 918 COOKIE_NULL, 919 COOKIE_NULL 920 } 921 }, 922 { 923 __LINE__, 924 " ", 925 0, 926 0, 927 0, 928 0, 929 0, 930 { 931 COOKIE_NULL, 932 COOKIE_NULL, 933 COOKIE_NULL, 934 COOKIE_NULL, 935 COOKIE_NULL 936 } 937 }, 938 { 939 __LINE__, 940 "\t", 941 0, 942 0, 943 0, 944 0, 945 0, 946 { 947 COOKIE_NULL, 948 COOKIE_NULL, 949 COOKIE_NULL, 950 COOKIE_NULL, 951 COOKIE_NULL 952 } 953 }, 954 { 955 __LINE__, 956 "var=,", 957 0, 958 0, 959 0, 960 0, 961 0, 962 { 963 COOKIE_NULL, 964 COOKIE_NULL, 965 COOKIE_NULL, 966 COOKIE_NULL, 967 COOKIE_NULL 968 } 969 }, 970 { 971 __LINE__, 972 "var=\"\\ \"", 973 0, 974 0, 975 0, 976 0, 977 0, 978 { 979 COOKIE_NULL, 980 COOKIE_NULL, 981 COOKIE_NULL, 982 COOKIE_NULL, 983 COOKIE_NULL 984 } 985 }, 986 { 987 __LINE__, 988 "var=value space", 989 0, 990 0, 991 0, 992 0, 993 0, 994 { 995 COOKIE_NULL, 996 COOKIE_NULL, 997 COOKIE_NULL, 998 COOKIE_NULL, 999 COOKIE_NULL 1000 } 1001 }, 1002 { 1003 __LINE__, 1004 "var=value\ttab", 1005 0, 1006 0, 1007 0, 1008 0, 1009 0, 1010 { 1011 COOKIE_NULL, 1012 COOKIE_NULL, 1013 COOKIE_NULL, 1014 COOKIE_NULL, 1015 COOKIE_NULL 1016 } 1017 }, 1018 { 1019 __LINE__, 1020 "=", 1021 0, 1022 0, 1023 0, 1024 0, 1025 0, 1026 { 1027 COOKIE_NULL, 1028 COOKIE_NULL, 1029 COOKIE_NULL, 1030 COOKIE_NULL, 1031 COOKIE_NULL 1032 } 1033 }, 1034 { 1035 __LINE__, 1036 "====", 1037 0, 1038 0, 1039 0, 1040 0, 1041 0, 1042 { 1043 COOKIE_NULL, 1044 COOKIE_NULL, 1045 COOKIE_NULL, 1046 COOKIE_NULL, 1047 COOKIE_NULL 1048 } 1049 }, 1050 { 1051 __LINE__, 1052 ";=", 1053 0, 1054 0, 1055 0, 1056 0, 1057 0, 1058 { 1059 COOKIE_NULL, 1060 COOKIE_NULL, 1061 COOKIE_NULL, 1062 COOKIE_NULL, 1063 COOKIE_NULL 1064 } 1065 }, 1066 { 1067 __LINE__, 1068 "var", 1069 0, 1070 0, 1071 0, 1072 0, 1073 0, 1074 { 1075 COOKIE_NULL, 1076 COOKIE_NULL, 1077 COOKIE_NULL, 1078 COOKIE_NULL, 1079 COOKIE_NULL 1080 } 1081 }, 1082 { 1083 __LINE__, 1084 "=;", 1085 0, 1086 0, 1087 0, 1088 0, 1089 0, 1090 { 1091 COOKIE_NULL, 1092 COOKIE_NULL, 1093 COOKIE_NULL, 1094 COOKIE_NULL, 1095 COOKIE_NULL 1096 } 1097 }, 1098 { 1099 __LINE__, 1100 "= ;", 1101 0, 1102 0, 1103 0, 1104 0, 1105 0, 1106 { 1107 COOKIE_NULL, 1108 COOKIE_NULL, 1109 COOKIE_NULL, 1110 COOKIE_NULL, 1111 COOKIE_NULL 1112 } 1113 }, 1114 { 1115 __LINE__, 1116 ";= ;", 1117 0, 1118 0, 1119 0, 1120 0, 1121 0, 1122 { 1123 COOKIE_NULL, 1124 COOKIE_NULL, 1125 COOKIE_NULL, 1126 COOKIE_NULL, 1127 COOKIE_NULL 1128 } 1129 } 1130 }; 1131 1132 /* Global parameters */ 1133 static int verbose; 1134 static int oneone; /**< If false use HTTP/1.0 for requests*/ 1135 static int use_discp_n3; 1136 static int use_discp_n2; 1137 static int use_discp_zero; 1138 static int use_discp_p1; 1139 static int use_discp_p2; 1140 static int discp_level; 1141 1142 static void 1143 test_global_init (void) 1144 { 1145 libcurl_errbuf[0] = 0; 1146 1147 if (0 != curl_global_init (CURL_GLOBAL_WIN32)) 1148 externalErrorExit (); 1149 } 1150 1151 1152 static void 1153 test_global_cleanup (void) 1154 { 1155 curl_global_cleanup (); 1156 } 1157 1158 1159 struct CBC 1160 { 1161 char *buf; 1162 size_t pos; 1163 size_t size; 1164 }; 1165 1166 1167 static size_t 1168 copyBuffer (void *ptr, 1169 size_t size, 1170 size_t nmemb, 1171 void *ctx) 1172 { 1173 struct CBC *cbc = ctx; 1174 1175 if (cbc->pos + size * nmemb > cbc->size) 1176 return 0; /* overflow */ 1177 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); 1178 cbc->pos += size * nmemb; 1179 return size * nmemb; 1180 } 1181 1182 1183 struct ahc_cls_type 1184 { 1185 const char *rq_method; 1186 const char *rq_url; 1187 const struct strct_test_data *check; 1188 }; 1189 1190 1191 static enum MHD_Result 1192 ahcCheck (void *cls, 1193 struct MHD_Connection *connection, 1194 const char *url, 1195 const char *method, 1196 const char *version, 1197 const char *upload_data, size_t *upload_data_size, 1198 void **req_cls) 1199 { 1200 static int marker; 1201 struct MHD_Response *response; 1202 enum MHD_Result ret; 1203 struct ahc_cls_type *const param = (struct ahc_cls_type *) cls; 1204 unsigned int expected_num_cookies; 1205 unsigned int i; 1206 int cookie_failed; 1207 1208 if (NULL == param) 1209 mhdErrorExitDesc ("cls parameter is NULL"); 1210 if (use_discp_p2) 1211 expected_num_cookies = param->check->num_cookies_strict_p2; 1212 else if (use_discp_p1) 1213 expected_num_cookies = param->check->num_cookies_strict_p1; 1214 else if (use_discp_zero) 1215 expected_num_cookies = param->check->num_cookies_strict_zero; 1216 else if (use_discp_n2) 1217 expected_num_cookies = param->check->num_cookies_strict_n2; 1218 else if (use_discp_n3) 1219 expected_num_cookies = param->check->num_cookies_strict_n3; 1220 else 1221 externalErrorExit (); 1222 1223 1224 if (oneone) 1225 { 1226 if (0 != strcmp (version, MHD_HTTP_VERSION_1_1)) 1227 mhdErrorExitDesc ("Unexpected HTTP version"); 1228 } 1229 else 1230 { 1231 if (0 != strcmp (version, MHD_HTTP_VERSION_1_0)) 1232 mhdErrorExitDesc ("Unexpected HTTP version"); 1233 } 1234 1235 if (0 != strcmp (url, param->rq_url)) 1236 mhdErrorExitDesc ("Unexpected URI"); 1237 1238 if (NULL != upload_data) 1239 mhdErrorExitDesc ("'upload_data' is not NULL"); 1240 1241 if (NULL == upload_data_size) 1242 mhdErrorExitDesc ("'upload_data_size' pointer is NULL"); 1243 1244 if (0 != *upload_data_size) 1245 mhdErrorExitDesc ("'*upload_data_size' value is not zero"); 1246 1247 if (0 != strcmp (param->rq_method, method)) 1248 mhdErrorExitDesc ("Unexpected request method"); 1249 1250 cookie_failed = 0; 1251 for (i = 0; i < expected_num_cookies; ++i) 1252 { 1253 const char *cookie_val; 1254 size_t cookie_val_len; 1255 const struct strct_cookie *const cookie_data = param->check->cookies + i; 1256 if (NULL == cookie_data->name.str) 1257 externalErrorExitDesc ("Broken test data"); 1258 if (NULL == cookie_data->value.str) 1259 externalErrorExitDesc ("Broken test data"); 1260 1261 cookie_val = 1262 MHD_lookup_connection_value (connection, 1263 MHD_COOKIE_KIND, 1264 cookie_data->name.str); 1265 if (cookie_val == NULL) 1266 { 1267 fprintf (stderr, "'%s' cookie not found.\n", 1268 cookie_data->name.str); 1269 cookie_failed = 1; 1270 } 1271 else if (0 != strcmp (cookie_val, 1272 cookie_data->value.str)) 1273 { 1274 fprintf (stderr, "'%s' cookie decoded incorrectly.\n" 1275 "Expected: %s\nGot: %s\n", 1276 cookie_data->name.str, 1277 cookie_data->value.str, 1278 cookie_val); 1279 cookie_failed = 1; 1280 } 1281 else if (MHD_YES != 1282 MHD_lookup_connection_value_n (connection, 1283 MHD_COOKIE_KIND, 1284 cookie_data->name.str, 1285 cookie_data->name.len, 1286 &cookie_val, &cookie_val_len)) 1287 { 1288 fprintf (stderr, "'%s' (length %lu) cookie not found.\n", 1289 cookie_data->name.str, 1290 (unsigned long) cookie_data->name.len); 1291 cookie_failed = 1; 1292 } 1293 else 1294 { 1295 if (cookie_data->value.len != cookie_val_len) 1296 { 1297 fprintf (stderr, "'%s' (length %lu) cookie has wrong value length.\n" 1298 "Expected: %lu\nGot: %lu\n", 1299 cookie_data->name.str, 1300 (unsigned long) cookie_data->name.len, 1301 (unsigned long) cookie_data->value.len, 1302 (unsigned long) cookie_val_len); 1303 cookie_failed = 1; 1304 } 1305 else if (0 != memcmp (cookie_val, cookie_data->value.str, cookie_val_len)) 1306 { 1307 fprintf (stderr, "'%s' (length %lu) cookie has wrong value.\n" 1308 "Expected: %.*s\nGot: %.*s\n", 1309 cookie_data->name.str, 1310 (unsigned long) cookie_data->name.len, 1311 (int) cookie_data->value.len, cookie_data->value.str, 1312 (int) cookie_val_len, cookie_val); 1313 cookie_failed = 1; 1314 } 1315 } 1316 } 1317 if (((int) expected_num_cookies) != 1318 MHD_get_connection_values_n (connection, MHD_COOKIE_KIND, NULL, NULL)) 1319 { 1320 fprintf (stderr, "Wrong total number of cookies.\n" 1321 "Expected: %u\nGot: %d\n", 1322 expected_num_cookies, 1323 MHD_get_connection_values_n (connection, MHD_COOKIE_KIND, NULL, 1324 NULL)); 1325 cookie_failed = 1; 1326 } 1327 if (cookie_failed) 1328 { 1329 response = 1330 MHD_create_response_from_buffer_static (MHD_STATICSTR_LEN_ (PAGE_ERROR), 1331 PAGE_ERROR); 1332 ret = MHD_queue_response (connection, 1333 MHD_HTTP_BAD_REQUEST, 1334 response); 1335 MHD_destroy_response (response); 1336 1337 return ret; 1338 } 1339 1340 if (&marker != *req_cls) 1341 { 1342 *req_cls = ▮ 1343 return MHD_YES; 1344 } 1345 *req_cls = NULL; 1346 1347 response = 1348 MHD_create_response_from_buffer_static (MHD_STATICSTR_LEN_ (PAGE), 1349 PAGE); 1350 if (NULL == response) 1351 mhdErrorExitDesc ("Failed to create response"); 1352 1353 ret = MHD_queue_response (connection, 1354 MHD_HTTP_OK, 1355 response); 1356 MHD_destroy_response (response); 1357 if (MHD_YES != ret) 1358 mhdErrorExitDesc ("Failed to queue response"); 1359 1360 return ret; 1361 } 1362 1363 1364 static int 1365 libcurl_debug_cb (CURL *handle, 1366 curl_infotype type, 1367 char *data, 1368 size_t size, 1369 void *userptr) 1370 { 1371 static const char excess_mark[] = "Excess found"; 1372 static const size_t excess_mark_len = MHD_STATICSTR_LEN_ (excess_mark); 1373 1374 (void) handle; 1375 (void) userptr; 1376 1377 #ifdef _DEBUG 1378 switch (type) 1379 { 1380 case CURLINFO_TEXT: 1381 fprintf (stderr, "* %.*s", (int) size, data); 1382 break; 1383 case CURLINFO_HEADER_IN: 1384 fprintf (stderr, "< %.*s", (int) size, data); 1385 break; 1386 case CURLINFO_HEADER_OUT: 1387 fprintf (stderr, "> %.*s", (int) size, data); 1388 break; 1389 case CURLINFO_DATA_IN: 1390 #if 0 1391 fprintf (stderr, "<| %.*s\n", (int) size, data); 1392 #endif 1393 break; 1394 case CURLINFO_DATA_OUT: 1395 case CURLINFO_SSL_DATA_IN: 1396 case CURLINFO_SSL_DATA_OUT: 1397 case CURLINFO_END: 1398 default: 1399 break; 1400 } 1401 #endif /* _DEBUG */ 1402 if (CURLINFO_TEXT == type) 1403 { 1404 if ((size >= excess_mark_len) && 1405 (0 == memcmp (data, excess_mark, excess_mark_len))) 1406 mhdErrorExitDesc ("Extra data has been detected in MHD reply"); 1407 } 1408 return 0; 1409 } 1410 1411 1412 static CURL * 1413 setupCURL (void *cbc, uint16_t port) 1414 { 1415 CURL *c; 1416 1417 c = curl_easy_init (); 1418 if (NULL == c) 1419 libcurlErrorExitDesc ("curl_easy_init() failed"); 1420 1421 if ((CURLE_OK != curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L)) || 1422 (CURLE_OK != curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, 1423 ©Buffer)) || 1424 (CURLE_OK != curl_easy_setopt (c, CURLOPT_WRITEDATA, cbc)) || 1425 (CURLE_OK != curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 1426 ((long) TIMEOUTS_VAL))) || 1427 (CURLE_OK != curl_easy_setopt (c, CURLOPT_HTTP_VERSION, 1428 (oneone) ? 1429 CURL_HTTP_VERSION_1_1 : 1430 CURL_HTTP_VERSION_1_0)) || 1431 (CURLE_OK != curl_easy_setopt (c, CURLOPT_TIMEOUT, 1432 ((long) TIMEOUTS_VAL))) || 1433 (CURLE_OK != curl_easy_setopt (c, CURLOPT_ERRORBUFFER, 1434 libcurl_errbuf)) || 1435 (CURLE_OK != curl_easy_setopt (c, CURLOPT_FAILONERROR, 0L)) || 1436 #ifdef _DEBUG 1437 (CURLE_OK != curl_easy_setopt (c, CURLOPT_VERBOSE, 1L)) || 1438 #endif /* _DEBUG */ 1439 (CURLE_OK != curl_easy_setopt (c, CURLOPT_DEBUGFUNCTION, 1440 &libcurl_debug_cb)) || 1441 #if CURL_AT_LEAST_VERSION (7, 85, 0) 1442 (CURLE_OK != curl_easy_setopt (c, CURLOPT_PROTOCOLS_STR, "http")) || 1443 #elif CURL_AT_LEAST_VERSION (7, 19, 4) 1444 (CURLE_OK != curl_easy_setopt (c, CURLOPT_PROTOCOLS, CURLPROTO_HTTP)) || 1445 #endif /* CURL_AT_LEAST_VERSION (7, 19, 4) */ 1446 #if CURL_AT_LEAST_VERSION (7, 45, 0) 1447 (CURLE_OK != curl_easy_setopt (c, CURLOPT_DEFAULT_PROTOCOL, "http")) || 1448 #endif /* CURL_AT_LEAST_VERSION (7, 45, 0) */ 1449 (CURLE_OK != curl_easy_setopt (c, CURLOPT_PORT, ((long) port)))) 1450 libcurlErrorExitDesc ("curl_easy_setopt() failed"); 1451 1452 if (CURLE_OK != 1453 curl_easy_setopt (c, CURLOPT_URL, 1454 URL_SCHEME_HOST EXPECTED_URI_BASE_PATH)) 1455 libcurlErrorExitDesc ("Cannot set request URL"); 1456 1457 return c; 1458 } 1459 1460 1461 static CURLcode 1462 performQueryExternal (struct MHD_Daemon *d, CURL *c, CURLM **multi_reuse) 1463 { 1464 CURLM *multi; 1465 time_t start; 1466 struct timeval tv; 1467 CURLcode ret; 1468 1469 ret = CURLE_FAILED_INIT; /* will be replaced with real result */ 1470 if (NULL != *multi_reuse) 1471 multi = *multi_reuse; 1472 else 1473 { 1474 multi = curl_multi_init (); 1475 if (multi == NULL) 1476 libcurlErrorExitDesc ("curl_multi_init() failed"); 1477 *multi_reuse = multi; 1478 } 1479 if (CURLM_OK != curl_multi_add_handle (multi, c)) 1480 libcurlErrorExitDesc ("curl_multi_add_handle() failed"); 1481 1482 start = time (NULL); 1483 while (time (NULL) - start <= TIMEOUTS_VAL) 1484 { 1485 fd_set rs; 1486 fd_set ws; 1487 fd_set es; 1488 MHD_socket maxMhdSk; 1489 int maxCurlSk; 1490 int running; 1491 1492 maxMhdSk = MHD_INVALID_SOCKET; 1493 maxCurlSk = -1; 1494 FD_ZERO (&rs); 1495 FD_ZERO (&ws); 1496 FD_ZERO (&es); 1497 if (NULL != multi) 1498 { 1499 curl_multi_perform (multi, &running); 1500 if (0 == running) 1501 { 1502 struct CURLMsg *msg; 1503 int msgLeft; 1504 int totalMsgs = 0; 1505 do 1506 { 1507 msg = curl_multi_info_read (multi, &msgLeft); 1508 if (NULL == msg) 1509 libcurlErrorExitDesc ("curl_multi_info_read() failed"); 1510 totalMsgs++; 1511 if (CURLMSG_DONE == msg->msg) 1512 ret = msg->data.result; 1513 } while (msgLeft > 0); 1514 if (1 != totalMsgs) 1515 { 1516 fprintf (stderr, 1517 "curl_multi_info_read returned wrong " 1518 "number of results (%d).\n", 1519 totalMsgs); 1520 externalErrorExit (); 1521 } 1522 curl_multi_remove_handle (multi, c); 1523 multi = NULL; 1524 } 1525 else 1526 { 1527 if (CURLM_OK != curl_multi_fdset (multi, &rs, &ws, &es, &maxCurlSk)) 1528 libcurlErrorExitDesc ("curl_multi_fdset() failed"); 1529 } 1530 } 1531 if (NULL == multi) 1532 { /* libcurl has finished, check whether MHD still needs to perform cleanup */ 1533 if (0 != MHD_get_timeout64s (d)) 1534 break; /* MHD finished as well */ 1535 } 1536 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxMhdSk)) 1537 mhdErrorExitDesc ("MHD_get_fdset() failed"); 1538 tv.tv_sec = 0; 1539 tv.tv_usec = 200000; 1540 if (0 == MHD_get_timeout64s (d)) 1541 tv.tv_usec = 0; 1542 else 1543 { 1544 long curl_to = -1; 1545 curl_multi_timeout (multi, &curl_to); 1546 if (0 == curl_to) 1547 tv.tv_usec = 0; 1548 } 1549 #ifdef MHD_POSIX_SOCKETS 1550 if (maxMhdSk > maxCurlSk) 1551 maxCurlSk = maxMhdSk; 1552 #endif /* MHD_POSIX_SOCKETS */ 1553 if (-1 == select (maxCurlSk + 1, &rs, &ws, &es, &tv)) 1554 { 1555 #ifdef MHD_POSIX_SOCKETS 1556 if (EINTR != errno) 1557 externalErrorExitDesc ("Unexpected select() error"); 1558 #else 1559 if ((WSAEINVAL != WSAGetLastError ()) || 1560 (0 != rs.fd_count) || (0 != ws.fd_count) || (0 != es.fd_count) ) 1561 externalErrorExitDesc ("Unexpected select() error"); 1562 Sleep ((unsigned long) tv.tv_usec / 1000); 1563 #endif 1564 } 1565 if (MHD_YES != MHD_run_from_select (d, &rs, &ws, &es)) 1566 mhdErrorExitDesc ("MHD_run_from_select() failed"); 1567 } 1568 1569 return ret; 1570 } 1571 1572 1573 /** 1574 * Check request result 1575 * @param curl_code the CURL easy return code 1576 * @param pcbc the pointer struct CBC 1577 * @return non-zero if success, zero if failed 1578 */ 1579 static unsigned int 1580 check_result (CURLcode curl_code, CURL *c, long expected_code, 1581 struct CBC *pcbc) 1582 { 1583 long code; 1584 1585 if (CURLE_OK != curl_code) 1586 { 1587 fflush (stdout); 1588 if (0 != libcurl_errbuf[0]) 1589 fprintf (stderr, "Request failed. " 1590 "libcurl error: '%s'.\n" 1591 "libcurl error description: '%s'.\n", 1592 curl_easy_strerror (curl_code), 1593 libcurl_errbuf); 1594 else 1595 fprintf (stderr, "Request failed. " 1596 "libcurl error: '%s'.\n", 1597 curl_easy_strerror (curl_code)); 1598 fflush (stderr); 1599 return 0; 1600 } 1601 1602 if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code)) 1603 libcurlErrorExit (); 1604 1605 if (expected_code != code) 1606 { 1607 fprintf (stderr, "### The response has wrong HTTP code: %ld\t" 1608 "Expected: %ld.\n", 1609 code, expected_code); 1610 return 0; 1611 } 1612 else if (verbose) 1613 printf ("### The response has expected HTTP code: %ld\n", expected_code); 1614 1615 if (pcbc->pos != MHD_STATICSTR_LEN_ (PAGE)) 1616 { 1617 fprintf (stderr, "Got %u bytes ('%.*s'), expected %u bytes. ", 1618 (unsigned) pcbc->pos, (int) pcbc->pos, pcbc->buf, 1619 (unsigned) MHD_STATICSTR_LEN_ (PAGE)); 1620 mhdErrorExitDesc ("Wrong returned data length"); 1621 } 1622 if (0 != memcmp (PAGE, pcbc->buf, pcbc->pos)) 1623 { 1624 fprintf (stderr, "Got invalid response '%.*s'. ", 1625 (int) pcbc->pos, pcbc->buf); 1626 mhdErrorExitDesc ("Wrong returned data"); 1627 } 1628 fflush (stderr); 1629 fflush (stdout); 1630 1631 return 1; 1632 } 1633 1634 1635 static unsigned int 1636 testExternalPolling (void) 1637 { 1638 struct MHD_Daemon *d; 1639 uint16_t port; 1640 struct CBC cbc; 1641 struct ahc_cls_type ahc_param; 1642 char buf[2048]; 1643 CURL *c; 1644 CURLM *multi_reuse; 1645 size_t i; 1646 int failed = 0; 1647 1648 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 1649 port = 0; 1650 else 1651 port = 1340 + oneone ? 0 : 6 + (uint16_t) (1 + discp_level); 1652 1653 d = MHD_start_daemon (MHD_USE_ERROR_LOG | MHD_USE_NO_THREAD_SAFETY, 1654 port, NULL, NULL, 1655 &ahcCheck, &ahc_param, 1656 MHD_OPTION_CLIENT_DISCIPLINE_LVL, 1657 (int) (discp_level), 1658 MHD_OPTION_APP_FD_SETSIZE, (int) FD_SETSIZE, 1659 MHD_OPTION_END); 1660 if (d == NULL) 1661 return 1; 1662 if (0 == port) 1663 { 1664 const union MHD_DaemonInfo *dinfo; 1665 1666 dinfo = MHD_get_daemon_info (d, 1667 MHD_DAEMON_INFO_BIND_PORT); 1668 if ( (NULL == dinfo) || 1669 (0 == dinfo->port) ) 1670 mhdErrorExitDesc ("MHD_get_daemon_info() failed"); 1671 port = dinfo->port; 1672 } 1673 1674 ahc_param.rq_method = MHD_HTTP_METHOD_GET; 1675 ahc_param.rq_url = EXPECTED_URI_BASE_PATH; 1676 cbc.buf = buf; 1677 cbc.size = sizeof (buf); 1678 memset (cbc.buf, 0, cbc.size); 1679 c = setupCURL (&cbc, port); 1680 multi_reuse = NULL; 1681 for (i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i) 1682 { 1683 cbc.pos = 0; 1684 ahc_param.check = test_data + i; 1685 if (CURLE_OK != 1686 curl_easy_setopt (c, CURLOPT_COOKIE, 1687 ahc_param.check->header_str)) 1688 libcurlErrorExitDesc ("Cannot set request cookies"); 1689 1690 if (check_result (performQueryExternal (d, c, &multi_reuse), c, 1691 MHD_HTTP_OK, &cbc)) 1692 { 1693 if (verbose) 1694 printf ("### Got expected response for the check at line %u.\n", 1695 test_data[i].line_num); 1696 fflush (stdout); 1697 } 1698 else 1699 { 1700 fprintf (stderr, "### FAILED request for the check at line %u.\n", 1701 test_data[i].line_num); 1702 fflush (stderr); 1703 failed = 1; 1704 } 1705 } 1706 1707 curl_easy_cleanup (c); 1708 if (NULL != multi_reuse) 1709 curl_multi_cleanup (multi_reuse); 1710 1711 MHD_stop_daemon (d); 1712 return failed ? 1 : 0; 1713 } 1714 1715 1716 int 1717 main (int argc, char *const *argv) 1718 { 1719 unsigned int errorCount = 0; 1720 1721 /* Test type and test parameters */ 1722 verbose = ! (has_param (argc, argv, "-q") || 1723 has_param (argc, argv, "--quiet") || 1724 has_param (argc, argv, "-s") || 1725 has_param (argc, argv, "--silent")); 1726 oneone = ! has_in_name (argv[0], "10"); 1727 use_discp_n3 = has_in_name (argv[0], "_discp_n3"); 1728 use_discp_n2 = has_in_name (argv[0], "_discp_n2"); 1729 use_discp_zero = has_in_name (argv[0], "_discp_zero"); 1730 use_discp_p1 = has_in_name (argv[0], "_discp_p1"); 1731 use_discp_p2 = has_in_name (argv[0], "_discp_p2"); 1732 if (1 != ((use_discp_n3 ? 1 : 0) + (use_discp_n2 ? 1 : 0) 1733 + (use_discp_zero ? 1 : 0) 1734 + (use_discp_p1 ? 1 : 0) + (use_discp_p2 ? 1 : 0))) 1735 return 99; 1736 1737 if (use_discp_n3) 1738 discp_level = -3; 1739 else if (use_discp_n2) 1740 discp_level = -2; 1741 else if (use_discp_zero) 1742 discp_level = 0; 1743 else if (use_discp_p1) 1744 discp_level = 1; 1745 else if (use_discp_p2) 1746 discp_level = 2; 1747 1748 test_global_init (); 1749 1750 errorCount += testExternalPolling (); 1751 if (errorCount != 0) 1752 fprintf (stderr, "Error (code: %u)\n", errorCount); 1753 1754 test_global_cleanup (); 1755 1756 return (0 == errorCount) ? 0 : 1; /* 0 == pass */ 1757 }