updated libxml2 to 2.5.10
[TestXSLT.git] / libxml2 / nanohttp.c
index 376660b..15cc94d 100644 (file)
@@ -27,6 +27,9 @@
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
 #define SOCKET int
 #endif
 
+
+#ifdef __MINGW32__
+#define _WINSOCKAPI_
+#include <wsockcompat.h>
+#include <winsock2.h>
+#undef SOCKLEN_T
+#define SOCKLEN_T unsigned int
+#endif
+
+
 #include <libxml/globals.h>
 #include <libxml/xmlerror.h>
 #include <libxml/xmlmemory.h>
@@ -149,6 +162,20 @@ static int socket_errno(void) {
 #endif
 }
 
+#ifdef SUPPORT_IP6
+static
+int have_ipv6(void) {
+    int s;
+
+    s = socket (AF_INET6, SOCK_STREAM, 0);
+    if (s != -1) {
+       close (s);
+       return (1);
+    }
+    return (0);
+}
+#endif
+
 /**
  * xmlNanoHTTPInit:
  *
@@ -253,26 +280,64 @@ xmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt, const char *URL) {
 
     buf[indx] = 0;
     while (1) {
-        if (cur[0] == ':') {
+       if ((strchr (cur, '[') && !strchr (cur, ']')) ||
+               (!strchr (cur, '[') && strchr (cur, ']'))) {
+           xmlGenericError (xmlGenericErrorContext, "\nxmlNanoHTTPScanURL: %s",
+                   "Syntax Error\n");
+           return;
+       }
+
+       if (cur[0] == '[') {
+           cur++;
+           while (cur[0] != ']')
+               buf[indx++] = *cur++;
+    
+           if (!strchr (buf, ':')) {
+               xmlGenericError (xmlGenericErrorContext, "\nxmlNanoHTTPScanURL: %s",
+                       "Use [IPv6]/IPv4 format\n");
+               return;
+           }
+
            buf[indx] = 0;
-           ctxt->hostname = xmlMemStrdup(buf);
+           ctxt->hostname = xmlMemStrdup (buf);
            indx = 0;
            cur += 1;
-           while ((*cur >= '0') && (*cur <= '9')) {
-               port *= 10;
-               port += *cur - '0';
+           if (cur[0] == ':') {
                cur++;
+               while (*cur >= '0' && *cur <= '9') {
+                   port *= 10;
+                   port += *cur - '0';
+                   cur++;
+               }
+
+               if (port != 0) ctxt->port = port;
+               while ((cur[0] != '/') && (*cur != 0))
+                   cur++;
            }
-           if (port != 0) ctxt->port = port;
-           while ((cur[0] != '/') && (*cur != 0)) 
-               cur++;
-           break;
-       }
-        if ((*cur == '/') || (*cur == 0)) {
-           buf[indx] = 0;
-           ctxt->hostname = xmlMemStrdup(buf);
-           indx = 0;
            break;
+        }
+       else {
+           if (cur[0] == ':') {
+               buf[indx] = 0;
+               ctxt->hostname = xmlMemStrdup (buf);
+               indx = 0;
+               cur += 1;
+               while ((*cur >= '0') && (*cur <= '9')) {
+                   port *= 10;
+                   port += *cur - '0';
+                   cur++;
+               }
+               if (port != 0) ctxt->port = port;
+               while ((cur[0] != '/') && (*cur != 0)) 
+                   cur++;
+               break;
+           }
+           if ((*cur == '/') || (*cur == 0)) {
+               buf[indx] = 0;
+               ctxt->hostname = xmlMemStrdup (buf);
+               indx = 0;
+               break;
+           }
        }
        buf[indx++] = *cur++;
     }
@@ -335,26 +400,64 @@ xmlNanoHTTPScanProxy(const char *URL) {
 
     buf[indx] = 0;
     while (1) {
-        if (cur[0] == ':') {
+       if ((strchr (cur, '[') && !strchr (cur, ']')) ||
+               (!strchr (cur, '[') && strchr (cur, ']'))) {
+           xmlGenericError (xmlGenericErrorContext, "\nxmlNanoHTTPScanProxy: %s",
+                   "Syntax error\n");
+           return;
+       }
+
+       if (cur[0] == '[') {
+           cur++;
+           while (cur[0] != ']')
+               buf[indx++] = *cur++;
+
+           if (!strchr (buf, ':')) {
+               xmlGenericError (xmlGenericErrorContext, "\nxmlNanoHTTPScanProxy: %s",
+                       "Use [IPv6]/IPv4 format\n");
+               return;
+           }
+
            buf[indx] = 0;
-           proxy = xmlMemStrdup(buf);
+           proxy = xmlMemStrdup (buf);
            indx = 0;
            cur += 1;
-           while ((*cur >= '0') && (*cur <= '9')) {
-               port *= 10;
-               port += *cur - '0';
-               cur++;
-           }
-           if (port != 0) proxyPort = port;
-           while ((cur[0] != '/') && (*cur != 0)) 
+           if (cur[0] == ':') {
                cur++;
+               while (*cur >= '0' && *cur <= '9') {
+                   port *= 10;
+                   port += *cur - '0';
+                   cur++;
+               }
+
+               if (port != 0) proxyPort = port;
+               while ((cur[0] != '/') && (*cur != 0))
+                   cur ++;
+           }
            break;
        }
-        if ((*cur == '/') || (*cur == 0)) {
-           buf[indx] = 0;
-           proxy = xmlMemStrdup(buf);
-           indx = 0;
-           break;
+       else {
+           if (cur[0] == ':') {
+               buf[indx] = 0;
+               proxy = xmlMemStrdup (buf);
+               indx = 0;
+               cur += 1;
+               while ((*cur >= '0') && (*cur <= '9')) {
+                   port *= 10;
+                   port += *cur - '0';
+                   cur++;
+               }
+               if (port != 0) proxyPort = port;
+               while ((cur[0] != '/') && (*cur != 0)) 
+                   cur++;
+               break;
+           }
+           if ((*cur == '/') || (*cur == 0)) {
+               buf[indx] = 0;
+               proxy = xmlMemStrdup (buf);
+               indx = 0;
+               break;
+           }
        }
        buf[indx++] = *cur++;
     }
@@ -484,7 +587,7 @@ xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) {
 
     while (ctxt->state & XML_NANO_HTTP_READ) {
        if (ctxt->in == NULL) {
-           ctxt->in = (char *) xmlMalloc(65000 * sizeof(char));
+           ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char));
            if (ctxt->in == NULL) {
                ctxt->last = -1;
                xmlGenericError( xmlGenericErrorContext, 
@@ -711,11 +814,23 @@ xmlNanoHTTPScanAnswer(xmlNanoHTTPCtxtPtr ctxt, const char *line) {
 static int
 xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
 {
-    SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
     fd_set wfd;
     struct timeval tv;
     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
+#endif
+    {
+       s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
+       addrlen = sizeof (struct sockaddr_in);
+    }
     if (s==-1) {
 #ifdef DEBUG_HTTP
        perror("socket");
@@ -764,7 +879,7 @@ xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
 #endif /* !VMS */
 #endif /* !_WINSOCKAPI_ */
 
-    if ((connect(s, addr, sizeof(*addr))==-1)) {
+    if (connect (s, addr, addrlen) == -1) {
        switch (socket_errno()) {
            case EINPROGRESS:
            case EWOULDBLOCK:
@@ -851,7 +966,7 @@ static int
 xmlNanoHTTPConnectHost(const char *host, int port)
 {
     struct hostent *h;
-    struct sockaddr *addr;
+    struct sockaddr *addr = NULL;
     struct in_addr ia;
     struct sockaddr_in sockin;
 
@@ -862,13 +977,63 @@ xmlNanoHTTPConnectHost(const char *host, int port)
     int i;
     int s;
 
-#if defined(SUPPORT_IP6) && defined(RES_USE_INET6)
-    if (!(_res.options & RES_INIT))
-        res_init();
-    _res.options |= RES_USE_INET6;
+    memset (&sockin, 0, sizeof(sockin));
+#ifdef SUPPORT_IP6
+    memset (&sockin6, 0, sizeof(sockin6));
+    if (have_ipv6 ())
+#if !defined(HAVE_GETADDRINFO) && defined(RES_USE_INET6)
+    {
+       if (!(_res.options & RES_INIT))
+           res_init();
+       _res.options |= RES_USE_INET6;
+    }
+#elif defined(HAVE_GETADDRINFO)
+    {
+       int status;
+       struct addrinfo hints, *res, *result;
+
+       result = NULL;
+       memset (&hints, 0,sizeof(hints));
+       hints.ai_socktype = SOCK_STREAM;
+
+       status = getaddrinfo (host, NULL, &hints, &result);
+       if (status) {
+           xmlGenericError (xmlGenericErrorContext,
+                   "xmlNanoHTTPConnectHost:  %s '%s' - %s",
+                   "Failed to resolve host", host, gai_strerror (status));
+
+           return (-1);
+       }
+
+       for (res = result; res; res = res->ai_next) {
+           if (res->ai_family == AF_INET || res->ai_family == AF_INET6) {
+               if (res->ai_family == AF_INET6) {
+                   memcpy (&sockin6, res->ai_addr, res->ai_addrlen);
+                   sockin6.sin6_port = htons (port);
+                   addr = (struct sockaddr *)&sockin6;
+               }
+               else {
+                   memcpy (&sockin, res->ai_addr, res->ai_addrlen);
+                   sockin.sin_port = htons (port);
+                   addr = (struct sockaddr *)&sockin;
+               }
+
+               s = xmlNanoHTTPConnectAttempt (addr);
+               if (s != -1) {
+                   freeaddrinfo (result);
+                   return (s);
+               }
+           }
+       }
+       if (result)
+           freeaddrinfo (result);
+       return (-1);
+    } else
+#endif
 #endif
-    h = gethostbyname(host);
-    if (h == NULL) {
+    {   
+       h = gethostbyname (host);
+       if (h == NULL) {
 
 /*
  * Okay, I got fed up by the non-portability of this error message
@@ -876,68 +1041,68 @@ xmlNanoHTTPConnectHost(const char *host, int port)
  * and one want to enable it, send me the defined(foobar) needed
  */
 #if defined(HAVE_NETDB_H) && defined(HOST_NOT_FOUND) && defined(linux)
-        const char *h_err_txt = "";
-
-        switch (h_errno) {
-            case HOST_NOT_FOUND:
-                h_err_txt = "Authoritive host not found";
-                break;
-
-            case TRY_AGAIN:
-                h_err_txt =
-                    "Non-authoritive host not found or server failure.";
-                break;
-
-            case NO_RECOVERY:
-                h_err_txt =
-                    "Non-recoverable errors:  FORMERR, REFUSED, or NOTIMP.";
-                break;
-
-            case NO_ADDRESS:
-                h_err_txt =
-                    "Valid name, no data record of requested type.";
-                break;
-
-            default:
-                h_err_txt = "No error text defined.";
-                break;
-        }
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlNanoHTTPConnectHost:  %s '%s' - %s",
-                        "Failed to resolve host", host, h_err_txt);
+           const char *h_err_txt = "";
+
+           switch (h_errno) {
+               case HOST_NOT_FOUND:
+                   h_err_txt = "Authoritive host not found";
+                   break;
+
+               case TRY_AGAIN:
+                   h_err_txt =
+                       "Non-authoritive host not found or server failure.";
+                   break;
+
+               case NO_RECOVERY:
+                   h_err_txt =
+                       "Non-recoverable errors:  FORMERR, REFUSED, or NOTIMP.";
+                   break;
+
+               case NO_ADDRESS:
+                   h_err_txt =
+                       "Valid name, no data record of requested type.";
+                   break;
+
+               default:
+                   h_err_txt = "No error text defined.";
+                   break;
+           }
+           xmlGenericError (xmlGenericErrorContext,
+               "xmlNanoHTTPConnectHost:  %s '%s' - %s",
+               "Failed to resolve host", host, h_err_txt);
 #else
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlNanoHTTPConnectHost:  %s '%s'",
-                        "Failed to resolve host", host);
+           xmlGenericError (xmlGenericErrorContext,
+               "xmlNanoHTTPConnectHost:  %s '%s'",
+               "Failed to resolve host", host);
 #endif
-        return (-1);
-    }
+           return (-1);
+       }
 
-    for (i = 0; h->h_addr_list[i]; i++) {
-        if (h->h_addrtype == AF_INET) {
-            /* A records (IPv4) */
-            memcpy(&ia, h->h_addr_list[i], h->h_length);
-            sockin.sin_family = h->h_addrtype;
-            sockin.sin_addr = ia;
-            sockin.sin_port = htons(port);
-            addr = (struct sockaddr *) &sockin;
+       for (i = 0; h->h_addr_list[i]; i++) {
+           if (h->h_addrtype == AF_INET) {
+               /* A records (IPv4) */
+               memcpy (&ia, h->h_addr_list[i], h->h_length);
+               sockin.sin_family = h->h_addrtype;
+               sockin.sin_addr = ia;
+               sockin.sin_port = htons (port);
+               addr = (struct sockaddr *) &sockin;
 #ifdef SUPPORT_IP6
-        } else if (h->h_addrtype == AF_INET6) {
-            /* AAAA records (IPv6) */
-            memcpy(&ia6, h->h_addr_list[i], h->h_length);
-            sockin6.sin_family = h->h_addrtype;
-            sockin6.sin_addr = ia6;
-            sockin6.sin_port = htons(port);
-            addr = (struct sockaddr *) &sockin6;
+           } else if (have_ipv6 () && (h->h_addrtype == AF_INET6)) {
+               /* AAAA records (IPv6) */
+               memcpy (&ia6, h->h_addr_list[i], h->h_length);
+               sockin6.sin6_family = h->h_addrtype;
+               sockin6.sin6_addr = ia6;
+               sockin6.sin6_port = htons (port);
+               addr = (struct sockaddr *) &sockin6;
 #endif
-        } else
-            break;              /* for */
+           } else
+               break;              /* for */
 
-        s = xmlNanoHTTPConnectAttempt(addr);
-        if (s != -1)
-            return (s);
+           s = xmlNanoHTTPConnectAttempt (addr);
+           if (s != -1)
+               return (s);
+       }
     }
-
 #ifdef DEBUG_HTTP
     xmlGenericError(xmlGenericErrorContext,
                     "xmlNanoHTTPConnectHost:  unable to connect to '%s'.\n",
@@ -1059,9 +1224,11 @@ xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input,
     char *bp, *p;
     int blen, ret;
     int head;
-    int xmt_bytes;
     int nbRedirects = 0;
     char *redirURL = NULL;
+#ifdef DEBUG_HTTP
+    int xmt_bytes;
+#endif
     
     if (URL == NULL) return(NULL);
     if (method == NULL) method = "GET";
@@ -1125,7 +1292,7 @@ retry:
     if (contentType && *contentType)
        blen += strlen(*contentType) + 16;
     blen += strlen(method) + strlen(ctxt->path) + 24;
-    bp = xmlMalloc(blen);
+    bp = xmlMallocAtomic(blen);
     if ( bp == NULL ) {
         xmlNanoHTTPFreeCtxt( ctxt );
        xmlGenericError( xmlGenericErrorContext,
@@ -1173,26 +1340,30 @@ retry:
     ctxt->outptr = ctxt->out = bp;
     ctxt->state = XML_NANO_HTTP_WRITE;
     blen = strlen( ctxt->out );
-    xmt_bytes = xmlNanoHTTPSend(ctxt, ctxt->out, blen );
 #ifdef DEBUG_HTTP
+    xmt_bytes = xmlNanoHTTPSend(ctxt, ctxt->out, blen );
     if ( xmt_bytes != blen )
         xmlGenericError( xmlGenericErrorContext,
                        "xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
                        xmt_bytes, blen,
                        "bytes of HTTP headers sent to host",
                        ctxt->hostname );
+#else
+    xmlNanoHTTPSend(ctxt, ctxt->out, blen );
 #endif
 
     if ( input != NULL ) {
+#ifdef DEBUG_HTTP
         xmt_bytes = xmlNanoHTTPSend( ctxt, input, ilen );
 
-#ifdef DEBUG_HTTP
        if ( xmt_bytes != ilen )
            xmlGenericError( xmlGenericErrorContext,
                        "xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
                        xmt_bytes, ilen,
                        "bytes of HTTP content sent to host",
                        ctxt->hostname );
+#else
+       xmlNanoHTTPSend( ctxt, input, ilen );
 #endif
     }