diff options
author | Daniel Veillard <veillard@src.gnome.org> | 2000-07-10 10:27:46 +0000 |
---|---|---|
committer | Daniel Veillard <veillard@src.gnome.org> | 2000-07-10 10:27:46 +0000 |
commit | 4970326b4c7cb27b0423c180bf880f7b31254d9e (patch) | |
tree | 8528f46040d6b5305bc54d494725a3f8d3deb172 /nanoftp.c | |
parent | 6388e174d6a6cf573e0307060cf7966de1b94de3 (diff) | |
download | libxml2-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.c | 178 |
1 files changed, 126 insertions, 52 deletions
@@ -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); |