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