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

📄 nanoftp.c

📁 Vovida 社区开源的 SIP 协议源码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * @ctx:  an FTP context * * Check if there is a response from the FTP server after a command. * Returns the code number, or 0 */intxmlNanoFTPCheckResponse(void *ctx) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    char buf[1024 + 1];    fd_set rfd;    struct timeval tv;    tv.tv_sec = 0;    tv.tv_usec = 0;    FD_ZERO(&rfd);    FD_SET(ctxt->controlFd, &rfd);    switch(select(ctxt->controlFd + 1, &rfd, NULL, NULL, &tv)) {	case 0:	    return(0);	case -1:#ifdef DEBUG_FTP	    perror("select");#endif	    return(-1);			    }    return(xmlNanoFTPReadResponse(ctx, buf, 1024));}/** * Send the user authentification */static intxmlNanoFTPSendUser(void *ctx) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    char buf[200];    int len;    int res;    if (ctxt->user == NULL)#ifndef HAVE_SNPRINTF	len = sprintf(buf, "USER anonymous\r\n");#else /* HAVE_SNPRINTF */	len = snprintf(buf, sizeof(buf), "USER anonymous\r\n");#endif /* HAVE_SNPRINTF */    else#ifndef HAVE_SNPRINTF	len = sprintf(buf, "USER %s\r\n", ctxt->user);#else /* HAVE_SNPRINTF */	len = snprintf(buf, sizeof(buf), "USER %s\r\n", ctxt->user);#endif /* HAVE_SNPRINTF */#ifdef DEBUG_FTP    printf(buf);#endif    res = send(ctxt->controlFd, buf, len, 0);    if (res < 0) return(res);    return(0);}/** * Send the password authentification */static intxmlNanoFTPSendPasswd(void *ctx) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    char buf[200];    int len;    int res;    if (ctxt->passwd == NULL)#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", hostname);#endif /* HAVE_SNPRINTF */    else#ifndef HAVE_SNPRINTF	len = sprintf(buf, "PASS %s\r\n", ctxt->passwd);#else /* HAVE_SNPRINTF */	len = snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);#endif /* HAVE_SNPRINTF */#ifdef DEBUG_FTP    printf(buf);#endif    res = send(ctxt->controlFd, buf, len, 0);    if (res < 0) return(res);    return(0);}/** * xmlNanoFTPQuit: * @ctx:  an FTP context * * Send a QUIT command to the server * * Returns -1 in case of error, 0 otherwise */intxmlNanoFTPQuit(void *ctx) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    char buf[200];    int len;    int res;#ifndef HAVE_SNPRINTF    len = sprintf(buf, "QUIT\r\n");#else /* HAVE_SNPRINTF */    len = snprintf(buf, sizeof(buf), "QUIT\r\n");#endif /* HAVE_SNPRINTF */#ifdef DEBUG_FTP    printf(buf);#endif    res = send(ctxt->controlFd, buf, len, 0);    return(0);}/** * xmlNanoFTPConnect: * @ctx:  an FTP context * * Tries to open a control connection * * Returns -1 in case of error, 0 otherwise */intxmlNanoFTPConnect(void *ctx) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    struct hostent *hp;    int port;    int res;    if (ctxt == NULL)	return(-1);    if (ctxt->hostname == NULL)	return(-1);    /*     * 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 {	port = ctxt->port;    }    if (port == 0)	port = 21;    ctxt->ftpAddr.sin_port = htons(port);    ctxt->controlFd = socket(AF_INET, SOCK_STREAM, 0);    if (ctxt->controlFd < 0)        return(-1);    /*     * Do the connect.     */    if (connect(ctxt->controlFd, (struct sockaddr *) &ctxt->ftpAddr,                sizeof(struct sockaddr_in)) < 0) {        close(ctxt->controlFd); ctxt->controlFd = -1;        ctxt->controlFd = -1;	return(-1);    }    /*     * Wait for the HELLO from the server.     */    res = xmlNanoFTPGetResponse(ctxt);    if (res != 2) {        close(ctxt->controlFd); ctxt->controlFd = -1;        ctxt->controlFd = -1;	return(-1);    }    /*     * State diagram for the login operation on the FTP server     *     * Reference: RFC 959     *     *                       1     * +---+   USER    +---+------------->+---+     * | B |---------->| W | 2       ---->| E |     * +---+           +---+------  |  -->+---+     *                  | |       | | |     *                3 | | 4,5   | | |     *    --------------   -----  | | |     *   |                      | | | |     *   |                      | | | |     *   |                 ---------  |     *   |               1|     | |   |     *   V                |     | |   |     * +---+   PASS    +---+ 2  |  ------>+---+     * |   |---------->| W |------------->| S |     * +---+           +---+   ---------->+---+     *                  | |   | |     |     *                3 | |4,5| |     |     *    --------------   --------   |     *   |                    | |  |  |     *   |                    | |  |  |     *   |                 -----------     *   |             1,3|   | |  |     *   V                |  2| |  |     * +---+   ACCT    +---+--  |   ----->+---+     * |   |---------->| W | 4,5 -------->| F |     * +---+           +---+------------->+---+     *     * Of course in case of using a proxy this get really nasty and is not     * standardized at all :-(     */    if (proxy) {        int len;	char buf[400];        if (proxyUser != NULL) {	    /*	     * We need proxy auth	     */#ifndef HAVE_SNPRINTF	    len = sprintf(buf, "USER %s\r\n", proxyUser);#else /* HAVE_SNPRINTF */	    len = snprintf(buf, sizeof(buf), "USER %s\r\n", proxyUser);#endif /* HAVE_SNPRINTF */#ifdef DEBUG_FTP	    printf(buf);#endif	    res = send(ctxt->controlFd, buf, len, 0);	    if (res < 0) {		close(ctxt->controlFd);		ctxt->controlFd = -1;	        return(res);	    }	    res = xmlNanoFTPGetResponse(ctxt);	    switch (res) {		case 2:		    if (proxyPasswd == NULL)			break;		case 3:		    if (proxyPasswd != NULL)#ifndef HAVE_SNPRINTF			len = sprintf(buf, "PASS %s\r\n", proxyPasswd);#else /* HAVE_SNPRINTF */			len = snprintf(buf, sizeof(buf), "PASS %s\r\n", proxyPasswd);#endif /* HAVE_SNPRINTF */		    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",			               hostname);#endif /* HAVE_SNPRINTF */#ifdef DEBUG_FTP		    printf(buf);#endif		    res = send(ctxt->controlFd, buf, len, 0);		    if (res < 0) {			close(ctxt->controlFd);			ctxt->controlFd = -1;			return(res);		    }		    res = xmlNanoFTPGetResponse(ctxt);		    if (res > 3) {			close(ctxt->controlFd);			ctxt->controlFd = -1;			return(-1);		    }		    break;		case 1:		    break;		case 4:		case 5:		case -1:		default:		    close(ctxt->controlFd);		    ctxt->controlFd = -1;		    return(-1);	    }	}	/*	 * We assume we don't need more authentication to the proxy	 * and that it succeeded :-\	 */	switch (proxyType) {	    case 0:		/* we will try in seqence */	    case 1:		/* Using SITE command */#ifndef HAVE_SNPRINTF		len = sprintf(buf, "SITE %s\r\n", ctxt->hostname);#else /* HAVE_SNPRINTF */		len = snprintf(buf, sizeof(buf), "SITE %s\r\n", ctxt->hostname);#endif /* HAVE_SNPRINTF */#ifdef DEBUG_FTP		printf(buf);#endif		res = send(ctxt->controlFd, buf, len, 0);		if (res < 0) {		    close(ctxt->controlFd); ctxt->controlFd = -1;		    ctxt->controlFd = -1;		    return(res);		}		res = xmlNanoFTPGetResponse(ctxt);		if (res == 2) {		    /* we assume it worked :-\ 1 is error for SITE command */		    proxyType = 1;		    break;		}    		if (proxyType == 1) {		    close(ctxt->controlFd); ctxt->controlFd = -1;		    ctxt->controlFd = -1;		    return(-1);		}	    case 2:		/* USER user@host command */		if (ctxt->user == NULL)#ifndef HAVE_SNPRINTF		    len = sprintf(buf, "USER anonymous@%s\r\n",#else /* HAVE_SNPRINTF */		    len = snprintf(buf, sizeof(buf), "USER anonymous@%s\r\n",#endif /* HAVE_SNPRINTF */			           ctxt->hostname);		else#ifndef HAVE_SNPRINTF		    len = sprintf(buf, "USER %s@%s\r\n",#else /* HAVE_SNPRINTF */		    len = snprintf(buf, sizeof(buf), "USER %s@%s\r\n",#endif /* HAVE_SNPRINTF */			           ctxt->user, ctxt->hostname);#ifdef DEBUG_FTP		printf(buf);#endif		res = send(ctxt->controlFd, buf, len, 0);		if (res < 0) {		    close(ctxt->controlFd); ctxt->controlFd = -1;		    ctxt->controlFd = -1;		    return(res);		}		res = xmlNanoFTPGetResponse(ctxt);		if ((res == 1) || (res == 2)) {		    /* we assume it worked :-\ */		    proxyType = 2;		    return(0);		}    		if (ctxt->passwd == NULL)#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", hostname);#endif /* HAVE_SNPRINTF */		else#ifndef HAVE_SNPRINTF		    len = sprintf(buf, "PASS %s\r\n", ctxt->passwd);#else /* HAVE_SNPRINTF */		    len = snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);#endif /* HAVE_SNPRINTF */#ifdef DEBUG_FTP		printf(buf);#endif		res = send(ctxt->controlFd, buf, len, 0);		if (res < 0) {		    close(ctxt->controlFd); ctxt->controlFd = -1;		    ctxt->controlFd = -1;		    return(res);		}		res = xmlNanoFTPGetResponse(ctxt);		if ((res == 1) || (res == 2)) {		    /* we assume it worked :-\ */		    proxyType = 2;		    return(0);		}		if (proxyType == 2) {		    close(ctxt->controlFd); ctxt->controlFd = -1;		    ctxt->controlFd = -1;		    return(-1);		}	    case 3:		/*		 * If you need support for other Proxy authentication scheme		 * send the code or at least the sequence in use.		 */	    default:		close(ctxt->controlFd); ctxt->controlFd = -1;		ctxt->controlFd = -1;		return(-1);	}    }    /*     * Non-proxy handling.     */    res = xmlNanoFTPSendUser(ctxt);    if (res < 0) {        close(ctxt->controlFd); ctxt->controlFd = -1;        ctxt->controlFd = -1;	return(-1);    }    res = xmlNanoFTPGetResponse(ctxt);    switch (res) {	case 2:	    return(0);	case 3:	    break;	case 1:	case 4:	case 5:        case -1:	default:	    close(ctxt->controlFd); ctxt->controlFd = -1;	    ctxt->controlFd = -1;	    return(-1);    }    res = xmlNanoFTPSendPasswd(ctxt);    if (res < 0) {        close(ctxt->controlFd); ctxt->controlFd = -1;        ctxt->controlFd = -1;	return(-1);    }    res = xmlNanoFTPGetResponse(ctxt);    switch (res) {	case 2:	    break;	case 3:	    fprintf(stderr, "FTP server asking for ACCNT on anonymous\n");	case 1:	case 4:	case 5:        case -1:	default:	    close(ctxt->controlFd); ctxt->controlFd = -1;	    ctxt->controlFd = -1;	    return(-1);    }    return(0);}/** * xmlNanoFTPConnectTo: * @server:  an FTP server name * @directory:  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 */void *xmlNanoFTPConnectTo(const char *server, int port) {    xmlNanoFTPCtxtPtr ctxt;    int res;    xmlNanoFTPInit();    if (server == NULL) 	return(NULL);    ctxt = xmlNanoFTPNewCtxt(NULL);    ctxt->hostname = xmlMemStrdup(server);    if (port != 0)	ctxt->port = port;    res = xmlNanoFTPConnect(ctxt);    if (res < 0) {	xmlNanoFTPFreeCtxt(ctxt);	return(NULL);    }    return(ctxt);}/** * xmlNanoFTPGetConnection: * @ctx:  an FTP context * @directory:  a directory on the server * * Tries to change the remote directory * * Returns -1 incase of error, 1 if CWD worked, 0 if it failed */intxmlNanoFTPCwd(void *ctx, char *directory) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    char buf[400];    int len;    int res;    /*     * Expected response code for CWD:     *     * CWD     *     250     *     500, 501, 502, 421, 530, 550     */#ifndef HAVE_SNPRINTF    len = sprintf(buf, "CWD %s\r\n", directory);#else /* HAVE_SNPRINTF */    len = snprintf(buf, sizeof(buf), "CWD %s\r\n", directory);#endif /* HAVE_SNPRINTF */#ifdef DEBUG_FTP    printf(buf);#endif    res = send(ctxt->controlFd, buf, len, 0);    if (res < 0) return(res);    res = xmlNanoFTPGetResponse(ctxt);    if (res == 4) {	return(-1);    }    if (res == 2) return(1);    if (res == 5) {	return(0);    }    return(0);}/** * xmlNanoFTPGetConnection: * @ctx:  an FTP context * * Try to open a data connection to the server. Currently only * passive mode is supported. * * Returns -1 incase of error, 0 otherwise */intxmlNanoFTPGetConnection(void *ctx) {    xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;    char buf[200], *cur;    int len, i;    int res;    unsigned char ad[6], *adp, *portp;    unsigned int temp[6];    struct sockaddr_in dataAddr;    size_t dataAddrLen;    ctxt->dataFd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);    if (ctxt->dataFd < 0) {        fprintf(stderr, "xmlNanoFTPGetConnection: failed to create socket\n");    }    dataAddrLen = sizeof(dataAddr);    memset(&dataAddr, 0, dataAddrLen);    dataAddr.sin_family = AF_INET;    if (ctxt->passive) {#ifndef HAVE_SNPRINTF	len = sprintf(buf, "PASV\r\n");#else /* HAVE_SNPRINTF */	len = snprintf(buf, sizeof(buf), "PASV\r\n");#endif /* HAVE_SNPRINTF */#ifdef DEBUG_FTP	printf(buf);#endif	res = send(ctxt->controlFd, buf, len, 0);	if (res < 0) {	    close(ctxt->dataFd); ctxt->dataFd = -1;	    return(res);	}        res = xmlNanoFTPReadResponse(ctx, buf, sizeof(buf) -1);	if (res != 2) {	    if (res == 5) {	        close(ctxt->dataFd); ctxt->dataFd = -1;		return(-1);	    } else {		/*		 * retry with an active connection		 */	        close(ctxt->dataFd); ctxt->dataFd = -1;	        ctxt->passive = 0;	    }	}	cur = &buf[4];	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;	    return(-1);	}	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);	if (connect(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) {	    fprintf(stderr, "Failed to create a data connection\n");	    close(ctxt->dataFd); ctxt->dataFd = -1;	    return (-1);	}    } else {        getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen);	dataAddr.sin_port = 0;	if (bind(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) {	    fprintf(stderr, "Failed to bind a port\n");	    close(ctxt->dataFd); ctxt->dataFd = -1;	    return (-1);	}        getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen);

⌨️ 快捷键说明

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