⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nanoftp.c

📁 SIP 1.5.0源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/** * ftp.c: basic handling of an FTP command connection to check for *        directory availability. No transfer is needed. * *  Reference: RFC 959 */#include "global.h"#ifdef WIN32#define INCLUDE_WINSOCK#include "win32config.h"#else#include "config.h"#endif#include "xmlversion.h"#ifdef LIBXML_FTP_ENABLED#include <stdio.h>#include <string.h>#ifdef HAVE_CTYPE_H#include <ctype.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#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#ifdef HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#ifdef HAVE_NETDB_H#include <netdb.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h> #endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#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#include <libxml/xmlmemory.h>#include <libxml/nanoftp.h>/* #define DEBUG_FTP 1  */#ifdef STANDALONE#ifndef DEBUG_FTP#define DEBUG_FTP 1#endif#endifstatic char hostname[100];#define FTP_COMMAND_OK		200#define FTP_SYNTAX_ERROR	500#define FTP_GET_PASSWD		331typedef struct xmlNanoFTPCtxt {    char *protocol;	/* the protocol name */    char *hostname;	/* the host name */    int port;		/* the port */    char *path;		/* the path within the URL */    char *user;		/* user string */    char *passwd;	/* passwd string */    struct sockaddr_in ftpAddr; /* the socket address struct */    int passive;	/* currently we support only passive !!! */    int controlFd;	/* the file descriptor for the control socket */    int dataFd;		/* the file descriptor for the data socket */    int state;		/* WRITE / READ / CLOSED */    int returnValue;	/* the protocol return value */} xmlNanoFTPCtxt, *xmlNanoFTPCtxtPtr;static int initialized = 0;static char *proxy = NULL;	/* the proxy name if any */static int proxyPort = 0;	/* the proxy port if any */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 ? *//** * xmlNanoFTPInit: * * Initialize the FTP protocol layer. * Currently it just checks for proxy informations, * and get the hostname */voidxmlNanoFTPInit(void) {    const char *env;    if (initialized)	return;    gethostname(hostname, sizeof(hostname));    proxyPort = 21;    env = getenv("no_proxy");    if (env != NULL)	return;    env = getenv("ftp_proxy");    if (env != NULL) {	xmlNanoFTPScanProxy(env);    } else {	env = getenv("FTP_PROXY");	if (env != NULL) {	    xmlNanoFTPScanProxy(env);	}    }    env = getenv("ftp_proxy_user");    if (env != NULL) {	proxyUser = xmlMemStrdup(env);    }    env = getenv("ftp_proxy_password");    if (env != NULL) {	proxyPasswd = xmlMemStrdup(env);    }    initialized = 1;}/** * xmlNanoFTPClenup: * * Cleanup the FTP protocol layer. This cleanup proxy informations. */voidxmlNanoFTPCleanup(void) {    if (proxy != NULL) {	xmlFree(proxy);	proxy = NULL;    }    if (proxyUser != NULL) {	xmlFree(proxyUser);	proxyUser = NULL;    }    if (proxyPasswd != NULL) {	xmlFree(proxyPasswd);	proxyPasswd = NULL;    }    hostname[0] = 0;    initialized = 0;    return;}/** * xmlNanoFTPProxy: * @host:  the proxy host name * @port:  the proxy port * @user:  the proxy user name * @passwd:  the proxy password * @type:  the type of proxy 1 for using SITE, 2 for USER a@b * * Setup the FTP proxy informations. * This can also be done by using ftp_proxy ftp_proxy_user and * ftp_proxy_password environment variables. */voidxmlNanoFTPProxy(const char *host, int port, const char *user,	        const char *passwd, int type) {    if (proxy != NULL)	xmlFree(proxy);    if (proxyUser != NULL)	xmlFree(proxyUser);    if (proxyPasswd != NULL)	xmlFree(proxyPasswd);    if (host)	proxy = xmlMemStrdup(host);    if (user)	proxyUser = xmlMemStrdup(user);    if (passwd)	proxyPasswd = xmlMemStrdup(passwd);    proxyPort = port;    proxyType = type;}/** * xmlNanoFTPScanURL: * @ctx:  an FTP context * @URL:  The URL used to initialize the context * * (Re)Initialize an FTP context by parsing the URL and finding * the protocol host port and path it indicates. */static voidxmlNanoFTPScanURL(void *ctx, const char *URL) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    const char *cur = URL;    char buf[4096];    int index = 0;    int port = 0;    if (ctxt->protocol != NULL) {         xmlFree(ctxt->protocol);	ctxt->protocol = NULL;    }    if (ctxt->hostname != NULL) {         xmlFree(ctxt->hostname);	ctxt->hostname = NULL;    }    if (ctxt->path != NULL) {         xmlFree(ctxt->path);	ctxt->path = NULL;    }    if (URL == NULL) return;    buf[index] = 0;    while (*cur != 0) {        if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) {	    buf[index] = 0;	    ctxt->protocol = xmlMemStrdup(buf);	    index = 0;            cur += 3;	    break;	}	buf[index++] = *cur++;    }    if (*cur == 0) return;    buf[index] = 0;    while (1) {        if (cur[0] == ':') {	    buf[index] = 0;	    ctxt->hostname = xmlMemStrdup(buf);	    index = 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[index] = 0;	    ctxt->hostname = xmlMemStrdup(buf);	    index = 0;	    break;	}	buf[index++] = *cur++;    }    if (*cur == 0)         ctxt->path = xmlMemStrdup("/");    else {        index = 0;        buf[index] = 0;	while (*cur != 0)	    buf[index++] = *cur++;	buf[index] = 0;	ctxt->path = xmlMemStrdup(buf);    }	}/** * xmlNanoFTPUpdateURL: * @ctx:  an FTP context * @URL:  The URL used to update the context * * Update an FTP context by parsing the URL and finding * new path it indicates. If there is an error in the  * protocol, hostname, port or other information, the * error is raised. It indicates a new connection has to * be established. * * Returns 0 if Ok, -1 in case of error (other host). */intxmlNanoFTPUpdateURL(void *ctx, const char *URL) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    const char *cur = URL;    char buf[4096];    int index = 0;    int port = 0;    if (URL == NULL)	return(-1);    if (ctxt == NULL)	return(-1);    if (ctxt->protocol == NULL)	return(-1);    if (ctxt->hostname == NULL)	return(-1);    buf[index] = 0;    while (*cur != 0) {        if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) {	    buf[index] = 0;	    if (strcmp(ctxt->protocol, buf))		return(-1);	    index = 0;            cur += 3;	    break;	}	buf[index++] = *cur++;    }    if (*cur == 0)	return(-1);    buf[index] = 0;    while (1) {        if (cur[0] == ':') {	    buf[index] = 0;	    if (strcmp(ctxt->hostname, buf))		return(-1);	    index = 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[index] = 0;	    if (strcmp(ctxt->hostname, buf))		return(-1);	    index = 0;	    break;	}	buf[index++] = *cur++;    }    if (ctxt->path != NULL) {	xmlFree(ctxt->path);	ctxt->path = NULL;    }    if (*cur == 0)         ctxt->path = xmlMemStrdup("/");    else {        index = 0;        buf[index] = 0;	while (*cur != 0)	    buf[index++] = *cur++;	buf[index] = 0;	ctxt->path = xmlMemStrdup(buf);    }	    return(0);}/** * xmlNanoFTPScanProxy: * @URL:  The proxy URL used to initialize the proxy context * * (Re)Initialize the FTP Proxy context by parsing the URL and finding * the protocol host port it indicates. * Should be like ftp://myproxy/ or ftp://myproxy:3128/ * A NULL URL cleans up proxy informations. */voidxmlNanoFTPScanProxy(const char *URL) {    const char *cur = URL;    char buf[4096];    int index = 0;    int port = 0;    if (proxy != NULL) {         xmlFree(proxy);	proxy = NULL;    }    if (proxyPort != 0) { 	proxyPort = 0;    }#ifdef DEBUG_FTP    if (URL == NULL)	printf("Removing FTP proxy info\n");    else	printf("Using FTP proxy %s\n", URL);#endif    if (URL == NULL) return;    buf[index] = 0;    while (*cur != 0) {        if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) {	    buf[index] = 0;	    index = 0;            cur += 3;	    break;	}	buf[index++] = *cur++;    }    if (*cur == 0) return;    buf[index] = 0;    while (1) {        if (cur[0] == ':') {	    buf[index] = 0;	    proxy = xmlMemStrdup(buf);	    index = 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[index] = 0;	    proxy = xmlMemStrdup(buf);	    index = 0;	    break;	}	buf[index++] = *cur++;    }}/** * xmlNanoFTPNewCtxt: * @URL:  The URL used to initialize the context * * Allocate and initialize a new FTP context. * * Returns an FTP context or NULL in case of error. */void *xmlNanoFTPNewCtxt(const char *URL) {    xmlNanoFTPCtxtPtr ret;    ret = (xmlNanoFTPCtxtPtr) xmlMalloc(sizeof(xmlNanoFTPCtxt));    if (ret == NULL) return(NULL);    memset(ret, 0, sizeof(xmlNanoFTPCtxt));    ret->port = 21;    ret->passive = 1;    ret->returnValue = 0;    if (URL != NULL)	xmlNanoFTPScanURL(ret, URL);    return(ret);}/** * xmlNanoFTPFreeCtxt: * @ctx:  an FTP context * * Frees the context after closing the connection. */voidxmlNanoFTPFreeCtxt(void * ctx) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    if (ctxt == NULL) return;    if (ctxt->hostname != NULL) xmlFree(ctxt->hostname);    if (ctxt->protocol != NULL) xmlFree(ctxt->protocol);    if (ctxt->path != NULL) xmlFree(ctxt->path);    ctxt->passive = 1;    if (ctxt->controlFd >= 0) close(ctxt->controlFd);    ctxt->controlFd = -1;    xmlFree(ctxt);}/** * Parsing of the server answer, we just extract the code. * return 0 for errors *     +XXX for last line of response *     -XXX for response to be continued */static intxmlNanoFTPParseResponse(void *ctx, char *buf, int len) {    int val = 0;    if (len < 3) return(-1);    if ((*buf >= '0') && (*buf <= '9'))         val = val * 10 + (*buf - '0');    else        return(0);    buf++;    if ((*buf >= '0') && (*buf <= '9'))         val = val * 10 + (*buf - '0');    else        return(0);    buf++;    if ((*buf >= '0') && (*buf <= '9'))         val = val * 10 + (*buf - '0');    else        return(0);    buf++;    if (*buf == '-')         return(-val);    return(val);}/** * 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 intxmlNanoFTPReadResponse(void *ctx, char *buf, int size) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    char *ptr, *end;    int len;    int res = -1;    if (size <= 0) return(-1);get_more:    if ((len = recv(ctxt->controlFd, buf, size - 1, 0)) < 0) {	close(ctxt->controlFd); ctxt->controlFd = -1;        ctxt->controlFd = -1;        return(-1);    }    if (len == 0) {        return(-1);    }    end = &buf[len];    *end = 0;#ifdef DEBUG_FTP    printf(buf);#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);	}	while ((ptr < end) && (*ptr != '\n')) ptr++;	if (ptr >= end) {#ifdef DEBUG_FTP	    fprintf(stderr, "xmlNanoFTPReadResponse: unexpected end %s\n", buf);#endif	    return((-res) / 100);	}	if (*ptr != '\r') ptr++;    }    if (res < 0) goto get_more;#ifdef DEBUG_FTP    printf("Got %d\n", res);#endif    return(res / 100);}/** * xmlNanoFTPGetResponse: * @ctx:  an FTP context * * Get the response from the FTP server after a command. * Returns the code number */intxmlNanoFTPGetResponse(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); **************/    return(xmlNanoFTPReadResponse(ctx, buf, 16 * 1024));}/**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -