| OLD | NEW |
| 1 /* | 1 /* |
| 2 * nanohttp.c: minimalist HTTP GET implementation to fetch external subsets. | 2 * nanohttp.c: minimalist HTTP GET implementation to fetch external subsets. |
| 3 * focuses on size, streamability, reentrancy and portability | 3 * focuses on size, streamability, reentrancy and portability |
| 4 * | 4 * |
| 5 * This is clearly not a general purpose HTTP implementation | 5 * This is clearly not a general purpose HTTP implementation |
| 6 * If you look for one, check: | 6 * If you look for one, check: |
| 7 * http://www.w3.org/Library/ | 7 * http://www.w3.org/Library/ |
| 8 * | 8 * |
| 9 * See Copyright for the status of this software. | 9 * See Copyright for the status of this software. |
| 10 * | 10 * |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 #endif | 47 #endif |
| 48 #ifdef HAVE_FCNTL_H | 48 #ifdef HAVE_FCNTL_H |
| 49 #include <fcntl.h> | 49 #include <fcntl.h> |
| 50 #endif | 50 #endif |
| 51 #ifdef HAVE_ERRNO_H | 51 #ifdef HAVE_ERRNO_H |
| 52 #include <errno.h> | 52 #include <errno.h> |
| 53 #endif | 53 #endif |
| 54 #ifdef HAVE_SYS_TIME_H | 54 #ifdef HAVE_SYS_TIME_H |
| 55 #include <sys/time.h> | 55 #include <sys/time.h> |
| 56 #endif | 56 #endif |
| 57 #ifndef HAVE_POLL_H |
| 57 #ifdef HAVE_SYS_SELECT_H | 58 #ifdef HAVE_SYS_SELECT_H |
| 58 #include <sys/select.h> | 59 #include <sys/select.h> |
| 59 #endif | 60 #endif |
| 61 #else |
| 62 #include <poll.h> |
| 63 #endif |
| 60 #ifdef HAVE_STRINGS_H | 64 #ifdef HAVE_STRINGS_H |
| 61 #include <strings.h> | 65 #include <strings.h> |
| 62 #endif | 66 #endif |
| 63 #ifdef SUPPORT_IP6 | 67 #ifdef SUPPORT_IP6 |
| 64 #include <resolv.h> | 68 #include <resolv.h> |
| 65 #endif | 69 #endif |
| 66 #ifdef HAVE_ZLIB_H | 70 #ifdef HAVE_ZLIB_H |
| 67 #include <zlib.h> | 71 #include <zlib.h> |
| 68 #endif | 72 #endif |
| 69 | 73 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 88 #include <libxml/xmlmemory.h> | 92 #include <libxml/xmlmemory.h> |
| 89 #include <libxml/parser.h> /* for xmlStr(n)casecmp() */ | 93 #include <libxml/parser.h> /* for xmlStr(n)casecmp() */ |
| 90 #include <libxml/nanohttp.h> | 94 #include <libxml/nanohttp.h> |
| 91 #include <libxml/globals.h> | 95 #include <libxml/globals.h> |
| 92 #include <libxml/uri.h> | 96 #include <libxml/uri.h> |
| 93 | 97 |
| 94 /** | 98 /** |
| 95 * A couple portability macros | 99 * A couple portability macros |
| 96 */ | 100 */ |
| 97 #ifndef _WINSOCKAPI_ | 101 #ifndef _WINSOCKAPI_ |
| 98 #ifndef __BEOS__ | 102 #if !defined(__BEOS__) || defined(__HAIKU__) |
| 99 #define closesocket(s) close(s) | 103 #define closesocket(s) close(s) |
| 100 #endif | 104 #endif |
| 101 #define SOCKET int | 105 #define SOCKET int |
| 102 #endif | 106 #endif |
| 103 | 107 |
| 104 #ifdef __BEOS__ | 108 #ifdef __BEOS__ |
| 105 #ifndef PF_INET | 109 #ifndef PF_INET |
| 106 #define PF_INET AF_INET | 110 #define PF_INET AF_INET |
| 107 #endif | 111 #endif |
| 108 #endif | 112 #endif |
| (...skipping 30 matching lines...) Expand all Loading... |
| 139 int state; /* WRITE / READ / CLOSED */ | 143 int state; /* WRITE / READ / CLOSED */ |
| 140 char *out; /* buffer sent (zero terminated) */ | 144 char *out; /* buffer sent (zero terminated) */ |
| 141 char *outptr; /* index within the buffer sent */ | 145 char *outptr; /* index within the buffer sent */ |
| 142 char *in; /* the receiving buffer */ | 146 char *in; /* the receiving buffer */ |
| 143 char *content; /* the start of the content */ | 147 char *content; /* the start of the content */ |
| 144 char *inptr; /* the next byte to read from network */ | 148 char *inptr; /* the next byte to read from network */ |
| 145 char *inrptr; /* the next byte to give back to the client */ | 149 char *inrptr; /* the next byte to give back to the client */ |
| 146 int inlen; /* len of the input buffer */ | 150 int inlen; /* len of the input buffer */ |
| 147 int last; /* return code for last operation */ | 151 int last; /* return code for last operation */ |
| 148 int returnValue; /* the protocol return value */ | 152 int returnValue; /* the protocol return value */ |
| 153 int version; /* the protocol version */ |
| 149 int ContentLength; /* specified content length from HTTP header */ | 154 int ContentLength; /* specified content length from HTTP header */ |
| 150 char *contentType; /* the MIME type for the input */ | 155 char *contentType; /* the MIME type for the input */ |
| 151 char *location; /* the new URL in case of redirect */ | 156 char *location; /* the new URL in case of redirect */ |
| 152 char *authHeader; /* contents of {WWW,Proxy}-Authenticate header */ | 157 char *authHeader; /* contents of {WWW,Proxy}-Authenticate header */ |
| 153 char *encoding; /* encoding extracted from the contentType */ | 158 char *encoding; /* encoding extracted from the contentType */ |
| 154 char *mimeType; /* Mime-Type extracted from the contentType */ | 159 char *mimeType; /* Mime-Type extracted from the contentType */ |
| 155 #ifdef HAVE_ZLIB_H | 160 #ifdef HAVE_ZLIB_H |
| 156 z_stream *strm; /* Zlib stream object */ | 161 z_stream *strm; /* Zlib stream object */ |
| 157 int usesGzip; /* "Content-Encoding: gzip" was detected */ | 162 int usesGzip; /* "Content-Encoding: gzip" was detected */ |
| 158 #endif | 163 #endif |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 | 437 |
| 433 /** | 438 /** |
| 434 * xmlNanoHTTPSend: | 439 * xmlNanoHTTPSend: |
| 435 * @ctxt: an HTTP context | 440 * @ctxt: an HTTP context |
| 436 * | 441 * |
| 437 * Send the input needed to initiate the processing on the server side | 442 * Send the input needed to initiate the processing on the server side |
| 438 * Returns number of bytes sent or -1 on error. | 443 * Returns number of bytes sent or -1 on error. |
| 439 */ | 444 */ |
| 440 | 445 |
| 441 static int | 446 static int |
| 442 xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char * xmt_ptr, int outlen) { | 447 xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char *xmt_ptr, int outlen) |
| 448 { |
| 449 int total_sent = 0; |
| 450 #ifdef HAVE_POLL_H |
| 451 struct pollfd p; |
| 452 #else |
| 453 struct timeval tv; |
| 454 fd_set wfd; |
| 455 #endif |
| 443 | 456 |
| 444 int » total_sent = 0; | 457 if ((ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL)) { |
| 445 | |
| 446 if ( (ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL ) ) { | |
| 447 while (total_sent < outlen) { | 458 while (total_sent < outlen) { |
| 448 int nsent = send(ctxt->fd, xmt_ptr + total_sent, | 459 int nsent = send(ctxt->fd, xmt_ptr + total_sent, |
| 449 outlen - total_sent, 0); | 460 outlen - total_sent, 0); |
| 450 if (nsent>0) | 461 |
| 462 if (nsent > 0) |
| 451 total_sent += nsent; | 463 total_sent += nsent; |
| 452 » else if ( ( nsent == -1 ) && | 464 else if ((nsent == -1) && |
| 453 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK | 465 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK |
| 454 » » ( socket_errno( ) != EAGAIN ) && | 466 (socket_errno() != EAGAIN) && |
| 455 #endif | 467 #endif |
| 456 » » ( socket_errno( ) != EWOULDBLOCK ) ) { | 468 (socket_errno() != EWOULDBLOCK)) { |
| 457 » » __xmlIOErr(XML_FROM_HTTP, 0, "send failed\n"); | 469 __xmlIOErr(XML_FROM_HTTP, 0, "send failed\n"); |
| 458 » » if ( total_sent == 0 ) | 470 if (total_sent == 0) |
| 459 » » total_sent = -1; | 471 total_sent = -1; |
| 460 » » break; | 472 break; |
| 461 » } | 473 } else { |
| 462 » else { | 474 /* |
| 463 » /* | 475 * No data sent |
| 464 » » ** No data sent | 476 * Since non-blocking sockets are used, wait for |
| 465 » » ** Since non-blocking sockets are used, wait for | 477 * socket to be writable or default timeout prior |
| 466 » » ** socket to be writable or default timeout prior | 478 * to retrying. |
| 467 » » ** to retrying. | 479 */ |
| 468 » » */ | 480 #ifndef HAVE_POLL_H |
| 481 #ifndef _WINSOCKAPI_ |
| 482 if (ctxt->fd > FD_SETSIZE) |
| 483 return -1; |
| 484 #endif |
| 469 | 485 |
| 470 » » struct timeval» tv; | 486 tv.tv_sec = timeout; |
| 471 » » fd_set» » wfd; | 487 tv.tv_usec = 0; |
| 472 | 488 FD_ZERO(&wfd); |
| 473 » » tv.tv_sec = timeout; | |
| 474 » » tv.tv_usec = 0; | |
| 475 » » FD_ZERO( &wfd ); | |
| 476 #ifdef _MSC_VER | 489 #ifdef _MSC_VER |
| 477 #pragma warning(push) | 490 #pragma warning(push) |
| 478 #pragma warning(disable: 4018) | 491 #pragma warning(disable: 4018) |
| 479 #endif | 492 #endif |
| 480 » » FD_SET( ctxt->fd, &wfd ); | 493 FD_SET(ctxt->fd, &wfd); |
| 481 #ifdef _MSC_VER | 494 #ifdef _MSC_VER |
| 482 #pragma warning(pop) | 495 #pragma warning(pop) |
| 483 #endif | 496 #endif |
| 484 » » (void)select( ctxt->fd + 1, NULL, &wfd, NULL, &tv ); | 497 (void) select(ctxt->fd + 1, NULL, &wfd, NULL, &tv); |
| 485 » } | 498 #else |
| 486 » } | 499 p.fd = ctxt->fd; |
| 500 p.events = POLLOUT; |
| 501 (void) poll(&p, 1, timeout * 1000); |
| 502 #endif /* !HAVE_POLL_H */ |
| 503 } |
| 504 } |
| 487 } | 505 } |
| 488 | 506 |
| 489 return total_sent; | 507 return total_sent; |
| 490 } | 508 } |
| 491 | 509 |
| 492 /** | 510 /** |
| 493 * xmlNanoHTTPRecv: | 511 * xmlNanoHTTPRecv: |
| 494 * @ctxt: an HTTP context | 512 * @ctxt: an HTTP context |
| 495 * | 513 * |
| 496 * Read information coming from the HTTP connection. | 514 * Read information coming from the HTTP connection. |
| 497 * This is a blocking call (but it blocks in select(), not read()). | 515 * This is a blocking call (but it blocks in select(), not read()). |
| 498 * | 516 * |
| 499 * Returns the number of byte read or -1 in case of error. | 517 * Returns the number of byte read or -1 in case of error. |
| 500 */ | 518 */ |
| 501 | 519 |
| 502 static int | 520 static int |
| 503 xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) { | 521 xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) |
| 522 { |
| 523 #ifdef HAVE_POLL_H |
| 524 struct pollfd p; |
| 525 #else |
| 504 fd_set rfd; | 526 fd_set rfd; |
| 505 struct timeval tv; | 527 struct timeval tv; |
| 528 #endif |
| 506 | 529 |
| 507 | 530 |
| 508 while (ctxt->state & XML_NANO_HTTP_READ) { | 531 while (ctxt->state & XML_NANO_HTTP_READ) { |
| 509 » if (ctxt->in == NULL) { | 532 if (ctxt->in == NULL) { |
| 510 » ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char)); | 533 ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char)); |
| 511 » if (ctxt->in == NULL) { | 534 if (ctxt->in == NULL) { |
| 512 » » xmlHTTPErrMemory("allocating input"); | 535 xmlHTTPErrMemory("allocating input"); |
| 513 » ctxt->last = -1; | 536 ctxt->last = -1; |
| 514 » » return(-1); | 537 return (-1); |
| 515 » } | 538 } |
| 516 » ctxt->inlen = 65000; | 539 ctxt->inlen = 65000; |
| 517 » ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in; | 540 ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in; |
| 518 » } | 541 } |
| 519 » if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) { | 542 if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) { |
| 520 » int delta = ctxt->inrptr - ctxt->in; | 543 int delta = ctxt->inrptr - ctxt->in; |
| 521 » int len = ctxt->inptr - ctxt->inrptr; | 544 int len = ctxt->inptr - ctxt->inrptr; |
| 522 » | 545 |
| 523 » memmove(ctxt->in, ctxt->inrptr, len); | 546 memmove(ctxt->in, ctxt->inrptr, len); |
| 524 » ctxt->inrptr -= delta; | 547 ctxt->inrptr -= delta; |
| 525 » ctxt->content -= delta; | 548 ctxt->content -= delta; |
| 526 » ctxt->inptr -= delta; | 549 ctxt->inptr -= delta; |
| 527 » } | 550 } |
| 528 if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) { | 551 if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) { |
| 529 » int d_inptr = ctxt->inptr - ctxt->in; | 552 int d_inptr = ctxt->inptr - ctxt->in; |
| 530 » int d_content = ctxt->content - ctxt->in; | 553 int d_content = ctxt->content - ctxt->in; |
| 531 » int d_inrptr = ctxt->inrptr - ctxt->in; | 554 int d_inrptr = ctxt->inrptr - ctxt->in; |
| 532 » char *» tmp_ptr = ctxt->in; | 555 char *tmp_ptr = ctxt->in; |
| 533 | 556 |
| 534 » ctxt->inlen *= 2; | 557 ctxt->inlen *= 2; |
| 535 ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen); | 558 ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen); |
| 536 » if (ctxt->in == NULL) { | 559 if (ctxt->in == NULL) { |
| 537 » » xmlHTTPErrMemory("allocating input buffer"); | 560 xmlHTTPErrMemory("allocating input buffer"); |
| 538 » » xmlFree( tmp_ptr ); | 561 xmlFree(tmp_ptr); |
| 539 » ctxt->last = -1; | 562 ctxt->last = -1; |
| 540 » » return(-1); | 563 return (-1); |
| 541 » } | 564 } |
| 542 ctxt->inptr = ctxt->in + d_inptr; | 565 ctxt->inptr = ctxt->in + d_inptr; |
| 543 ctxt->content = ctxt->in + d_content; | 566 ctxt->content = ctxt->in + d_content; |
| 544 ctxt->inrptr = ctxt->in + d_inrptr; | 567 ctxt->inrptr = ctxt->in + d_inrptr; |
| 545 » } | 568 } |
| 546 » ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0); | 569 ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0); |
| 547 » if (ctxt->last > 0) { | 570 if (ctxt->last > 0) { |
| 548 » ctxt->inptr += ctxt->last; | 571 ctxt->inptr += ctxt->last; |
| 549 » return(ctxt->last); | 572 return (ctxt->last); |
| 550 » } | 573 } |
| 551 » if (ctxt->last == 0) { | 574 if (ctxt->last == 0) { |
| 552 » return(0); | 575 return (0); |
| 553 » } | 576 } |
| 554 » if (ctxt->last == -1) { | 577 if (ctxt->last == -1) { |
| 555 » switch (socket_errno()) { | 578 switch (socket_errno()) { |
| 556 » » case EINPROGRESS: | 579 case EINPROGRESS: |
| 557 » » case EWOULDBLOCK: | 580 case EWOULDBLOCK: |
| 558 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK | 581 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK |
| 559 » » case EAGAIN: | 582 case EAGAIN: |
| 560 #endif | 583 #endif |
| 561 » » break; | 584 break; |
| 562 | 585 |
| 563 » » case ECONNRESET: | 586 case ECONNRESET: |
| 564 » » case ESHUTDOWN: | 587 case ESHUTDOWN: |
| 565 » » return ( 0 ); | 588 return (0); |
| 566 | 589 |
| 567 » » default: | 590 default: |
| 568 » » __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n"); | 591 __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n"); |
| 569 » » return(-1); | 592 return (-1); |
| 570 » } | 593 } |
| 571 » } | 594 } |
| 595 #ifdef HAVE_POLL_H |
| 596 p.fd = ctxt->fd; |
| 597 p.events = POLLIN; |
| 598 if ((poll(&p, 1, timeout * 1000) < 1) |
| 599 #if defined(EINTR) |
| 600 && (errno != EINTR) |
| 601 #endif |
| 602 ) |
| 603 return (0); |
| 604 #else /* !HAVE_POLL_H */ |
| 605 #ifndef _WINSOCKAPI_ |
| 606 if (ctxt->fd > FD_SETSIZE) |
| 607 return 0; |
| 608 #endif |
| 572 | 609 |
| 573 » tv.tv_sec = timeout; | 610 tv.tv_sec = timeout; |
| 574 » tv.tv_usec = 0; | 611 tv.tv_usec = 0; |
| 575 » FD_ZERO(&rfd); | 612 FD_ZERO(&rfd); |
| 613 |
| 576 #ifdef _MSC_VER | 614 #ifdef _MSC_VER |
| 577 #pragma warning(push) | 615 #pragma warning(push) |
| 578 #pragma warning(disable: 4018) | 616 #pragma warning(disable: 4018) |
| 579 #endif | 617 #endif |
| 580 » FD_SET(ctxt->fd, &rfd); | 618 |
| 619 FD_SET(ctxt->fd, &rfd); |
| 620 |
| 581 #ifdef _MSC_VER | 621 #ifdef _MSC_VER |
| 582 #pragma warning(pop) | 622 #pragma warning(pop) |
| 583 #endif | 623 #endif |
| 584 » | 624 |
| 585 » if ( (select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1) | 625 if ((select(ctxt->fd + 1, &rfd, NULL, NULL, &tv) < 1) |
| 586 #if defined(EINTR) | 626 #if defined(EINTR) |
| 587 » » && (errno != EINTR) | 627 && (errno != EINTR) |
| 588 #endif | 628 #endif |
| 589 » ) | 629 ) |
| 590 » » return(0); | 630 return (0); |
| 631 #endif /* !HAVE_POLL_H */ |
| 591 } | 632 } |
| 592 return(0); | 633 return (0); |
| 593 } | 634 } |
| 594 | 635 |
| 595 /** | 636 /** |
| 596 * xmlNanoHTTPReadLine: | 637 * xmlNanoHTTPReadLine: |
| 597 * @ctxt: an HTTP context | 638 * @ctxt: an HTTP context |
| 598 * | 639 * |
| 599 * Read one line in the HTTP server output, usually for extracting | 640 * Read one line in the HTTP server output, usually for extracting |
| 600 * the HTTP protocol informations from the answer header. | 641 * the HTTP protocol informations from the answer header. |
| 601 * | 642 * |
| 602 * Returns a newly allocated string with a copy of the line, or NULL | 643 * Returns a newly allocated string with a copy of the line, or NULL |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 if ((*cur != ' ') && (*cur != '\t')) return; | 720 if ((*cur != ' ') && (*cur != '\t')) return; |
| 680 while ((*cur == ' ') || (*cur == '\t')) cur++; | 721 while ((*cur == ' ') || (*cur == '\t')) cur++; |
| 681 if ((*cur < '0') || (*cur > '9')) return; | 722 if ((*cur < '0') || (*cur > '9')) return; |
| 682 while ((*cur >= '0') && (*cur <= '9')) { | 723 while ((*cur >= '0') && (*cur <= '9')) { |
| 683 ret *= 10; | 724 ret *= 10; |
| 684 ret += *cur - '0'; | 725 ret += *cur - '0'; |
| 685 cur++; | 726 cur++; |
| 686 } | 727 } |
| 687 if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return; | 728 if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return; |
| 688 ctxt->returnValue = ret; | 729 ctxt->returnValue = ret; |
| 730 ctxt->version = version; |
| 689 } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Content-Type:", 13)) { | 731 } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Content-Type:", 13)) { |
| 690 const xmlChar *charset, *last, *mime; | 732 const xmlChar *charset, *last, *mime; |
| 691 cur += 13; | 733 cur += 13; |
| 692 while ((*cur == ' ') || (*cur == '\t')) cur++; | 734 while ((*cur == ' ') || (*cur == '\t')) cur++; |
| 693 if (ctxt->contentType != NULL) | 735 if (ctxt->contentType != NULL) |
| 694 xmlFree(ctxt->contentType); | 736 xmlFree(ctxt->contentType); |
| 695 ctxt->contentType = xmlMemStrdup(cur); | 737 ctxt->contentType = xmlMemStrdup(cur); |
| 696 mime = (const xmlChar *) cur; | 738 mime = (const xmlChar *) cur; |
| 697 last = mime; | 739 last = mime; |
| 698 while ((*last != 0) && (*last != ' ') && (*last != '\t') && | 740 while ((*last != 0) && (*last != ' ') && (*last != '\t') && |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 * Attempt a connection to the given IP:port endpoint. It forces | 838 * Attempt a connection to the given IP:port endpoint. It forces |
| 797 * non-blocking semantic on the socket, and allow 60 seconds for | 839 * non-blocking semantic on the socket, and allow 60 seconds for |
| 798 * the host to answer. | 840 * the host to answer. |
| 799 * | 841 * |
| 800 * Returns -1 in case of failure, the file descriptor number otherwise | 842 * Returns -1 in case of failure, the file descriptor number otherwise |
| 801 */ | 843 */ |
| 802 | 844 |
| 803 static int | 845 static int |
| 804 xmlNanoHTTPConnectAttempt(struct sockaddr *addr) | 846 xmlNanoHTTPConnectAttempt(struct sockaddr *addr) |
| 805 { | 847 { |
| 848 #ifndef HAVE_POLL_H |
| 806 fd_set wfd; | 849 fd_set wfd; |
| 807 #ifdef _WINSOCKAPI_ | 850 #ifdef _WINSOCKAPI_ |
| 808 fd_set xfd; | 851 fd_set xfd; |
| 809 #endif | 852 #endif |
| 810 struct timeval tv; | 853 struct timeval tv; |
| 854 #else /* !HAVE_POLL_H */ |
| 855 struct pollfd p; |
| 856 #endif /* !HAVE_POLL_H */ |
| 811 int status; | 857 int status; |
| 858 |
| 812 int addrlen; | 859 int addrlen; |
| 860 |
| 813 SOCKET s; | 861 SOCKET s; |
| 814 | 862 |
| 815 #ifdef SUPPORT_IP6 | 863 #ifdef SUPPORT_IP6 |
| 816 if (addr->sa_family == AF_INET6) { | 864 if (addr->sa_family == AF_INET6) { |
| 817 » s = socket (PF_INET6, SOCK_STREAM, IPPROTO_TCP); | 865 s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); |
| 818 » addrlen = sizeof (struct sockaddr_in6); | 866 addrlen = sizeof(struct sockaddr_in6); |
| 819 } | 867 } else |
| 820 else | |
| 821 #endif | 868 #endif |
| 822 { | 869 { |
| 823 » s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); | 870 s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); |
| 824 » addrlen = sizeof (struct sockaddr_in); | 871 addrlen = sizeof(struct sockaddr_in); |
| 825 } | 872 } |
| 826 if (s==-1) { | 873 if (s == -1) { |
| 827 #ifdef DEBUG_HTTP | 874 #ifdef DEBUG_HTTP |
| 828 » perror("socket"); | 875 perror("socket"); |
| 829 #endif | 876 #endif |
| 830 » __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n"); | 877 __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n"); |
| 831 » return(-1); | 878 return (-1); |
| 832 } | 879 } |
| 833 | |
| 834 #ifdef _WINSOCKAPI_ | 880 #ifdef _WINSOCKAPI_ |
| 835 { | 881 { |
| 836 » u_long one = 1; | 882 u_long one = 1; |
| 837 | 883 |
| 838 » status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0; | 884 status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0; |
| 839 } | 885 } |
| 840 #else /* _WINSOCKAPI_ */ | 886 #else /* _WINSOCKAPI_ */ |
| 841 #if defined(VMS) | 887 #if defined(VMS) |
| 842 { | 888 { |
| 843 » int enable = 1; | 889 int enable = 1; |
| 844 » status = ioctl(s, FIONBIO, &enable); | 890 |
| 891 status = ioctl(s, FIONBIO, &enable); |
| 845 } | 892 } |
| 846 #else /* VMS */ | 893 #else /* VMS */ |
| 847 #if defined(__BEOS__) | 894 #if defined(__BEOS__) && !defined(__HAIKU__) |
| 848 » { | 895 { |
| 849 » » bool noblock = true; | 896 bool noblock = true; |
| 850 » » status = setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock, sizeof
(noblock)); | 897 |
| 851 » } | 898 status = |
| 899 setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock, |
| 900 sizeof(noblock)); |
| 901 } |
| 852 #else /* __BEOS__ */ | 902 #else /* __BEOS__ */ |
| 853 if ((status = fcntl(s, F_GETFL, 0)) != -1) { | 903 if ((status = fcntl(s, F_GETFL, 0)) != -1) { |
| 854 #ifdef O_NONBLOCK | 904 #ifdef O_NONBLOCK |
| 855 » status |= O_NONBLOCK; | 905 status |= O_NONBLOCK; |
| 856 #else /* O_NONBLOCK */ | 906 #else /* O_NONBLOCK */ |
| 857 #ifdef F_NDELAY | 907 #ifdef F_NDELAY |
| 858 » status |= F_NDELAY; | 908 status |= F_NDELAY; |
| 859 #endif /* F_NDELAY */ | 909 #endif /* F_NDELAY */ |
| 860 #endif /* !O_NONBLOCK */ | 910 #endif /* !O_NONBLOCK */ |
| 861 » status = fcntl(s, F_SETFL, status); | 911 status = fcntl(s, F_SETFL, status); |
| 862 } | 912 } |
| 863 if (status < 0) { | 913 if (status < 0) { |
| 864 #ifdef DEBUG_HTTP | 914 #ifdef DEBUG_HTTP |
| 865 » perror("nonblocking"); | 915 perror("nonblocking"); |
| 866 #endif | 916 #endif |
| 867 » __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n"); | 917 __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n"); |
| 868 » closesocket(s); | 918 closesocket(s); |
| 869 » return(-1); | 919 return (-1); |
| 870 } | 920 } |
| 871 #endif /* !__BEOS__ */ | 921 #endif /* !__BEOS__ */ |
| 872 #endif /* !VMS */ | 922 #endif /* !VMS */ |
| 873 #endif /* !_WINSOCKAPI_ */ | 923 #endif /* !_WINSOCKAPI_ */ |
| 874 | 924 |
| 875 if (connect (s, addr, addrlen) == -1) { | 925 if (connect(s, addr, addrlen) == -1) { |
| 876 » switch (socket_errno()) { | 926 switch (socket_errno()) { |
| 877 » case EINPROGRESS: | 927 case EINPROGRESS: |
| 878 » case EWOULDBLOCK: | 928 case EWOULDBLOCK: |
| 879 » » break; | 929 break; |
| 880 » default: | 930 default: |
| 881 » » __xmlIOErr(XML_FROM_HTTP, 0, "error connecting to HTTP server"); | 931 __xmlIOErr(XML_FROM_HTTP, 0, |
| 882 » » closesocket(s); | 932 "error connecting to HTTP server"); |
| 883 » » return(-1); | 933 closesocket(s); |
| 884 » } | 934 return (-1); |
| 885 }» | 935 } |
| 886 | 936 } |
| 937 #ifndef HAVE_POLL_H |
| 887 tv.tv_sec = timeout; | 938 tv.tv_sec = timeout; |
| 888 tv.tv_usec = 0; | 939 tv.tv_usec = 0; |
| 889 | 940 |
| 890 #ifdef _MSC_VER | 941 #ifdef _MSC_VER |
| 891 #pragma warning(push) | 942 #pragma warning(push) |
| 892 #pragma warning(disable: 4018) | 943 #pragma warning(disable: 4018) |
| 893 #endif | 944 #endif |
| 945 #ifndef _WINSOCKAPI_ |
| 946 if (s > FD_SETSIZE) |
| 947 return -1; |
| 948 #endif |
| 894 FD_ZERO(&wfd); | 949 FD_ZERO(&wfd); |
| 895 FD_SET(s, &wfd); | 950 FD_SET(s, &wfd); |
| 896 | 951 |
| 897 #ifdef _WINSOCKAPI_ | 952 #ifdef _WINSOCKAPI_ |
| 898 FD_ZERO(&xfd); | 953 FD_ZERO(&xfd); |
| 899 FD_SET(s, &xfd); | 954 FD_SET(s, &xfd); |
| 900 | 955 |
| 901 switch(select(s+1, NULL, &wfd, &xfd, &tv)) | 956 switch (select(s + 1, NULL, &wfd, &xfd, &tv)) |
| 902 #else | 957 #else |
| 903 switch(select(s+1, NULL, &wfd, NULL, &tv)) | 958 switch (select(s + 1, NULL, &wfd, NULL, &tv)) |
| 904 #endif | 959 #endif |
| 905 #ifdef _MSC_VER | 960 #ifdef _MSC_VER |
| 906 #pragma warning(pop) | 961 #pragma warning(pop) |
| 907 #endif | 962 #endif |
| 963 |
| 964 #else /* !HAVE_POLL_H */ |
| 965 p.fd = s; |
| 966 p.events = POLLOUT; |
| 967 switch (poll(&p, 1, timeout * 1000)) |
| 968 #endif /* !HAVE_POLL_H */ |
| 969 |
| 908 { | 970 { |
| 909 » case 0: | 971 case 0: |
| 910 » /* Time out */ | 972 /* Time out */ |
| 911 » __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out"); | 973 __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out"); |
| 912 » closesocket(s); | 974 closesocket(s); |
| 913 » return(-1); | 975 return (-1); |
| 914 » case -1: | 976 case -1: |
| 915 » /* Ermm.. ?? */ | 977 /* Ermm.. ?? */ |
| 916 » __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed"); | 978 __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed"); |
| 917 » closesocket(s); | 979 closesocket(s); |
| 918 » return(-1); | 980 return (-1); |
| 919 } | 981 } |
| 920 | 982 |
| 921 if ( FD_ISSET(s, &wfd) | 983 #ifndef HAVE_POLL_H |
| 984 if (FD_ISSET(s, &wfd) |
| 922 #ifdef _WINSOCKAPI_ | 985 #ifdef _WINSOCKAPI_ |
| 923 || FD_ISSET(s, &xfd) | 986 || FD_ISSET(s, &xfd) |
| 924 #endif | 987 #endif |
| 925 ) { | 988 ) |
| 926 » XML_SOCKLEN_T len; | 989 #else /* !HAVE_POLL_H */ |
| 927 » len = sizeof(status); | 990 if (p.revents == POLLOUT) |
| 991 #endif /* !HAVE_POLL_H */ |
| 992 { |
| 993 XML_SOCKLEN_T len; |
| 994 |
| 995 len = sizeof(status); |
| 928 #ifdef SO_ERROR | 996 #ifdef SO_ERROR |
| 929 » if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&status, &len) < 0 ) { | 997 if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &status, &len) < |
| 930 » /* Solaris error code */ | 998 0) { |
| 931 » __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n"); | 999 /* Solaris error code */ |
| 932 » return (-1); | 1000 __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n"); |
| 933 » } | 1001 return (-1); |
| 1002 } |
| 934 #endif | 1003 #endif |
| 935 » if ( status ) { | 1004 if (status) { |
| 936 » __xmlIOErr(XML_FROM_HTTP, 0, "Error connecting to remote host"); | 1005 __xmlIOErr(XML_FROM_HTTP, 0, |
| 937 » closesocket(s); | 1006 "Error connecting to remote host"); |
| 938 » errno = status; | 1007 closesocket(s); |
| 939 » return (-1); | 1008 errno = status; |
| 940 » } | 1009 return (-1); |
| 1010 } |
| 941 } else { | 1011 } else { |
| 942 » /* pbm */ | 1012 /* pbm */ |
| 943 » __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n"); | 1013 __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n"); |
| 944 » closesocket(s); | 1014 closesocket(s); |
| 945 » return (-1); | 1015 return (-1); |
| 946 } | 1016 } |
| 947 | 1017 |
| 948 return(s); | 1018 return (s); |
| 949 } | 1019 } |
| 950 | 1020 |
| 951 /** | 1021 /** |
| 952 * xmlNanoHTTPConnectHost: | 1022 * xmlNanoHTTPConnectHost: |
| 953 * @host: the host name | 1023 * @host: the host name |
| 954 * @port: the port number | 1024 * @port: the port number |
| 955 * | 1025 * |
| 956 * Attempt a connection to the given host:port endpoint. It tries | 1026 * Attempt a connection to the given host:port endpoint. It tries |
| 957 * the multiple IP provided by the DNS if available. | 1027 * the multiple IP provided by the DNS if available. |
| 958 * | 1028 * |
| 959 * Returns -1 in case of failure, the file descriptor number otherwise | 1029 * Returns -1 in case of failure, the file descriptor number otherwise |
| 960 */ | 1030 */ |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 * The contentType, or redir, if provided must be freed by the caller | 1336 * The contentType, or redir, if provided must be freed by the caller |
| 1267 */ | 1337 */ |
| 1268 | 1338 |
| 1269 void* | 1339 void* |
| 1270 xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input, | 1340 xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input, |
| 1271 char **contentType, char **redir, | 1341 char **contentType, char **redir, |
| 1272 const char *headers, int ilen ) { | 1342 const char *headers, int ilen ) { |
| 1273 xmlNanoHTTPCtxtPtr ctxt; | 1343 xmlNanoHTTPCtxtPtr ctxt; |
| 1274 char *bp, *p; | 1344 char *bp, *p; |
| 1275 int blen, ret; | 1345 int blen, ret; |
| 1276 int head; | |
| 1277 int nbRedirects = 0; | 1346 int nbRedirects = 0; |
| 1278 char *redirURL = NULL; | 1347 char *redirURL = NULL; |
| 1279 #ifdef DEBUG_HTTP | 1348 #ifdef DEBUG_HTTP |
| 1280 int xmt_bytes; | 1349 int xmt_bytes; |
| 1281 #endif | 1350 #endif |
| 1282 | 1351 |
| 1283 if (URL == NULL) return(NULL); | 1352 if (URL == NULL) return(NULL); |
| 1284 if (method == NULL) method = "GET"; | 1353 if (method == NULL) method = "GET"; |
| 1285 xmlNanoHTTPInit(); | 1354 xmlNanoHTTPInit(); |
| 1286 | 1355 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1428 "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", | 1497 "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", |
| 1429 xmt_bytes, ilen, | 1498 xmt_bytes, ilen, |
| 1430 "bytes of HTTP content sent to host", | 1499 "bytes of HTTP content sent to host", |
| 1431 ctxt->hostname ); | 1500 ctxt->hostname ); |
| 1432 #else | 1501 #else |
| 1433 xmlNanoHTTPSend( ctxt, input, ilen ); | 1502 xmlNanoHTTPSend( ctxt, input, ilen ); |
| 1434 #endif | 1503 #endif |
| 1435 } | 1504 } |
| 1436 | 1505 |
| 1437 ctxt->state = XML_NANO_HTTP_READ; | 1506 ctxt->state = XML_NANO_HTTP_READ; |
| 1438 head = 1; | |
| 1439 | 1507 |
| 1440 while ((p = xmlNanoHTTPReadLine(ctxt)) != NULL) { | 1508 while ((p = xmlNanoHTTPReadLine(ctxt)) != NULL) { |
| 1441 if (head && (*p == 0)) { | 1509 if (*p == 0) { |
| 1442 » head = 0; | |
| 1443 ctxt->content = ctxt->inrptr; | 1510 ctxt->content = ctxt->inrptr; |
| 1444 xmlFree(p); | 1511 xmlFree(p); |
| 1445 break; | 1512 break; |
| 1446 } | 1513 } |
| 1447 xmlNanoHTTPScanAnswer(ctxt, p); | 1514 xmlNanoHTTPScanAnswer(ctxt, p); |
| 1448 | 1515 |
| 1449 #ifdef DEBUG_HTTP | 1516 #ifdef DEBUG_HTTP |
| 1450 xmlGenericError(xmlGenericErrorContext, "<- %s\n", p); | 1517 xmlGenericError(xmlGenericErrorContext, "<- %s\n", p); |
| 1451 #endif | 1518 #endif |
| 1452 xmlFree(p); | 1519 xmlFree(p); |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1799 #include <stdio.h> | 1866 #include <stdio.h> |
| 1800 int main(int argc, char **argv) { | 1867 int main(int argc, char **argv) { |
| 1801 xmlGenericError(xmlGenericErrorContext, | 1868 xmlGenericError(xmlGenericErrorContext, |
| 1802 "%s : HTTP support not compiled in\n", argv[0]); | 1869 "%s : HTTP support not compiled in\n", argv[0]); |
| 1803 return(0); | 1870 return(0); |
| 1804 } | 1871 } |
| 1805 #endif /* STANDALONE */ | 1872 #endif /* STANDALONE */ |
| 1806 #endif /* LIBXML_HTTP_ENABLED */ | 1873 #endif /* LIBXML_HTTP_ENABLED */ |
| 1807 #define bottom_nanohttp | 1874 #define bottom_nanohttp |
| 1808 #include "elfgcchack.h" | 1875 #include "elfgcchack.h" |
| OLD | NEW |