1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2024-10-26 12:25:09 +03:00

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
This commit is contained in:
Daniel Veillard 2003-06-21 14:20:04 +00:00
parent e8b5b0f148
commit de2a67b430
6 changed files with 648 additions and 173 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -192,6 +192,42 @@ AC_TRY_COMPILE2([
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)]))

415
nanoftp.c
View File

@ -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 @@ typedef struct xmlNanoFTPCtxt {
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 *proxyUser = NULL; /* user for proxy authentication */
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 @@ xmlNanoFTPScanURL(void *ctx, const char *URL) {
}
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 @@ xmlNanoFTPUpdateURL(void *ctx, const char *URL) {
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 @@ xmlNanoFTPScanProxy(const char *URL) {
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 @@ xmlNanoFTPConnect(void *ctx) {
struct hostent *hp;
int port;
int res;
int addrlen;
if (ctxt == NULL)
return(-1);
@ -874,19 +1008,6 @@ xmlNanoFTPConnect(void *ctx) {
/*
* 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 @@ xmlNanoFTPConnect(void *ctx) {
}
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 @@ xmlNanoFTPConnect(void *ctx) {
* 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 @@ xmlNanoFTPGetConnection(void *ctx) {
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);
}
if (ctxt->dataFd < 0) {
xmlGenericError (xmlGenericErrorContext,
"xmlNanoFTPGetConnection: failed to create socket\n");
return (-1);
}
dataAddrLen = sizeof(dataAddr);
memset(&dataAddr, 0, dataAddrLen);
dataAddr.sin_family = AF_INET;
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 @@ xmlNanoFTPGetConnection(void *ctx) {
}
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 @@ xmlNanoFTPGetConnection(void *ctx) {
}
} 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 @@ xmlNanoFTPGetConnection(void *ctx) {
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

View File

@ -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 @@ static int socket_errno(void) {
#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 @@ 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 +387,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++;
}
@ -711,11 +801,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 +866,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:
@ -862,13 +964,64 @@ 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) {
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 @@ 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 = "";
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",