Applying IPv6 patch from Archana Shah <archana.shah@wipro.com>
closing bug #114837

* configure.in: Added checks for IPv6 support and getaddrinfo().

* acconfig.h: Defined HAVE_GETADDRINFO and SUPPORT_IP6.

* config.h.in: Defined HAVE_GETADDRINFO and SUPPORT_IP6.

* nanoftp.c: Structure xmlNanoFTPCtxt contains either sockaddr_storage
  field or sockaddr_in field, depending upon the availability of IPv6
  support.
  have_ipv6(): Added to check for run-time IPv6 support.
  (xmlNanoFTPScanURL), (xmlNanoFTPUpdateURL), (xmlNanoFTPScanProxy):
  Modified to parse a URI with IPv6 address given in [].
  (xmlNanoFTPConnect): Changed to use getaddrinfo for address
  resolution, if it is available on the system, as gethostbyname
  does not return IPv6 addresses on some platforms.
  (xmlNanoFTPGetConnection): Modified type of dataAddr variable to
  sockaddr_storage or sockaddr_in depending upon the IPv6 support.
  Sending EPSV, EPRT or PASV, PORT depending upon the type of address
  we are dealing with.

* nanohttp.c: (have_ipv6): Added to check for run-time IPv6 support.
  (xmlNanoHTTPScanURL), (xmlNanoHTTPScanProxy): Modified to parse
  a URI with IPv6 address given in [].
  (xmlNanoHTTPConnectHost): Modified to use getaddrinfo if it is
  available on the system. Also IPv6 addresses will be resolved by
  gethostbyname only if IPv6 run-time support is available.
  (xmlNanoHTTPConnectAttempt): Modified to deal with IPv6 address.

Daniel
diff --git a/ChangeLog b/ChangeLog
index aba71d0..6f769dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+Sat Jun 21 16:10:24 CEST 2003 Daniel Veillard <daniel@veillard.com>
+
+        Applying IPv6 patch from Archana Shah <archana.shah@wipro.com>
+	closing bug #114837
+
+	* configure.in: Added checks for IPv6 support and getaddrinfo().
+
+	* acconfig.h: Defined HAVE_GETADDRINFO and SUPPORT_IP6.
+
+	* config.h.in: Defined HAVE_GETADDRINFO and SUPPORT_IP6.
+
+	* nanoftp.c: Structure xmlNanoFTPCtxt contains either sockaddr_storage
+	  field or sockaddr_in field, depending upon the availability of IPv6
+	  support.
+	  have_ipv6(): Added to check for run-time IPv6 support.
+	  (xmlNanoFTPScanURL), (xmlNanoFTPUpdateURL), (xmlNanoFTPScanProxy):
+	  Modified to parse a URI with IPv6 address given in [].
+	  (xmlNanoFTPConnect): Changed to use getaddrinfo for address
+	  resolution, if it is available on the system, as gethostbyname
+	  does not return IPv6 addresses on some platforms.
+	  (xmlNanoFTPGetConnection): Modified type of dataAddr variable to
+	  sockaddr_storage or sockaddr_in depending upon the IPv6 support.
+	  Sending EPSV, EPRT or PASV, PORT depending upon the type of address
+	  we are dealing with.
+
+	* nanohttp.c: (have_ipv6): Added to check for run-time IPv6 support.
+	  (xmlNanoHTTPScanURL), (xmlNanoHTTPScanProxy): Modified to parse
+	  a URI with IPv6 address given in [].
+	  (xmlNanoHTTPConnectHost): Modified to use getaddrinfo if it is
+	  available on the system. Also IPv6 addresses will be resolved by
+	  gethostbyname only if IPv6 run-time support is available.
+	  (xmlNanoHTTPConnectAttempt): Modified to deal with IPv6 address.
+
 Sat Jun 14 18:46:51 CEST 2003 Igor Zlatkovic <igor@zlatkovic.com>
 
 	* win32/configure.js include/win32config.h 
diff --git a/acconfig.h b/acconfig.h
index 5a2d3a0..7e4d9b8 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -9,3 +9,9 @@
 #undef SOCKLEN_T
 #undef HAVE_LIBPTHREAD
 #undef HAVE_PTHREAD_H
+
+/* Define if IPV6 support is there */
+#undef SUPPORT_IP6
+
+/* Define if getaddrinfo is there */
+#undef HAVE_GETADDRINFO
diff --git a/config.h.in b/config.h.in
index a5d52cb..3464eee 100644
--- a/config.h.in
+++ b/config.h.in
@@ -11,6 +11,12 @@
 #undef HAVE_LIBPTHREAD
 #undef HAVE_PTHREAD_H
 
+/* Define if IPv6 support is there. */
+#undef SUPPORT_IP6
+
+/* Define if you have the getaddrinfo function. */
+#undef HAVE_GETADDRINFO
+
 /* Define to 1 if you have the <ansidecl.h> header file. */
 #undef HAVE_ANSIDECL_H
 
diff --git a/configure.in b/configure.in
index a2dfa32..ae9b177 100644
--- a/configure.in
+++ b/configure.in
@@ -192,6 +192,42 @@
       AC_MSG_WARN(could not determine)])])])
 AC_DEFINE_UNQUOTED(SOCKLEN_T, $SOCKLEN_T)
 
+dnl ***********************Checking for availability of IPv6*******************
+
+AC_MSG_CHECKING([whether to enable IPv6])
+AC_ARG_ENABLE(ipv6, [ --enable-ipv6=[yes/no] enables compilation of IPv6 code],, enable_ipv6=yes)
+if test $enable_ipv6 = yes; then
+  have_ipv6=no
+  AC_TRY_COMPILE([
+    #include <sys/socket.h>
+    #include <sys/types.h>], [
+    struct sockaddr_storage ss;
+    socket(AF_INET6, SOCK_STREAM, 0)
+    ],
+    have_ipv6=yes,
+    have_ipv6=no
+  )
+  AC_MSG_RESULT($have_ipv6)
+
+  if test $have_ipv6=yes; then
+    AC_DEFINE(SUPPORT_IP6)
+
+    have_getaddrinfo=no
+    AC_CHECK_FUNC(getaddrinfo, have_getaddrinfo=yes)
+    if test $have_getaddrinfo != yes; then
+      for lib in bsd socket inet; do
+        AC_CHECK_LIB($lib, getaddrinfo, [LIBS="$LIBS -l$lib";have_getaddrinfo=yes;break])
+      done
+    fi
+
+    if test $have_getaddrinfo=yes; then
+      AC_DEFINE(HAVE_GETADDRINFO)
+    fi
+  fi
+fi 
+
+dnl ******************************End IPv6 checks******************************
+
 dnl Checks for isnan in libm if not in libc
 AC_CHECK_FUNC(isnan, , AC_CHECK_LIB(m, isnan,
   [AC_DEFINE(HAVE_ISNAN)]))
diff --git a/nanoftp.c b/nanoftp.c
index 8df6f29..bd3f0d5 100644
--- a/nanoftp.c
+++ b/nanoftp.c
@@ -62,6 +62,7 @@
 #include <libxml/uri.h>
 #include <libxml/nanoftp.h>
 #include <libxml/globals.h>
+#include <config.h>
 
 /* #define DEBUG_FTP 1  */
 #ifdef STANDALONE
@@ -93,7 +94,11 @@
     char *path;		/* the path within the URL */
     char *user;		/* user string */
     char *passwd;	/* passwd string */
+#ifdef SUPPORT_IP6
+    struct sockaddr_storage ftpAddr; /* this is large enough to hold IPv6 address*/
+#else
     struct sockaddr_in ftpAddr; /* the socket address struct */
+#endif
     int passive;	/* currently we support only passive !!! */
     SOCKET controlFd;	/* the file descriptor for the control socket */
     SOCKET dataFd;	/* the file descriptor for the data socket */
@@ -113,6 +118,19 @@
 static char *proxyPasswd = NULL;/* passwd for proxy authentication */
 static int proxyType = 0;	/* uses TYPE or a@b ? */
 
+#ifdef SUPPORT_IP6
+static int have_ipv6() {
+    int s;
+
+    s = socket (AF_INET6, SOCK_STREAM, 0);
+    if (s != -1) {
+	close (s);
+	return (1);
+    }
+    return (0);
+}
+#endif
+
 /**
  * xmlNanoFTPInit:
  *
@@ -289,26 +307,64 @@
     }
 
     while (1) {
-        if (cur[0] == ':') {
+	if ((strchr (cur, '[') && !strchr (cur, ']')) ||
+		(!strchr (cur, '[') && strchr (cur, ']'))) {
+	    xmlGenericError (xmlGenericErrorContext, "\nxmlNanoFTPScanURL: %s",
+		    "Syntax Error\n");
+	    return;
+	}
+
+	if (cur[0] == '[') {
+	    cur++;
+	    while (cur[0] != ']')
+		buf[indx++] = *cur++;
+
+	    if (!strchr (buf, ':')) {
+		xmlGenericError (xmlGenericErrorContext, "\nxmlNanoFTPScanURL: %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 {     /* address is an IPv4 one*/
+	    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++;
     }
@@ -371,29 +427,69 @@
 
     buf[indx] = 0;
     while (1) {
-        if (cur[0] == ':') {
+	if ((strchr (cur, '[') && !strchr (cur, ']')) ||
+		(!strchr (cur, '[') && strchr (cur, ']'))) {
+	    xmlGenericError (xmlGenericErrorContext, "\nxmlNanoFTPUpdateURL: %s",
+		    "Syntax Error\n");
+	    return (-1);
+	}
+
+	if (cur[0] == '[') {
+	    cur++;
+	    while (cur[0] != ']')
+		buf[indx++] = *cur++;
+
+	    if (!strchr (buf, ':')) {
+		xmlGenericError (xmlGenericErrorContext, "\nxmlNanoFTPUpdateURL: %s",
+			"Use [IPv6]/IPv4 format\n");
+		return (-1);
+	    }
+
 	    buf[indx] = 0;
-	    if (strcmp(ctxt->hostname, buf))
-		return(-1);
+	    if (strcmp (ctxt->hostname, buf))
+		return (-1);
 	    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 != ctxt->port)
+		    return (-1);
+		while ((cur[0] != '/') && (*cur != 0))
+		    cur++;
 	    }
-	    if (port != ctxt->port)
-		return(-1);
-	    while ((cur[0] != '/') && (*cur != 0)) 
-	        cur++;
 	    break;
 	}
-        if ((*cur == '/') || (*cur == 0)) {
-	    buf[indx] = 0;
-	    if (strcmp(ctxt->hostname, buf))
-		return(-1);
-	    indx = 0;
-	    break;
+	else {
+	    if (cur[0] == ':') {
+		buf[indx] = 0;
+		if (strcmp (ctxt->hostname, buf))
+		    return (-1);
+		indx = 0;
+		cur += 1;
+		while ((*cur >= '0') && (*cur <= '9')) {
+		    port *= 10;
+		    port += *cur - '0';
+		    cur++;
+		}
+		if (port != ctxt->port)
+		    return (-1);
+		while ((cur[0] != '/') && (*cur != 0)) 
+		    cur++;
+		break;
+	    }
+	    if ((*cur == '/') || (*cur == 0)) {
+		buf[indx] = 0;
+		if (strcmp (ctxt->hostname, buf))
+		    return (-1);
+		indx = 0;
+		break;
+	    }
 	}
 	buf[indx++] = *cur++;
     }
@@ -460,26 +556,63 @@
 
     buf[indx] = 0;
     while (1) {
-        if (cur[0] == ':') {
+	if ((strchr (cur, '[') && !strchr (cur, ']')) ||
+		(!strchr (cur, '[') && strchr (cur, ']'))) {
+	    xmlGenericError (xmlGenericErrorContext, "\nxmlNanoFTPScanProxy: %s",
+		    "Syntax error\n");
+	    return;
+	}
+
+	if (cur[0] == '[') {
+	    cur++;
+	    while (cur[0] != ']')
+		buf[indx++] = *cur++;
+	    if (!strchr (buf, ':')) {
+		xmlGenericError (xmlGenericErrorContext, "\nxmlNanoFTPScanProxy: %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';
+	    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++;
 	    }
-	    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++;
     }
@@ -865,6 +998,7 @@
     struct hostent *hp;
     int port;
     int res;
+    int addrlen;
 
     if (ctxt == NULL)
 	return(-1);
@@ -874,19 +1008,6 @@
     /*
      * do the blocking DNS query.
      */
-    if (proxy)
-	hp = gethostbyname(proxy);
-    else
-	hp = gethostbyname(ctxt->hostname);
-    if (hp == NULL)
-        return(-1);
-
-    /*
-     * Prepare the socket
-     */
-    memset(&ctxt->ftpAddr, 0, sizeof(ctxt->ftpAddr));
-    ctxt->ftpAddr.sin_family = AF_INET;
-    memcpy(&ctxt->ftpAddr.sin_addr, hp->h_addr_list[0], hp->h_length);
     if (proxy) {
         port = proxyPort;
     } else {
@@ -894,8 +1015,65 @@
     }
     if (port == 0)
 	port = 21;
-    ctxt->ftpAddr.sin_port = htons(port);
-    ctxt->controlFd = socket(AF_INET, SOCK_STREAM, 0);
+
+    memset (&ctxt->ftpAddr, 0, sizeof(ctxt->ftpAddr));
+
+#ifdef SUPPORT_IP6
+    if (have_ipv6 ()) {
+	struct addrinfo hints, *res, *result;
+
+	result = NULL;
+	memset (&hints, 0, sizeof(hints));
+	hints.ai_socktype = SOCK_STREAM;
+
+	if (proxy) {
+	    if (getaddrinfo (proxy, NULL, &hints, &result) != 0)
+		return (-1);
+	}
+	else
+	    if (getaddrinfo (ctxt->hostname, NULL, &hints, &result) != 0)
+		return (-1);
+
+	for (res = result; res; res = res->ai_next)
+	    if (res->ai_family == AF_INET || res->ai_family == AF_INET6)
+		break;
+
+	if (res) {
+	    if (res->ai_family == AF_INET6) {
+		memcpy (&ctxt->ftpAddr, res->ai_addr, res->ai_addrlen);
+		((struct sockaddr_in6 *) &ctxt->ftpAddr)->sin6_port = htons (port);
+		ctxt->controlFd = socket (AF_INET6, SOCK_STREAM, 0);
+	    }
+	    else {
+		memcpy (&ctxt->ftpAddr, res->ai_addr, res->ai_addrlen);
+		((struct sockaddr_in *) &ctxt->ftpAddr)->sin_port = htons (port);
+		ctxt->controlFd = socket (AF_INET, SOCK_STREAM, 0);
+	    }
+	    addrlen = res->ai_addrlen;
+	    freeaddrinfo (result);
+	}
+    }
+    else
+#endif
+    {
+	if (proxy)
+	    hp = gethostbyname (proxy);
+	else
+	    hp = gethostbyname (ctxt->hostname);
+	if (hp == NULL)
+	    return (-1);
+
+    /*
+     * Prepare the socket
+     */
+	((struct sockaddr_in *)&ctxt->ftpAddr)->sin_family = AF_INET;
+	memcpy (&((struct sockaddr_in *)&ctxt->ftpAddr)->sin_addr,
+		hp->h_addr_list[0], hp->h_length);
+	((struct sockaddr_in *)&ctxt->ftpAddr)->sin_port = htons (port);
+	ctxt->controlFd = socket (AF_INET, SOCK_STREAM, 0);
+	addrlen = sizeof (struct sockaddr_in);
+    }
+
     if (ctxt->controlFd < 0)
         return(-1);
 
@@ -903,7 +1081,7 @@
      * Do the connect.
      */
     if (connect(ctxt->controlFd, (struct sockaddr *) &ctxt->ftpAddr,
-                sizeof(struct sockaddr_in)) < 0) {
+	    addrlen) < 0) {
         closesocket(ctxt->controlFd); ctxt->controlFd = -1;
         ctxt->controlFd = -1;
 	return(-1);
@@ -1293,22 +1471,41 @@
     int res;
     unsigned char ad[6], *adp, *portp;
     unsigned int temp[6];
+#ifdef SUPPORT_IP6
+    struct sockaddr_storage dataAddr;
+#else
     struct sockaddr_in dataAddr;
+#endif
     SOCKLEN_T dataAddrLen;
 
-    ctxt->dataFd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if (ctxt->dataFd < 0) {
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPGetConnection: failed to create socket\n");
-	return(-1);
+    memset (&dataAddr, 0, sizeof(dataAddr));
+#ifdef SUPPORT_IP6
+    if ((ctxt->ftpAddr).ss_family == AF_INET6) {
+	ctxt->dataFd = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+	((struct sockaddr_in6 *)&dataAddr)->sin6_family = AF_INET6;
+	dataAddrLen = sizeof(struct sockaddr_in6);
+    } else
+#endif
+    {
+	ctxt->dataFd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	((struct sockaddr_in *)&dataAddr)->sin_family = AF_INET;
+	dataAddrLen = sizeof (struct sockaddr_in);
     }
-    dataAddrLen = sizeof(dataAddr);
-    memset(&dataAddr, 0, dataAddrLen);
-    dataAddr.sin_family = AF_INET;
+
+    if (ctxt->dataFd < 0) {
+	xmlGenericError (xmlGenericErrorContext,
+		"xmlNanoFTPGetConnection: failed to create socket\n");
+	return (-1);
+    }
 
     if (ctxt->passive) {
-	snprintf(buf, sizeof(buf), "PASV\r\n");
-        len = strlen(buf);
+#ifdef SUPPORT_IP6
+	if ((ctxt->ftpAddr).ss_family == AF_INET6)
+	    snprintf (buf, sizeof(buf), "EPSV\r\n");
+	else
+#endif
+	    snprintf (buf, sizeof(buf), "PASV\r\n");
+        len = strlen (buf);
 #ifdef DEBUG_FTP
 	xmlGenericError(xmlGenericErrorContext, "%s", buf);
 #endif
@@ -1332,18 +1529,36 @@
 	}
 	cur = &ctxt->controlBuf[ctxt->controlBufAnswer]; 
 	while (((*cur < '0') || (*cur > '9')) && *cur != '\0') cur++;
-	if (sscanf(cur, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2],
-	            &temp[3], &temp[4], &temp[5]) != 6) {
-	    xmlGenericError(xmlGenericErrorContext,
-		    "Invalid answer to PASV\n");
-	    if (ctxt->dataFd != -1) {
-		closesocket(ctxt->dataFd); ctxt->dataFd = -1;
+#ifdef SUPPORT_IP6
+	if ((ctxt->ftpAddr).ss_family == AF_INET6) {
+	    if (sscanf (cur, "%u", &temp[0]) != 1) {
+		xmlGenericError (xmlGenericErrorContext,
+			"Invalid answer to EPSV\n");
+		if (ctxt->dataFd != -1) {
+		    closesocket (ctxt->dataFd); ctxt->dataFd = -1;
+		}
+		return (-1);
 	    }
-	    return(-1);
+	    memcpy (&((struct sockaddr_in6 *)&dataAddr)->sin6_addr, &((struct sockaddr_in6 *)&ctxt->ftpAddr)->sin6_addr, sizeof(struct in6_addr));
+	    ((struct sockaddr_in6 *)&dataAddr)->sin6_port = htons (temp[0]);
 	}
-	for (i=0; i<6; i++) ad[i] = (unsigned char) (temp[i] & 0xff);
-	memcpy(&dataAddr.sin_addr, &ad[0], 4);
-	memcpy(&dataAddr.sin_port, &ad[4], 2);
+	else
+#endif
+	{
+	    if (sscanf (cur, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2],
+		&temp[3], &temp[4], &temp[5]) != 6) {
+		xmlGenericError (xmlGenericErrorContext,
+			"Invalid answer to PASV\n");
+		if (ctxt->dataFd != -1) {
+		    closesocket (ctxt->dataFd); ctxt->dataFd = -1;
+		}
+		return (-1);
+	    }
+	    for (i=0; i<6; i++) ad[i] = (unsigned char) (temp[i] & 0xff);
+	    memcpy (&((struct sockaddr_in *)&dataAddr)->sin_addr, &ad[0], 4);
+	    memcpy (&((struct sockaddr_in *)&dataAddr)->sin_port, &ad[4], 2);
+	}
+
 	if (connect(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) {
 	    xmlGenericError(xmlGenericErrorContext,
 		    "Failed to create a data connection\n");
@@ -1352,7 +1567,13 @@
 	}
     } else {
         getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen);
-	dataAddr.sin_port = 0;
+#ifdef SUPPORT_IP6
+	if ((ctxt->ftpAddr).ss_family == AF_INET6)
+	    ((struct sockaddr_in6 *)&dataAddr)->sin6_port = 0;
+	else
+#endif
+	    ((struct sockaddr_in *)&dataAddr)->sin_port = 0;
+
 	if (bind(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) {
 	    xmlGenericError(xmlGenericErrorContext,
 		    "Failed to bind a port\n");
@@ -1362,17 +1583,37 @@
         getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen);
 
 	if (listen(ctxt->dataFd, 1) < 0) {
-	    xmlGenericError(xmlGenericErrorContext,
-		    "Could not listen on port %d\n",
-	            ntohs(dataAddr.sin_port));
+#ifdef SUPPORT_IP6
+	    if ((ctxt->ftpAddr).ss_family == AF_INET6)
+		xmlGenericError (xmlGenericErrorContext,
+			"Could not listen on port %d\n",
+			ntohs (((struct sockaddr_in6 *)&dataAddr)->sin6_port));
+	    else
+#endif
+		xmlGenericError (xmlGenericErrorContext,
+			"Could not listen on port %d\n",
+			ntohs (((struct sockaddr_in *)&dataAddr)->sin_port));
 	    closesocket(ctxt->dataFd); ctxt->dataFd = -1;
 	    return (-1);
 	}
-	adp = (unsigned char *) &dataAddr.sin_addr;
-	portp = (unsigned char *) &dataAddr.sin_port;
-	snprintf(buf, sizeof(buf), "PORT %d,%d,%d,%d,%d,%d\r\n",
-	       adp[0] & 0xff, adp[1] & 0xff, adp[2] & 0xff, adp[3] & 0xff,
-	       portp[0] & 0xff, portp[1] & 0xff);
+#ifdef SUPPORT_IP6
+	if ((ctxt->ftpAddr).ss_family == AF_INET6) {
+	    char buf6[INET6_ADDRSTRLEN];
+	    inet_ntop (AF_INET6, &((struct sockaddr_in6 *)&dataAddr)->sin6_addr,
+		    buf6, INET6_ADDRSTRLEN);
+	    adp = buf6;
+	    portp = (unsigned char *) &((struct sockaddr_in6 *)&dataAddr)->sin6_port;
+	    snprintf (buf, sizeof(buf), "EPRT |2|%s|%s|\r\n", adp, portp);
+        } else
+#endif
+	{
+	    adp = (unsigned char *) &((struct sockaddr_in *)&dataAddr)->sin_addr;
+	    portp = (unsigned char *) &((struct sockaddr_in *)&dataAddr)->sin_port;
+	    snprintf (buf, sizeof(buf), "PORT %d,%d,%d,%d,%d,%d\r\n",
+	    adp[0] & 0xff, adp[1] & 0xff, adp[2] & 0xff, adp[3] & 0xff,
+	    portp[0] & 0xff, portp[1] & 0xff);
+	}
+
         buf[sizeof(buf) - 1] = 0;
         len = strlen(buf);
 #ifdef DEBUG_FTP
diff --git a/nanohttp.c b/nanohttp.c
index 8c5f995..d94f6d9 100644
--- a/nanohttp.c
+++ b/nanohttp.c
@@ -77,6 +77,7 @@
 #include <libxml/nanohttp.h>
 #include <libxml/globals.h>
 #include <libxml/uri.h>
+#include <config.h>
 
 /**
  * A couple portability macros
@@ -149,6 +150,19 @@
 #endif
 }
 
+#ifdef SUPPORT_IP6
+static int have_ipv6() {
+    int s;
+
+    s = socket (AF_INET6, SOCK_STREAM, 0);
+    if (s != -1) {
+	close (s);
+	return (1);
+    }
+    return (0);
+}
+#endif
+
 /**
  * xmlNanoHTTPInit:
  *
@@ -253,26 +267,64 @@
 
     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 +387,64 @@
 
     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++;
     }
@@ -711,11 +801,23 @@
 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 +866,7 @@
 #endif /* !VMS */
 #endif /* !_WINSOCKAPI_ */
 
-    if ((connect(s, addr, sizeof(*addr))==-1)) {
+    if (connect (s, addr, addrlen) == -1) {
 	switch (socket_errno()) {
 	    case EINPROGRESS:
 	    case EWOULDBLOCK:
@@ -862,13 +964,64 @@
     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) {
+		if (res->ai_family == AF_INET6) {
+		    memcpy (&sockin6, res->ai_addr, res->ai_addrlen);
+		    sockin6.sin6_port = htons (port);
+		    addr = (struct sockaddr *)&sockin6;
+		}
+
+		if (res->ai_family == AF_INET) {
+		    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);
+		}
+	    }
+	    else {
+		freeaddrinfo (result);
+		return (-1);
+	    }
+	}
+    } else
 #endif
-    h = gethostbyname(host);
-    if (h == NULL) {
+#endif
+    {   
+	h = gethostbyname (host);
+	if (h == NULL) {
 
 /*
  * Okay, I got fed up by the non-portability of this error message
@@ -876,68 +1029,68 @@
  * 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 = "";
+	    const char *h_err_txt = "";
 
-        switch (h_errno) {
-            case HOST_NOT_FOUND:
-                h_err_txt = "Authoritive host not found";
-                break;
+	    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 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_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;
+		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);
+		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",