Fixed the way the control connection was handled,
Fixed the spec file,
Released 1.8.9,
Daniel
diff --git a/ChangeLog b/ChangeLog
index 3408a1b..997dbf8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Mon Jul 10 16:08:05 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
+
+ * configure.in: 1.8.9
+ * config.spec.in: more spec and dependances fixes
+ * nanoftp.c: fixed a the way the control connection was handled
+
Sun Jul 2 20:27:34 MEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* config.spec.in: fixed bug #7419, devel with same %ver
diff --git a/configure.in b/configure.in
index 97c3e94..d39b617 100644
--- a/configure.in
+++ b/configure.in
@@ -5,7 +5,7 @@
LIBXML_MAJOR_VERSION=1
LIBXML_MINOR_VERSION=8
-LIBXML_MICRO_VERSION=8
+LIBXML_MICRO_VERSION=9
LIBXML_VERSION=$LIBXML_MAJOR_VERSION.$LIBXML_MINOR_VERSION.$LIBXML_MICRO_VERSION
LIBXML_VERSION_INFO=`expr $LIBXML_MAJOR_VERSION + $LIBXML_MINOR_VERSION`:$LIBXML_MICRO_VERSION:$LIBXML_MINOR_VERSION
diff --git a/libxml.spec.in b/libxml.spec.in
index 33955af..00b21cb 100644
--- a/libxml.spec.in
+++ b/libxml.spec.in
@@ -7,10 +7,9 @@
Version: %ver
Release: 1
Copyright: LGPL
-Group: X11/Libraries
+Group: Development/Libraries
Source: ftp://ftp.gnome.org/pub/GNOME/sources/libxml/libxml-%{ver}.tar.gz
BuildRoot: /var/tmp/libxml-%{PACKAGE_VERSION}-root
-Provides: libxml.so.0
URL: http://rpmfind.net/veillard/XML/
Prereq: /sbin/install-info
@@ -21,8 +20,8 @@
%package devel
Summary: Libraries, includes, etc to develop libxml applications
-Group: X11/libraries
-Requires: libxml=%ver
+Group: Development/Libraries
+Requires: libxml = %{version}
%description devel
Libraries, include files, etc you can use to develop libxml applications.
@@ -84,10 +83,10 @@
# hack to get libxml.so.0 too !
# Get rid of it once deps to libxml.so.0 have disapeared.
#
-if [ -f $RPM_BUILD_ROOT/%{prefix}/lib/libxml.so.@VERSION@ ]
-then
- (cd $RPM_BUILD_ROOT/%{prefix}/lib/ ; cp libxml.so.@VERSION@ libxml.so.0.99.0 ; ln -sf libxml.so.0.99.0 libxml.so.0)
-fi
+#if [ -f $RPM_BUILD_ROOT/%{prefix}/lib/libxml.so.@VERSION@ ]
+#then
+# (cd $RPM_BUILD_ROOT/%{prefix}/lib/ ; cp libxml.so.@VERSION@ libxml.so.0.99.0 ; ln -sf libxml.so.0.99.0 libxml.so.0)
+#fi
#
# another hack to get /usr/include/gnome-xml/libxml/
#
diff --git a/nanoftp.c b/nanoftp.c
index 4fa3885..43694a2 100644
--- a/nanoftp.c
+++ b/nanoftp.c
@@ -1,6 +1,5 @@
-/**
- * ftp.c: basic handling of an FTP command connection to check for
- * directory availability. No transfer is needed.
+/*
+ * nanoftp.c: basic FTP client support
*
* Reference: RFC 959
*/
@@ -15,17 +14,12 @@
#include <stdio.h>
#include <string.h>
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -50,12 +44,6 @@
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
-#ifdef HAVE_RESOLV_H
-#include <resolv.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
@@ -75,6 +63,7 @@
#define FTP_COMMAND_OK 200
#define FTP_SYNTAX_ERROR 500
#define FTP_GET_PASSWD 331
+#define FTP_BUF_SIZE 512
typedef struct xmlNanoFTPCtxt {
char *protocol; /* the protocol name */
@@ -89,6 +78,11 @@
int dataFd; /* the file descriptor for the data socket */
int state; /* WRITE / READ / CLOSED */
int returnValue; /* the protocol return value */
+ /* buffer for data received from the control connection */
+ char controlBuf[FTP_BUF_SIZE + 1];
+ int controlBufIndex;
+ int controlBufUsed;
+ int controlBufAnswer;
} xmlNanoFTPCtxt, *xmlNanoFTPCtxtPtr;
static int initialized = 0;
@@ -446,7 +440,7 @@
* Returns an FTP context or NULL in case of error.
*/
-void *
+void*
xmlNanoFTPNewCtxt(const char *URL) {
xmlNanoFTPCtxtPtr ret;
@@ -457,6 +451,8 @@
ret->port = 21;
ret->passive = 1;
ret->returnValue = 0;
+ ret->controlBufIndex = 0;
+ ret->controlBufUsed = 0;
if (URL != NULL)
xmlNanoFTPScanURL(ret, URL);
@@ -481,12 +477,20 @@
ctxt->passive = 1;
if (ctxt->controlFd >= 0) close(ctxt->controlFd);
ctxt->controlFd = -1;
+ ctxt->controlBufIndex = -1;
+ ctxt->controlBufUsed = -1;
xmlFree(ctxt);
}
/**
+ * xmlNanoFTPParseResponse:
+ * @ctx: the FTP connection context
+ * @buf: the buffer containing the response
+ * @len: the buffer length
+ *
* Parsing of the server answer, we just extract the code.
- * return 0 for errors
+ *
+ * returns 0 for errors
* +XXX for last line of response
* -XXX for response to be continued
*/
@@ -516,59 +520,136 @@
}
/**
+ * xmlNanoFTPGetMore:
+ * @ctx: an FTP context
+ *
+ * Read more information from the FTP control connection
+ * Returns the number of bytes read, < 0 indicates an error
+ */
+static int
+xmlNanoFTPGetMore(void *ctx) {
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
+ int len;
+ int size;
+
+ if ((ctxt->controlBufIndex < 0) || (ctxt->controlBufIndex > FTP_BUF_SIZE)) {
+#ifdef DEBUG_FTP
+ printf("xmlNanoFTPGetMore : controlBufIndex = %d\n",
+ ctxt->controlBufIndex);
+#endif
+ return(-1);
+ }
+
+ if ((ctxt->controlBufUsed < 0) || (ctxt->controlBufUsed > FTP_BUF_SIZE)) {
+#ifdef DEBUG_FTP
+ printf("xmlNanoFTPGetMore : controlBufUsed = %d\n",
+ ctxt->controlBufUsed);
+#endif
+ return(-1);
+ }
+ if (ctxt->controlBufIndex > ctxt->controlBufUsed) {
+#ifdef DEBUG_FTP
+ printf("xmlNanoFTPGetMore : controlBufIndex > controlBufUsed %d > %d\n",
+ ctxt->controlBufIndex, ctxt->controlBufUsed);
+#endif
+ return(-1);
+ }
+
+ /*
+ * First pack the control buffer
+ */
+ if (ctxt->controlBufIndex > 0) {
+ memmove(&ctxt->controlBuf[0], &ctxt->controlBuf[ctxt->controlBufIndex],
+ ctxt->controlBufUsed - ctxt->controlBufIndex);
+ ctxt->controlBufUsed -= ctxt->controlBufIndex;
+ ctxt->controlBufIndex = 0;
+ }
+ size = FTP_BUF_SIZE - ctxt->controlBufUsed;
+ if (size == 0) {
+#ifdef DEBUG_FTP
+ printf("xmlNanoFTPGetMore : buffer full %d \n", ctxt->controlBufUsed);
+#endif
+ return(0);
+ }
+
+ /*
+ * Read the amount left on teh control connection
+ */
+ if ((len = recv(ctxt->controlFd, &ctxt->controlBuf[ctxt->controlBufIndex],
+ size, 0)) < 0) {
+ close(ctxt->controlFd); ctxt->controlFd = -1;
+ ctxt->controlFd = -1;
+ return(-1);
+ }
+#ifdef DEBUG_FTP
+ printf("xmlNanoFTPGetMore : read %d [%d - %d]\n", len,
+ ctxt->controlBufUsed, ctxt->controlBufUsed + len);
+#endif
+ ctxt->controlBufUsed += len;
+ ctxt->controlBuf[ctxt->controlBufUsed] = 0;
+
+ return(len);
+}
+
+/**
* xmlNanoFTPReadResponse:
* @ctx: an FTP context
- * @buf: buffer to read in
- * @size: buffer length
*
* Read the response from the FTP server after a command.
* Returns the code number
*/
static int
-xmlNanoFTPReadResponse(void *ctx, char *buf, int size) {
+xmlNanoFTPReadResponse(void *ctx) {
xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
char *ptr, *end;
int len;
- int res = -1;
-
- if (size <= 0) return(-1);
+ int res = -1, cur = -1;
get_more:
- if ((len = recv(ctxt->controlFd, buf, size - 1, 0)) < 0) {
- close(ctxt->controlFd); ctxt->controlFd = -1;
- ctxt->controlFd = -1;
+ /*
+ * Assumes everything up to controlBuf[controlBufIndex] has been read
+ * and analyzed.
+ */
+ len = xmlNanoFTPGetMore(ctx);
+ if ((ctxt->controlBufUsed == 0) && (len == 0)) {
return(-1);
}
- if (len == 0) {
- return(-1);
- }
+ ptr = &ctxt->controlBuf[ctxt->controlBufIndex];
+ end = &ctxt->controlBuf[ctxt->controlBufUsed];
- end = &buf[len];
- *end = 0;
#ifdef DEBUG_FTP
- printf(buf);
+ printf("\n<<<\n%s\n--\n", ptr);
#endif
- ptr = buf;
while (ptr < end) {
- res = xmlNanoFTPParseResponse(ctxt, ptr, end - ptr);
- if (res > 0) break;
- if (res == 0) {
-#ifdef DEBUG_FTP
- fprintf(stderr, "xmlNanoFTPReadResponse failed: %s\n", ptr);
-#endif
- return(-1);
+ cur = xmlNanoFTPParseResponse(ctxt, ptr, end - ptr);
+ if (cur > 0) {
+ /*
+ * Successfully scanned the control code, scratch
+ * till the end of the line, but keep the index to be
+ * able to analyze the result if needed.
+ */
+ res = cur;
+ ptr += 3;
+ ctxt->controlBufAnswer = ptr - ctxt->controlBuf;
+ while ((ptr < end) && (*ptr != '\n')) ptr++;
+ if (*ptr == '\n') ptr++;
+ if (*ptr == '\r') ptr++;
+ break;
}
while ((ptr < end) && (*ptr != '\n')) ptr++;
if (ptr >= end) {
-#ifdef DEBUG_FTP
- fprintf(stderr, "xmlNanoFTPReadResponse: unexpected end %s\n", buf);
-#endif
- return((-res) / 100);
+ ctxt->controlBufIndex = ctxt->controlBufUsed;
+ goto get_more;
}
if (*ptr != '\r') ptr++;
}
if (res < 0) goto get_more;
+ ctxt->controlBufIndex = ptr - ctxt->controlBuf;
+#ifdef DEBUG_FTP
+ ptr = &ctxt->controlBuf[ctxt->controlBufIndex];
+ printf("\n---\n%s\n--\n", ptr);
+#endif
#ifdef DEBUG_FTP
printf("Got %d\n", res);
@@ -586,22 +667,11 @@
int
xmlNanoFTPGetResponse(void *ctx) {
- char buf[16 * 1024 + 1];
-
-/**************
- fd_set rfd;
- struct timeval tv;
int res;
- tv.tv_sec = 10;
- tv.tv_usec = 0;
- FD_ZERO(&rfd);
- FD_SET(ctxt->controlFd, &rfd);
- res = select(ctxt->controlFd + 1, &rfd, NULL, NULL, &tv);
- if (res <= 0) return(res);
- **************/
+ res = xmlNanoFTPReadResponse(ctx);
- return(xmlNanoFTPReadResponse(ctx, buf, 16 * 1024));
+ return(res);
}
/**
@@ -615,7 +685,6 @@
int
xmlNanoFTPCheckResponse(void *ctx) {
xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
- char buf[1024 + 1];
fd_set rfd;
struct timeval tv;
@@ -634,7 +703,7 @@
}
- return(xmlNanoFTPReadResponse(ctx, buf, 1024));
+ return(xmlNanoFTPReadResponse(ctx));
}
/**
@@ -869,10 +938,11 @@
else
#ifndef HAVE_SNPRINTF
len = sprintf(buf, "PASS libxml@%s\r\n",
+ hostname);
#else /* HAVE_SNPRINTF */
len = snprintf(buf, sizeof(buf), "PASS libxml@%s\r\n",
-#endif /* HAVE_SNPRINTF */
hostname);
+#endif /* HAVE_SNPRINTF */
#ifdef DEBUG_FTP
printf(buf);
#endif
@@ -1061,15 +1131,14 @@
/**
* xmlNanoFTPConnectTo:
* @server: an FTP server name
- * @directory: the port (use 21 if 0)
+ * @port: the port (use 21 if 0)
*
* Tries to open a control connection to the given server/port
*
- * Returns and fTP context or NULL if it failed
+ * Returns an fTP context or NULL if it failed
*/
-
-void *
+void*
xmlNanoFTPConnectTo(const char *server, int port) {
xmlNanoFTPCtxtPtr ctxt;
int res;
@@ -1077,7 +1146,7 @@
xmlNanoFTPInit();
if (server == NULL)
return(NULL);
- ctxt = xmlNanoFTPNewCtxt(NULL);
+ ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(NULL);
ctxt->hostname = xmlMemStrdup(server);
if (port != 0)
ctxt->port = port;
@@ -1090,7 +1159,7 @@
}
/**
- * xmlNanoFTPGetConnection:
+ * xmlNanoFTPCwd:
* @ctx: an FTP context
* @directory: a directory on the server
*
@@ -1177,7 +1246,7 @@
close(ctxt->dataFd); ctxt->dataFd = -1;
return(res);
}
- res = xmlNanoFTPReadResponse(ctx, buf, sizeof(buf) -1);
+ res = xmlNanoFTPReadResponse(ctx);
if (res != 2) {
if (res == 5) {
close(ctxt->dataFd); ctxt->dataFd = -1;
@@ -1190,12 +1259,14 @@
ctxt->passive = 0;
}
}
- cur = &buf[4];
+ cur = &ctxt->controlBuf[ctxt->controlBufAnswer];
while (((*cur < '0') || (*cur > '9')) && *cur != '\0') cur++;
if (sscanf(cur, "%d,%d,%d,%d,%d,%d", &temp[0], &temp[1], &temp[2],
&temp[3], &temp[4], &temp[5]) != 6) {
fprintf(stderr, "Invalid answer to PASV\n");
- close(ctxt->dataFd); ctxt->dataFd = -1;
+ if (ctxt->dataFd != -1) {
+ close(ctxt->dataFd); ctxt->dataFd = -1;
+ }
return(-1);
}
for (i=0; i<6; i++) ad[i] = (unsigned char) (temp[i] & 0xff);
@@ -1226,11 +1297,13 @@
portp = (unsigned char *) &dataAddr.sin_port;
#ifndef HAVE_SNPRINTF
len = sprintf(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);
#else /* HAVE_SNPRINTF */
len = 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);
#endif /* HAVE_SNPRINTF */
- adp[0] & 0xff, adp[1] & 0xff, adp[2] & 0xff, adp[3] & 0xff,
- portp[0] & 0xff, portp[1] & 0xff);
buf[sizeof(buf) - 1] = 0;
#ifdef DEBUG_FTP
printf(buf);
@@ -1264,13 +1337,34 @@
xmlNanoFTPCloseConnection(void *ctx) {
xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
int res;
+ fd_set rfd, efd;
+ struct timeval tv;
close(ctxt->dataFd); ctxt->dataFd = -1;
- res = xmlNanoFTPGetResponse(ctxt);
- if (res != 2) {
+ tv.tv_sec = 15;
+ tv.tv_usec = 0;
+ FD_ZERO(&rfd);
+ FD_SET(ctxt->controlFd, &rfd);
+ FD_ZERO(&efd);
+ FD_SET(ctxt->controlFd, &efd);
+ res = select(ctxt->controlFd + 1, &rfd, NULL, &efd, &tv);
+ if (res < 0) {
+#ifdef DEBUG_FTP
+ perror("select");
+#endif
close(ctxt->controlFd); ctxt->controlFd = -1;
return(-1);
}
+ if (res == 0) {
+ fprintf(stderr, "xmlNanoFTPCloseConnection: timeout\n");
+ close(ctxt->controlFd); ctxt->controlFd = -1;
+ } else {
+ res = xmlNanoFTPGetResponse(ctxt);
+ if (res != 2) {
+ close(ctxt->controlFd); ctxt->controlFd = -1;
+ return(-1);
+ }
+ }
return(0);
}
@@ -1427,6 +1521,8 @@
if (xmlNanoFTPCwd(ctxt, ctxt->path) < 1)
return(-1);
ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
+ if (ctxt->dataFd == -1)
+ return(-1);
#ifndef HAVE_SNPRINTF
len = sprintf(buf, "LIST -L\r\n");
#else /* HAVE_SNPRINTF */
@@ -1438,6 +1534,8 @@
return(-1);
}
ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
+ if (ctxt->dataFd == -1)
+ return(-1);
#ifndef HAVE_SNPRINTF
len = sprintf(buf, "LIST -L %s\r\n", filename);
#else /* HAVE_SNPRINTF */
@@ -1452,7 +1550,7 @@
close(ctxt->dataFd); ctxt->dataFd = -1;
return(res);
}
- res = xmlNanoFTPReadResponse(ctxt, buf, sizeof(buf) -1);
+ res = xmlNanoFTPReadResponse(ctxt);
if (res != 1) {
close(ctxt->dataFd); ctxt->dataFd = -1;
return(-res);
@@ -1533,6 +1631,8 @@
if ((filename == NULL) && (ctxt->path == NULL))
return(-1);
ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
+ if (ctxt->dataFd == -1)
+ return(-1);
#ifndef HAVE_SNPRINTF
len = sprintf(buf, "TYPE I\r\n");
@@ -1547,7 +1647,7 @@
close(ctxt->dataFd); ctxt->dataFd = -1;
return(res);
}
- res = xmlNanoFTPReadResponse(ctxt, buf, sizeof(buf) -1);
+ res = xmlNanoFTPReadResponse(ctxt);
if (res != 2) {
close(ctxt->dataFd); ctxt->dataFd = -1;
return(-res);
@@ -1572,7 +1672,7 @@
close(ctxt->dataFd); ctxt->dataFd = -1;
return(res);
}
- res = xmlNanoFTPReadResponse(ctxt, buf, sizeof(buf) -1);
+ res = xmlNanoFTPReadResponse(ctxt);
if (res != 1) {
close(ctxt->dataFd); ctxt->dataFd = -1;
return(-res);
@@ -1687,7 +1787,7 @@
* Returns an FTP context, or NULL
*/
-void *
+void*
xmlNanoFTPOpen(const char *URL) {
xmlNanoFTPCtxtPtr ctxt;
int sock;
@@ -1696,7 +1796,7 @@
if (URL == NULL) return(NULL);
if (strncmp("ftp://", URL, 6)) return(NULL);
- ctxt = xmlNanoFTPNewCtxt(URL);
+ ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(URL);
if (ctxt == NULL) return(NULL);
if (xmlNanoFTPConnect(ctxt) < 0) {
xmlNanoFTPFreeCtxt(ctxt);