| Index: third_party/libxml/nanohttp.c
|
| diff --git a/third_party/libxml/nanohttp.c b/third_party/libxml/nanohttp.c
|
| index 07829c7f38c150396a7a1502d34b56fe95c0acc1..542c4eac943aa6088ae432b60e38903d687e6e9c 100644
|
| --- a/third_party/libxml/nanohttp.c
|
| +++ b/third_party/libxml/nanohttp.c
|
| @@ -54,9 +54,13 @@
|
| #ifdef HAVE_SYS_TIME_H
|
| #include <sys/time.h>
|
| #endif
|
| +#ifndef HAVE_POLL_H
|
| #ifdef HAVE_SYS_SELECT_H
|
| #include <sys/select.h>
|
| #endif
|
| +#else
|
| +#include <poll.h>
|
| +#endif
|
| #ifdef HAVE_STRINGS_H
|
| #include <strings.h>
|
| #endif
|
| @@ -95,7 +99,7 @@
|
| * A couple portability macros
|
| */
|
| #ifndef _WINSOCKAPI_
|
| -#ifndef __BEOS__
|
| +#if !defined(__BEOS__) || defined(__HAIKU__)
|
| #define closesocket(s) close(s)
|
| #endif
|
| #define SOCKET int
|
| @@ -146,6 +150,7 @@ typedef struct xmlNanoHTTPCtxt {
|
| int inlen; /* len of the input buffer */
|
| int last; /* return code for last operation */
|
| int returnValue; /* the protocol return value */
|
| + int version; /* the protocol version */
|
| int ContentLength; /* specified content length from HTTP header */
|
| char *contentType; /* the MIME type for the input */
|
| char *location; /* the new URL in case of redirect */
|
| @@ -439,51 +444,64 @@ xmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt) {
|
| */
|
|
|
| static int
|
| -xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char * xmt_ptr, int outlen) {
|
| -
|
| - int total_sent = 0;
|
| +xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char *xmt_ptr, int outlen)
|
| +{
|
| + int total_sent = 0;
|
| +#ifdef HAVE_POLL_H
|
| + struct pollfd p;
|
| +#else
|
| + struct timeval tv;
|
| + fd_set wfd;
|
| +#endif
|
|
|
| - if ( (ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL ) ) {
|
| + if ((ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL)) {
|
| while (total_sent < outlen) {
|
| int nsent = send(ctxt->fd, xmt_ptr + total_sent,
|
| - outlen - total_sent, 0);
|
| - if (nsent>0)
|
| + outlen - total_sent, 0);
|
| +
|
| + if (nsent > 0)
|
| total_sent += nsent;
|
| - else if ( ( nsent == -1 ) &&
|
| + else if ((nsent == -1) &&
|
| #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
|
| - ( socket_errno( ) != EAGAIN ) &&
|
| + (socket_errno() != EAGAIN) &&
|
| +#endif
|
| + (socket_errno() != EWOULDBLOCK)) {
|
| + __xmlIOErr(XML_FROM_HTTP, 0, "send failed\n");
|
| + if (total_sent == 0)
|
| + total_sent = -1;
|
| + break;
|
| + } else {
|
| + /*
|
| + * No data sent
|
| + * Since non-blocking sockets are used, wait for
|
| + * socket to be writable or default timeout prior
|
| + * to retrying.
|
| + */
|
| +#ifndef HAVE_POLL_H
|
| +#ifndef _WINSOCKAPI_
|
| + if (ctxt->fd > FD_SETSIZE)
|
| + return -1;
|
| #endif
|
| - ( socket_errno( ) != EWOULDBLOCK ) ) {
|
| - __xmlIOErr(XML_FROM_HTTP, 0, "send failed\n");
|
| - if ( total_sent == 0 )
|
| - total_sent = -1;
|
| - break;
|
| - }
|
| - else {
|
| - /*
|
| - ** No data sent
|
| - ** Since non-blocking sockets are used, wait for
|
| - ** socket to be writable or default timeout prior
|
| - ** to retrying.
|
| - */
|
| -
|
| - struct timeval tv;
|
| - fd_set wfd;
|
| -
|
| - tv.tv_sec = timeout;
|
| - tv.tv_usec = 0;
|
| - FD_ZERO( &wfd );
|
| +
|
| + tv.tv_sec = timeout;
|
| + tv.tv_usec = 0;
|
| + FD_ZERO(&wfd);
|
| #ifdef _MSC_VER
|
| #pragma warning(push)
|
| #pragma warning(disable: 4018)
|
| #endif
|
| - FD_SET( ctxt->fd, &wfd );
|
| + FD_SET(ctxt->fd, &wfd);
|
| #ifdef _MSC_VER
|
| #pragma warning(pop)
|
| #endif
|
| - (void)select( ctxt->fd + 1, NULL, &wfd, NULL, &tv );
|
| - }
|
| - }
|
| + (void) select(ctxt->fd + 1, NULL, &wfd, NULL, &tv);
|
| +#else
|
| + p.fd = ctxt->fd;
|
| + p.events = POLLOUT;
|
| + (void) poll(&p, 1, timeout * 1000);
|
| +#endif /* !HAVE_POLL_H */
|
| + }
|
| + }
|
| }
|
|
|
| return total_sent;
|
| @@ -500,96 +518,119 @@ xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char * xmt_ptr, int outlen) {
|
| */
|
|
|
| static int
|
| -xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) {
|
| +xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt)
|
| +{
|
| +#ifdef HAVE_POLL_H
|
| + struct pollfd p;
|
| +#else
|
| fd_set rfd;
|
| struct timeval tv;
|
| +#endif
|
|
|
|
|
| while (ctxt->state & XML_NANO_HTTP_READ) {
|
| - if (ctxt->in == NULL) {
|
| - ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char));
|
| - if (ctxt->in == NULL) {
|
| - xmlHTTPErrMemory("allocating input");
|
| - ctxt->last = -1;
|
| - return(-1);
|
| - }
|
| - ctxt->inlen = 65000;
|
| - ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in;
|
| - }
|
| - if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) {
|
| - int delta = ctxt->inrptr - ctxt->in;
|
| - int len = ctxt->inptr - ctxt->inrptr;
|
| -
|
| - memmove(ctxt->in, ctxt->inrptr, len);
|
| - ctxt->inrptr -= delta;
|
| - ctxt->content -= delta;
|
| - ctxt->inptr -= delta;
|
| - }
|
| + if (ctxt->in == NULL) {
|
| + ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char));
|
| + if (ctxt->in == NULL) {
|
| + xmlHTTPErrMemory("allocating input");
|
| + ctxt->last = -1;
|
| + return (-1);
|
| + }
|
| + ctxt->inlen = 65000;
|
| + ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in;
|
| + }
|
| + if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) {
|
| + int delta = ctxt->inrptr - ctxt->in;
|
| + int len = ctxt->inptr - ctxt->inrptr;
|
| +
|
| + memmove(ctxt->in, ctxt->inrptr, len);
|
| + ctxt->inrptr -= delta;
|
| + ctxt->content -= delta;
|
| + ctxt->inptr -= delta;
|
| + }
|
| if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) {
|
| - int d_inptr = ctxt->inptr - ctxt->in;
|
| - int d_content = ctxt->content - ctxt->in;
|
| - int d_inrptr = ctxt->inrptr - ctxt->in;
|
| - char * tmp_ptr = ctxt->in;
|
| + int d_inptr = ctxt->inptr - ctxt->in;
|
| + int d_content = ctxt->content - ctxt->in;
|
| + int d_inrptr = ctxt->inrptr - ctxt->in;
|
| + char *tmp_ptr = ctxt->in;
|
|
|
| - ctxt->inlen *= 2;
|
| + ctxt->inlen *= 2;
|
| ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen);
|
| - if (ctxt->in == NULL) {
|
| - xmlHTTPErrMemory("allocating input buffer");
|
| - xmlFree( tmp_ptr );
|
| - ctxt->last = -1;
|
| - return(-1);
|
| - }
|
| + if (ctxt->in == NULL) {
|
| + xmlHTTPErrMemory("allocating input buffer");
|
| + xmlFree(tmp_ptr);
|
| + ctxt->last = -1;
|
| + return (-1);
|
| + }
|
| ctxt->inptr = ctxt->in + d_inptr;
|
| ctxt->content = ctxt->in + d_content;
|
| ctxt->inrptr = ctxt->in + d_inrptr;
|
| - }
|
| - ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0);
|
| - if (ctxt->last > 0) {
|
| - ctxt->inptr += ctxt->last;
|
| - return(ctxt->last);
|
| - }
|
| - if (ctxt->last == 0) {
|
| - return(0);
|
| - }
|
| - if (ctxt->last == -1) {
|
| - switch (socket_errno()) {
|
| - case EINPROGRESS:
|
| - case EWOULDBLOCK:
|
| + }
|
| + ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0);
|
| + if (ctxt->last > 0) {
|
| + ctxt->inptr += ctxt->last;
|
| + return (ctxt->last);
|
| + }
|
| + if (ctxt->last == 0) {
|
| + return (0);
|
| + }
|
| + if (ctxt->last == -1) {
|
| + switch (socket_errno()) {
|
| + case EINPROGRESS:
|
| + case EWOULDBLOCK:
|
| #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
|
| - case EAGAIN:
|
| + case EAGAIN:
|
| +#endif
|
| + break;
|
| +
|
| + case ECONNRESET:
|
| + case ESHUTDOWN:
|
| + return (0);
|
| +
|
| + default:
|
| + __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n");
|
| + return (-1);
|
| + }
|
| + }
|
| +#ifdef HAVE_POLL_H
|
| + p.fd = ctxt->fd;
|
| + p.events = POLLIN;
|
| + if ((poll(&p, 1, timeout * 1000) < 1)
|
| +#if defined(EINTR)
|
| + && (errno != EINTR)
|
| +#endif
|
| + )
|
| + return (0);
|
| +#else /* !HAVE_POLL_H */
|
| +#ifndef _WINSOCKAPI_
|
| + if (ctxt->fd > FD_SETSIZE)
|
| + return 0;
|
| #endif
|
| - break;
|
| -
|
| - case ECONNRESET:
|
| - case ESHUTDOWN:
|
| - return ( 0 );
|
|
|
| - default:
|
| - __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n");
|
| - return(-1);
|
| - }
|
| - }
|
| + tv.tv_sec = timeout;
|
| + tv.tv_usec = 0;
|
| + FD_ZERO(&rfd);
|
|
|
| - tv.tv_sec = timeout;
|
| - tv.tv_usec = 0;
|
| - FD_ZERO(&rfd);
|
| #ifdef _MSC_VER
|
| #pragma warning(push)
|
| #pragma warning(disable: 4018)
|
| #endif
|
| - FD_SET(ctxt->fd, &rfd);
|
| +
|
| + FD_SET(ctxt->fd, &rfd);
|
| +
|
| #ifdef _MSC_VER
|
| #pragma warning(pop)
|
| #endif
|
| -
|
| - if ( (select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1)
|
| +
|
| + if ((select(ctxt->fd + 1, &rfd, NULL, NULL, &tv) < 1)
|
| #if defined(EINTR)
|
| - && (errno != EINTR)
|
| + && (errno != EINTR)
|
| #endif
|
| - )
|
| - return(0);
|
| + )
|
| + return (0);
|
| +#endif /* !HAVE_POLL_H */
|
| }
|
| - return(0);
|
| + return (0);
|
| }
|
|
|
| /**
|
| @@ -686,6 +727,7 @@ xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) {
|
| }
|
| if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return;
|
| ctxt->returnValue = ret;
|
| + ctxt->version = version;
|
| } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Content-Type:", 13)) {
|
| const xmlChar *charset, *last, *mime;
|
| cur += 13;
|
| @@ -803,87 +845,96 @@ xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) {
|
| static int
|
| xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
|
| {
|
| +#ifndef HAVE_POLL_H
|
| fd_set wfd;
|
| #ifdef _WINSOCKAPI_
|
| fd_set xfd;
|
| #endif
|
| struct timeval tv;
|
| +#else /* !HAVE_POLL_H */
|
| + struct pollfd p;
|
| +#endif /* !HAVE_POLL_H */
|
| int status;
|
| +
|
| int addrlen;
|
| +
|
| SOCKET s;
|
| -
|
| +
|
| #ifdef SUPPORT_IP6
|
| if (addr->sa_family == AF_INET6) {
|
| - s = socket (PF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
| - addrlen = sizeof (struct sockaddr_in6);
|
| - }
|
| - else
|
| + s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
| + addrlen = sizeof(struct sockaddr_in6);
|
| + } else
|
| #endif
|
| {
|
| - s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
| - addrlen = sizeof (struct sockaddr_in);
|
| + s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
| + addrlen = sizeof(struct sockaddr_in);
|
| }
|
| - if (s==-1) {
|
| + if (s == -1) {
|
| #ifdef DEBUG_HTTP
|
| - perror("socket");
|
| + perror("socket");
|
| #endif
|
| - __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n");
|
| - return(-1);
|
| + __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n");
|
| + return (-1);
|
| }
|
| -
|
| #ifdef _WINSOCKAPI_
|
| {
|
| - u_long one = 1;
|
| + u_long one = 1;
|
|
|
| - status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0;
|
| + status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0;
|
| }
|
| #else /* _WINSOCKAPI_ */
|
| #if defined(VMS)
|
| {
|
| - int enable = 1;
|
| - status = ioctl(s, FIONBIO, &enable);
|
| + int enable = 1;
|
| +
|
| + status = ioctl(s, FIONBIO, &enable);
|
| }
|
| #else /* VMS */
|
| -#if defined(__BEOS__)
|
| - {
|
| - bool noblock = true;
|
| - status = setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock, sizeof(noblock));
|
| - }
|
| +#if defined(__BEOS__) && !defined(__HAIKU__)
|
| + {
|
| + bool noblock = true;
|
| +
|
| + status =
|
| + setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock,
|
| + sizeof(noblock));
|
| + }
|
| #else /* __BEOS__ */
|
| if ((status = fcntl(s, F_GETFL, 0)) != -1) {
|
| #ifdef O_NONBLOCK
|
| - status |= O_NONBLOCK;
|
| + status |= O_NONBLOCK;
|
| #else /* O_NONBLOCK */
|
| #ifdef F_NDELAY
|
| - status |= F_NDELAY;
|
| + status |= F_NDELAY;
|
| #endif /* F_NDELAY */
|
| #endif /* !O_NONBLOCK */
|
| - status = fcntl(s, F_SETFL, status);
|
| + status = fcntl(s, F_SETFL, status);
|
| }
|
| if (status < 0) {
|
| #ifdef DEBUG_HTTP
|
| - perror("nonblocking");
|
| + perror("nonblocking");
|
| #endif
|
| - __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n");
|
| - closesocket(s);
|
| - return(-1);
|
| + __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n");
|
| + closesocket(s);
|
| + return (-1);
|
| }
|
| #endif /* !__BEOS__ */
|
| #endif /* !VMS */
|
| #endif /* !_WINSOCKAPI_ */
|
|
|
| - if (connect (s, addr, addrlen) == -1) {
|
| - switch (socket_errno()) {
|
| - case EINPROGRESS:
|
| - case EWOULDBLOCK:
|
| - break;
|
| - default:
|
| - __xmlIOErr(XML_FROM_HTTP, 0, "error connecting to HTTP server");
|
| - closesocket(s);
|
| - return(-1);
|
| - }
|
| - }
|
| -
|
| + if (connect(s, addr, addrlen) == -1) {
|
| + switch (socket_errno()) {
|
| + case EINPROGRESS:
|
| + case EWOULDBLOCK:
|
| + break;
|
| + default:
|
| + __xmlIOErr(XML_FROM_HTTP, 0,
|
| + "error connecting to HTTP server");
|
| + closesocket(s);
|
| + return (-1);
|
| + }
|
| + }
|
| +#ifndef HAVE_POLL_H
|
| tv.tv_sec = timeout;
|
| tv.tv_usec = 0;
|
|
|
| @@ -891,63 +942,82 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
|
| #pragma warning(push)
|
| #pragma warning(disable: 4018)
|
| #endif
|
| +#ifndef _WINSOCKAPI_
|
| + if (s > FD_SETSIZE)
|
| + return -1;
|
| +#endif
|
| FD_ZERO(&wfd);
|
| FD_SET(s, &wfd);
|
|
|
| -#ifdef _WINSOCKAPI_
|
| +#ifdef _WINSOCKAPI_
|
| FD_ZERO(&xfd);
|
| FD_SET(s, &xfd);
|
| -
|
| - switch(select(s+1, NULL, &wfd, &xfd, &tv))
|
| +
|
| + switch (select(s + 1, NULL, &wfd, &xfd, &tv))
|
| #else
|
| - switch(select(s+1, NULL, &wfd, NULL, &tv))
|
| + switch (select(s + 1, NULL, &wfd, NULL, &tv))
|
| #endif
|
| #ifdef _MSC_VER
|
| #pragma warning(pop)
|
| #endif
|
| +
|
| +#else /* !HAVE_POLL_H */
|
| + p.fd = s;
|
| + p.events = POLLOUT;
|
| + switch (poll(&p, 1, timeout * 1000))
|
| +#endif /* !HAVE_POLL_H */
|
| +
|
| {
|
| - case 0:
|
| - /* Time out */
|
| - __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out");
|
| - closesocket(s);
|
| - return(-1);
|
| - case -1:
|
| - /* Ermm.. ?? */
|
| - __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed");
|
| - closesocket(s);
|
| - return(-1);
|
| + case 0:
|
| + /* Time out */
|
| + __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out");
|
| + closesocket(s);
|
| + return (-1);
|
| + case -1:
|
| + /* Ermm.. ?? */
|
| + __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed");
|
| + closesocket(s);
|
| + return (-1);
|
| }
|
|
|
| - if ( FD_ISSET(s, &wfd)
|
| +#ifndef HAVE_POLL_H
|
| + if (FD_ISSET(s, &wfd)
|
| #ifdef _WINSOCKAPI_
|
| - || FD_ISSET(s, &xfd)
|
| + || FD_ISSET(s, &xfd)
|
| #endif
|
| - ) {
|
| - XML_SOCKLEN_T len;
|
| - len = sizeof(status);
|
| + )
|
| +#else /* !HAVE_POLL_H */
|
| + if (p.revents == POLLOUT)
|
| +#endif /* !HAVE_POLL_H */
|
| + {
|
| + XML_SOCKLEN_T len;
|
| +
|
| + len = sizeof(status);
|
| #ifdef SO_ERROR
|
| - if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&status, &len) < 0 ) {
|
| - /* Solaris error code */
|
| - __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n");
|
| - return (-1);
|
| - }
|
| -#endif
|
| - if ( status ) {
|
| - __xmlIOErr(XML_FROM_HTTP, 0, "Error connecting to remote host");
|
| - closesocket(s);
|
| - errno = status;
|
| - return (-1);
|
| - }
|
| + if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &status, &len) <
|
| + 0) {
|
| + /* Solaris error code */
|
| + __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n");
|
| + return (-1);
|
| + }
|
| +#endif
|
| + if (status) {
|
| + __xmlIOErr(XML_FROM_HTTP, 0,
|
| + "Error connecting to remote host");
|
| + closesocket(s);
|
| + errno = status;
|
| + return (-1);
|
| + }
|
| } else {
|
| - /* pbm */
|
| - __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n");
|
| - closesocket(s);
|
| - return (-1);
|
| + /* pbm */
|
| + __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n");
|
| + closesocket(s);
|
| + return (-1);
|
| }
|
| -
|
| - return(s);
|
| +
|
| + return (s);
|
| }
|
| -
|
| +
|
| /**
|
| * xmlNanoHTTPConnectHost:
|
| * @host: the host name
|
| @@ -1273,7 +1343,6 @@ xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input,
|
| xmlNanoHTTPCtxtPtr ctxt;
|
| char *bp, *p;
|
| int blen, ret;
|
| - int head;
|
| int nbRedirects = 0;
|
| char *redirURL = NULL;
|
| #ifdef DEBUG_HTTP
|
| @@ -1435,11 +1504,9 @@ retry:
|
| }
|
|
|
| ctxt->state = XML_NANO_HTTP_READ;
|
| - head = 1;
|
|
|
| while ((p = xmlNanoHTTPReadLine(ctxt)) != NULL) {
|
| - if (head && (*p == 0)) {
|
| - head = 0;
|
| + if (*p == 0) {
|
| ctxt->content = ctxt->inrptr;
|
| xmlFree(p);
|
| break;
|
|
|