diff options
Diffstat (limited to 'gnulib-local/lib/libxml/nanohttp.c')
-rw-r--r-- | gnulib-local/lib/libxml/nanohttp.c | 609 |
1 files changed, 354 insertions, 255 deletions
diff --git a/gnulib-local/lib/libxml/nanohttp.c b/gnulib-local/lib/libxml/nanohttp.c index ae7923f..e109ad7 100644 --- a/gnulib-local/lib/libxml/nanohttp.c +++ b/gnulib-local/lib/libxml/nanohttp.c @@ -10,7 +10,7 @@ * * daniel@veillard.com */ - + #define NEED_SOCKETS #define IN_LIBXML #include "libxml.h" @@ -46,7 +46,7 @@ #include <resolv.h> #endif #ifdef HAVE_FCNTL_H -#include <fcntl.h> +#include <fcntl.h> #endif #ifdef HAVE_ERRNO_H #include <errno.h> @@ -54,15 +54,16 @@ #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 -#ifdef SUPPORT_IP6 -#include <resolv.h> -#endif #ifdef HAVE_ZLIB_H #include <zlib.h> #endif @@ -71,19 +72,18 @@ #ifdef VMS #include <stropts> #define XML_SOCKLEN_T unsigned int -#define SOCKET int #endif - -#ifdef __MINGW32__ +#if defined(__MINGW32__) || defined(_WIN32_WCE) +#ifndef _WINSOCKAPI_ #define _WINSOCKAPI_ +#endif #include <wsockcompat.h> #include <winsock2.h> #undef XML_SOCKLEN_T #define XML_SOCKLEN_T unsigned int #endif - #include <libxml/globals.h> #include <libxml/xmlerror.h> #include <libxml/xmlmemory.h> @@ -96,10 +96,11 @@ * A couple portability macros */ #ifndef _WINSOCKAPI_ -#ifndef __BEOS__ +#if !defined(__BEOS__) || defined(__HAIKU__) #define closesocket(s) close(s) #endif #define SOCKET int +#define INVALID_SOCKET (-1) #endif #ifdef __BEOS__ @@ -111,9 +112,6 @@ #ifndef XML_SOCKLEN_T #define XML_SOCKLEN_T unsigned int #endif -#ifndef SOCKET -#define SOCKET int -#endif #ifdef STANDALONE #define DEBUG_HTTP @@ -147,6 +145,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 */ @@ -192,10 +191,10 @@ static int socket_errno(void) { #ifdef SUPPORT_IP6 static int have_ipv6(void) { - int s; + SOCKET s; s = socket (AF_INET6, SOCK_STREAM, 0); - if (s != -1) { + if (s != INVALID_SOCKET) { close (s); return (1); } @@ -214,7 +213,7 @@ void xmlNanoHTTPInit(void) { const char *env; #ifdef _WINSOCKAPI_ - WSADATA wsaData; + WSADATA wsaData; #endif if (initialized) @@ -277,22 +276,24 @@ xmlNanoHTTPCleanup(void) { static void xmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt, const char *URL) { xmlURIPtr uri; + int len; + /* * Clear any existing data from the context */ - if (ctxt->protocol != NULL) { + if (ctxt->protocol != NULL) { xmlFree(ctxt->protocol); ctxt->protocol = NULL; } - if (ctxt->hostname != NULL) { + if (ctxt->hostname != NULL) { xmlFree(ctxt->hostname); ctxt->hostname = NULL; } - if (ctxt->path != NULL) { + if (ctxt->path != NULL) { xmlFree(ctxt->path); ctxt->path = NULL; } - if (ctxt->query != NULL) { + if (ctxt->query != NULL) { xmlFree(ctxt->query); ctxt->query = NULL; } @@ -306,9 +307,17 @@ xmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt, const char *URL) { xmlFreeURI(uri); return; } - + ctxt->protocol = xmlMemStrdup(uri->scheme); - ctxt->hostname = xmlMemStrdup(uri->server); + /* special case of IPv6 addresses, the [] need to be removed */ + if ((uri->server != NULL) && (*uri->server == '[')) { + len = strlen(uri->server); + if ((len > 2) && (uri->server[len - 1] == ']')) { + ctxt->hostname = (char *) xmlCharStrndup(uri->server + 1, len -2); + } else + ctxt->hostname = xmlMemStrdup(uri->server); + } else + ctxt->hostname = xmlMemStrdup(uri->server); if (uri->path != NULL) ctxt->path = xmlMemStrdup(uri->path); else @@ -335,7 +344,7 @@ void xmlNanoHTTPScanProxy(const char *URL) { xmlURIPtr uri; - if (proxy != NULL) { + if (proxy != NULL) { xmlFree(proxy); proxy = NULL; } @@ -359,7 +368,7 @@ xmlNanoHTTPScanProxy(const char *URL) { xmlFreeURI(uri); return; } - + proxy = xmlMemStrdup(uri->server); if (uri->port != 0) proxyPort = uri->port; @@ -389,7 +398,7 @@ xmlNanoHTTPNewCtxt(const char *URL) { memset(ret, 0, sizeof(xmlNanoHTTPCtxt)); ret->port = 80; ret->returnValue = 0; - ret->fd = -1; + ret->fd = INVALID_SOCKET; ret->ContentLength = -1; xmlNanoHTTPScanURL(ret, URL); @@ -426,8 +435,8 @@ xmlNanoHTTPFreeCtxt(xmlNanoHTTPCtxtPtr ctxt) { #endif ctxt->state = XML_NANO_HTTP_NONE; - if (ctxt->fd >= 0) closesocket(ctxt->fd); - ctxt->fd = -1; + if (ctxt->fd != INVALID_SOCKET) closesocket(ctxt->fd); + ctxt->fd = INVALID_SOCKET; xmlFree(ctxt); } @@ -440,51 +449,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) + int nsent = send(ctxt->fd, SEND_ARG2_CAST (xmt_ptr + total_sent), + 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; @@ -501,96 +523,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 ); + tv.tv_sec = timeout; + tv.tv_usec = 0; + FD_ZERO(&rfd); - default: - __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n"); - return(-1); - } - } - - 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); } /** @@ -609,7 +654,7 @@ xmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt) { char buf[4096]; char *bp = buf; int rc; - + while (bp - buf < 4095) { if (ctxt->inrptr == ctxt->inptr) { if ( (rc = xmlNanoHTTPRecv(ctxt)) == 0) { @@ -687,6 +732,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; @@ -745,9 +791,9 @@ xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) { xmlFree(ctxt->location); if (*cur == '/') { xmlChar *tmp_http = xmlStrdup(BAD_CAST "http://"); - xmlChar *tmp_loc = + xmlChar *tmp_loc = xmlStrcat(tmp_http, (const xmlChar *) ctxt->hostname); - ctxt->location = + ctxt->location = (char *) xmlStrcat (tmp_loc, (const xmlChar *) cur); } else { ctxt->location = xmlMemStrdup(cur); @@ -801,90 +847,99 @@ xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) { * Returns -1 in case of failure, the file descriptor number otherwise */ -static int +static SOCKET 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 == INVALID_SOCKET) { #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 INVALID_SOCKET; } - #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 INVALID_SOCKET; } #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 INVALID_SOCKET; + } + } +#ifndef HAVE_POLL_H tv.tv_sec = timeout; tv.tv_usec = 0; @@ -892,63 +947,83 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr) #pragma warning(push) #pragma warning(disable: 4018) #endif +#ifndef _WINSOCKAPI_ + if (s > FD_SETSIZE) + return INVALID_SOCKET; +#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 INVALID_SOCKET; + case -1: + /* Ermm.. ?? */ + __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed"); + closesocket(s); + return INVALID_SOCKET; } - 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"); + closesocket(s); + return INVALID_SOCKET; + } +#endif + if (status) { + __xmlIOErr(XML_FROM_HTTP, 0, + "Error connecting to remote host"); + closesocket(s); + errno = status; + return INVALID_SOCKET; + } } 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 INVALID_SOCKET; } - - return(s); + + return (s); } - + /** * xmlNanoHTTPConnectHost: * @host: the host name @@ -960,7 +1035,7 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr) * Returns -1 in case of failure, the file descriptor number otherwise */ -static int +static SOCKET xmlNanoHTTPConnectHost(const char *host, int port) { struct hostent *h; @@ -973,7 +1048,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) struct sockaddr_in6 sockin6; #endif int i; - int s; + SOCKET s; memset (&sockin, 0, sizeof(sockin)); #ifdef SUPPORT_IP6 @@ -1004,7 +1079,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) status = getaddrinfo (host, NULL, &hints, &result); if (status) { __xmlIOErr(XML_FROM_HTTP, 0, "getaddrinfo failed\n"); - return (-1); + return INVALID_SOCKET; } for (res = result; res; res = res->ai_next) { @@ -1012,7 +1087,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) if (res->ai_addrlen > sizeof(sockin)) { __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); freeaddrinfo (result); - return (-1); + return INVALID_SOCKET; } memcpy (&sockin, res->ai_addr, res->ai_addrlen); sockin.sin_port = htons (port); @@ -1022,7 +1097,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) if (res->ai_addrlen > sizeof(sockin6)) { __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); freeaddrinfo (result); - return (-1); + return INVALID_SOCKET; } memcpy (&sockin6, res->ai_addr, res->ai_addrlen); sockin6.sin6_port = htons (port); @@ -1032,7 +1107,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) continue; /* for */ s = xmlNanoHTTPConnectAttempt (addr); - if (s != -1) { + if (s != INVALID_SOCKET) { freeaddrinfo (result); return (s); } @@ -1047,7 +1122,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) #endif #if !defined(HAVE_GETADDRINFO) || !defined(_WIN32) { - h = gethostbyname (host); + h = gethostbyname (GETHOSTBYNAME_ARG_CAST host); if (h == NULL) { /* @@ -1073,10 +1148,12 @@ xmlNanoHTTPConnectHost(const char *host, int port) "Non-recoverable errors: FORMERR, REFUSED, or NOTIMP."; break; +#ifdef NO_ADDRESS case NO_ADDRESS: h_err_txt = "Valid name, no data record of requested type."; break; +#endif default: h_err_txt = "No error text defined."; @@ -1086,7 +1163,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) #else __xmlIOErr(XML_FROM_HTTP, 0, "Failed to resolve host"); #endif - return (-1); + return INVALID_SOCKET; } for (i = 0; h->h_addr_list[i]; i++) { @@ -1094,19 +1171,19 @@ xmlNanoHTTPConnectHost(const char *host, int port) /* A records (IPv4) */ if ((unsigned int) h->h_length > sizeof(ia)) { __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); - return (-1); + return INVALID_SOCKET; } memcpy (&ia, h->h_addr_list[i], h->h_length); sockin.sin_family = h->h_addrtype; sockin.sin_addr = ia; - sockin.sin_port = (u_short)htons ((unsigned short)port); + sockin.sin_port = (unsigned short)htons ((unsigned short)port); addr = (struct sockaddr *) &sockin; #ifdef SUPPORT_IP6 } else if (have_ipv6 () && (h->h_addrtype == AF_INET6)) { /* AAAA records (IPv6) */ if ((unsigned int) h->h_length > sizeof(ia6)) { __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); - return (-1); + return INVALID_SOCKET; } memcpy (&ia6, h->h_addr_list[i], h->h_length); sockin6.sin6_family = h->h_addrtype; @@ -1118,7 +1195,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) break; /* for */ s = xmlNanoHTTPConnectAttempt (addr); - if (s != -1) + if (s != INVALID_SOCKET) return (s); } } @@ -1129,7 +1206,7 @@ xmlNanoHTTPConnectHost(const char *host, int port) "xmlNanoHTTPConnectHost: unable to connect to '%s'.\n", host); #endif - return (-1); + return INVALID_SOCKET; } @@ -1201,19 +1278,22 @@ xmlNanoHTTPRead(void *ctx, void *dest, int len) { #ifdef HAVE_ZLIB_H if (ctxt->usesGzip == 1) { if (ctxt->strm == NULL) return(0); - + ctxt->strm->next_out = dest; ctxt->strm->avail_out = len; + ctxt->strm->avail_in = ctxt->inptr - ctxt->inrptr; - do { - orig_avail_in = ctxt->strm->avail_in = ctxt->inptr - ctxt->inrptr - bytes_read; + while (ctxt->strm->avail_out > 0 && + (ctxt->strm->avail_in > 0 || xmlNanoHTTPRecv(ctxt) > 0)) { + orig_avail_in = ctxt->strm->avail_in = + ctxt->inptr - ctxt->inrptr - bytes_read; ctxt->strm->next_in = BAD_CAST (ctxt->inrptr + bytes_read); z_ret = inflate(ctxt->strm, Z_NO_FLUSH); bytes_read += orig_avail_in - ctxt->strm->avail_in; if (z_ret != Z_OK) break; - } while (ctxt->strm->avail_out > 0 && xmlNanoHTTPRecv(ctxt) > 0); + } ctxt->inrptr += bytes_read; return(len - ctxt->strm->avail_out); @@ -1270,30 +1350,30 @@ xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input, const char *headers, int ilen ) { xmlNanoHTTPCtxtPtr ctxt; char *bp, *p; - int blen, ret; - int head; + int blen; + SOCKET ret; int nbRedirects = 0; char *redirURL = NULL; #ifdef DEBUG_HTTP int xmt_bytes; #endif - + if (URL == NULL) return(NULL); if (method == NULL) method = "GET"; xmlNanoHTTPInit(); retry: - if (redirURL == NULL) + if (redirURL == NULL) { ctxt = xmlNanoHTTPNewCtxt(URL); - else { + if (ctxt == NULL) + return(NULL); + } else { ctxt = xmlNanoHTTPNewCtxt(redirURL); + if (ctxt == NULL) + return(NULL); ctxt->location = xmlMemStrdup(redirURL); } - if ( ctxt == NULL ) { - return ( NULL ); - } - if ((ctxt->protocol == NULL) || (strcmp(ctxt->protocol, "http"))) { __xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Not a valid HTTP URI"); xmlNanoHTTPFreeCtxt(ctxt); @@ -1315,7 +1395,7 @@ retry: blen = strlen(ctxt->hostname); ret = xmlNanoHTTPConnectHost(ctxt->hostname, ctxt->port); } - if (ret < 0) { + if (ret == INVALID_SOCKET) { xmlNanoHTTPFreeCtxt(ctxt); if (redirURL != NULL) xmlFree(redirURL); return(NULL); @@ -1330,13 +1410,23 @@ retry: if (headers != NULL) blen += strlen(headers) + 2; if (contentType && *contentType) + /* reserve for string plus 'Content-Type: \r\n" */ blen += strlen(*contentType) + 16; if (ctxt->query != NULL) + /* 1 for '?' */ blen += strlen(ctxt->query) + 1; blen += strlen(method) + strlen(ctxt->path) + 24; #ifdef HAVE_ZLIB_H + /* reserve for possible 'Accept-Encoding: gzip' string */ blen += 23; #endif + if (ctxt->port != 80) { + /* reserve space for ':xxxxx', incl. potential proxy */ + if (proxy) + blen += 12; + else + blen += 6; + } bp = (char*)xmlMallocAtomic(blen); if ( bp == NULL ) { xmlNanoHTTPFreeCtxt( ctxt ); @@ -1348,13 +1438,13 @@ retry: if (proxy) { if (ctxt->port != 80) { - p += snprintf( p, blen - (p - bp), "%s http://%s:%d%s", + p += snprintf( p, blen - (p - bp), "%s http://%s:%d%s", method, ctxt->hostname, - ctxt->port, ctxt->path ); + ctxt->port, ctxt->path ); } - else + else p += snprintf( p, blen - (p - bp), "%s http://%s%s", method, - ctxt->hostname, ctxt->path); + ctxt->hostname, ctxt->path); } else p += snprintf( p, blen - (p - bp), "%s %s", method, ctxt->path); @@ -1362,14 +1452,19 @@ retry: if (ctxt->query != NULL) p += snprintf( p, blen - (p - bp), "?%s", ctxt->query); - p += snprintf( p, blen - (p - bp), " HTTP/1.0\r\nHost: %s\r\n", + if (ctxt->port == 80) { + p += snprintf( p, blen - (p - bp), " HTTP/1.0\r\nHost: %s\r\n", ctxt->hostname); + } else { + p += snprintf( p, blen - (p - bp), " HTTP/1.0\r\nHost: %s:%d\r\n", + ctxt->hostname, ctxt->port); + } #ifdef HAVE_ZLIB_H p += snprintf(p, blen - (p - bp), "Accept-Encoding: gzip\r\n"); #endif - if (contentType != NULL && *contentType) + if (contentType != NULL && *contentType) p += snprintf(p, blen - (p - bp), "Content-Type: %s\r\n", *contentType); if (headers != NULL) @@ -1408,7 +1503,7 @@ retry: if ( xmt_bytes != ilen ) xmlGenericError( xmlGenericErrorContext, - "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", + "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", xmt_bytes, ilen, "bytes of HTTP content sent to host", ctxt->hostname ); @@ -1418,11 +1513,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; @@ -1532,12 +1625,13 @@ xmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) { char *buf = NULL; int fd; int len; - + int ret = 0; + if (filename == NULL) return(-1); ctxt = xmlNanoHTTPOpen(URL, contentType); if (ctxt == NULL) return(-1); - if (!strcmp(filename, "-")) + if (!strcmp(filename, "-")) fd = 0; else { fd = open(filename, O_CREAT | O_WRONLY, 00644); @@ -1553,12 +1647,14 @@ xmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) { xmlNanoHTTPFetchContent( ctxt, &buf, &len ); if ( len > 0 ) { - write(fd, buf, len); + if (write(fd, buf, len) == -1) { + ret = -1; + } } xmlNanoHTTPClose(ctxt); close(fd); - return(0); + return(ret); } #ifdef LIBXML_OUTPUT_ENABLED @@ -1577,13 +1673,14 @@ xmlNanoHTTPSave(void *ctxt, const char *filename) { char *buf = NULL; int fd; int len; - + int ret = 0; + if ((ctxt == NULL) || (filename == NULL)) return(-1); - if (!strcmp(filename, "-")) + if (!strcmp(filename, "-")) fd = 0; else { - fd = open(filename, O_CREAT | O_WRONLY); + fd = open(filename, O_CREAT | O_WRONLY, 0666); if (fd < 0) { xmlNanoHTTPClose(ctxt); return(-1); @@ -1592,12 +1689,14 @@ xmlNanoHTTPSave(void *ctxt, const char *filename) { xmlNanoHTTPFetchContent( ctxt, &buf, &len ); if ( len > 0 ) { - write(fd, buf, len); + if (write(fd, buf, len) == -1) { + ret = -1; + } } xmlNanoHTTPClose(ctxt); close(fd); - return(0); + return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ @@ -1707,7 +1806,7 @@ xmlNanoHTTPMimeType( void * ctx ) { * Check if all the content was read * * Returns 0 if all the content was read and available, returns - * -1 if received content length was less than specified or an error + * -1 if received content length was less than specified or an error * occurred. */ static int @@ -1761,7 +1860,7 @@ int main(int argc, char **argv) { char *contentType = NULL; if (argv[1] != NULL) { - if (argv[2] != NULL) + if (argv[2] != NULL) xmlNanoHTTPFetch(argv[1], argv[2], &contentType); else xmlNanoHTTPFetch(argv[1], "-", &contentType); |