summaryrefslogtreecommitdiff
path: root/nanoftp.c
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2000-07-10 10:27:46 +0000
committerDaniel Veillard <veillard@src.gnome.org>2000-07-10 10:27:46 +0000
commit4970326b4c7cb27b0423c180bf880f7b31254d9e (patch)
tree8528f46040d6b5305bc54d494725a3f8d3deb172 /nanoftp.c
parent6388e174d6a6cf573e0307060cf7966de1b94de3 (diff)
downloadlibxml2-4970326b4c7cb27b0423c180bf880f7b31254d9e.tar.gz
Fixed the handling of the control FTP connection
Fixed the spec file Daniel
Diffstat (limited to 'nanoftp.c')
-rw-r--r--nanoftp.c178
1 files changed, 126 insertions, 52 deletions
diff --git a/nanoftp.c b/nanoftp.c
index 9ebe015e..8d490e09 100644
--- a/nanoftp.c
+++ b/nanoftp.c
@@ -1,6 +1,5 @@
/*
- * nanoftp.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
*/
@@ -67,6 +66,7 @@ static char hostname[100];
#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 */
@@ -81,6 +81,11 @@ typedef struct xmlNanoFTPCtxt {
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;
@@ -449,6 +454,8 @@ xmlNanoFTPNewCtxt(const char *URL) {
ret->port = 21;
ret->passive = 1;
ret->returnValue = 0;
+ ret->controlBufIndex = 0;
+ ret->controlBufUsed = 0;
if (URL != NULL)
xmlNanoFTPScanURL(ret, URL);
@@ -473,6 +480,8 @@ xmlNanoFTPFreeCtxt(void * ctx) {
ctxt->passive = 1;
if (ctxt->controlFd >= 0) close(ctxt->controlFd);
ctxt->controlFd = -1;
+ ctxt->controlBufIndex = -1;
+ ctxt->controlBufUsed = -1;
xmlFree(ctxt);
}
@@ -514,59 +523,136 @@ xmlNanoFTPParseResponse(void *ctx, char *buf, int len) {
}
/**
- * xmlNanoFTPReadResponse:
+ * xmlNanoFTPGetMore:
* @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
+ * Read more information from the FTP control connection
+ * Returns the number of bytes read, < 0 indicates an error
*/
static int
-xmlNanoFTPReadResponse(void *ctx, char *buf, int size) {
+xmlNanoFTPGetMore(void *ctx) {
xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
- char *ptr, *end;
int len;
- int res = -1;
+ int size;
- if (size <= 0) return(-1);
+ if ((ctxt->controlBufIndex < 0) || (ctxt->controlBufIndex > FTP_BUF_SIZE)) {
+#ifdef DEBUG_FTP
+ printf("xmlNanoFTPGetMore : controlBufIndex = %d\n",
+ ctxt->controlBufIndex);
+#endif
+ return(-1);
+ }
-get_more:
- if ((len = recv(ctxt->controlFd, buf, size - 1, 0)) < 0) {
+ 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);
}
- if (len == 0) {
+#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
+ *
+ * Read the response from the FTP server after a command.
+ * Returns the code number
+ */
+static int
+xmlNanoFTPReadResponse(void *ctx) {
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
+ char *ptr, *end;
+ int len;
+ int res = -1, cur = -1;
+
+get_more:
+ /*
+ * Assumes everything up to controlBuf[controlBufIndex] has been read
+ * and analyzed.
+ */
+ len = xmlNanoFTPGetMore(ctx);
+ if ((ctxt->controlBufUsed == 0) && (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);
@@ -584,22 +670,11 @@ get_more:
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);
}
/**
@@ -613,7 +688,6 @@ xmlNanoFTPGetResponse(void *ctx) {
int
xmlNanoFTPCheckResponse(void *ctx) {
xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
- char buf[1024 + 1];
fd_set rfd;
struct timeval tv;
@@ -632,7 +706,7 @@ xmlNanoFTPCheckResponse(void *ctx) {
}
- return(xmlNanoFTPReadResponse(ctx, buf, 1024));
+ return(xmlNanoFTPReadResponse(ctx));
}
/**
@@ -1075,7 +1149,7 @@ xmlNanoFTPConnectTo(const char *server, int port) {
xmlNanoFTPInit();
if (server == NULL)
return(NULL);
- ctxt = xmlNanoFTPNewCtxt(NULL);
+ ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(NULL);
ctxt->hostname = xmlMemStrdup(server);
if (port != 0)
ctxt->port = port;
@@ -1088,7 +1162,7 @@ xmlNanoFTPConnectTo(const char *server, int port) {
}
/**
- * xmlNanoFTPGetConnection:
+ * xmlNanoFTPCwd:
* @ctx: an FTP context
* @directory: a directory on the server
*
@@ -1175,7 +1249,7 @@ xmlNanoFTPGetConnection(void *ctx) {
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;
@@ -1188,7 +1262,7 @@ xmlNanoFTPGetConnection(void *ctx) {
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) {
@@ -1479,7 +1553,7 @@ xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData,
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);
@@ -1576,7 +1650,7 @@ xmlNanoFTPGetSocket(void *ctx, const char *filename) {
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);
@@ -1601,7 +1675,7 @@ xmlNanoFTPGetSocket(void *ctx, const char *filename) {
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);
@@ -1725,7 +1799,7 @@ xmlNanoFTPOpen(const char *URL) {
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);