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

📄 htftp.c

📁 www工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
	switch ((state) ctrl->substate) {	  case NEED_TYPE:	    HTTRACE(PROT_TRACE, "FTP Data.... now in state NEED_TYPE\n");	    if(!data->type|| data->pasv || data->type=='N' || data->type=='L'){		ctrl->substate = NEED_SELECT;		break;	    }	    if (!ctrl->sent) {		char type[2];		*type = data->type;		*(type+1) = '\0';		status = SendCommand(request, ctrl, "TYPE", type);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_ERROR)		    ctrl->substate = SUB_ERROR;		ctrl->sent = YES;	    } else {		status = HTHost_read(HTNet_host(cnet), cnet);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_LOADED) {		    if (ctrl->repcode/100 == 2)			ctrl->substate = NEED_SELECT;		    else			ctrl->substate = SUB_ERROR;		} else		    ctrl->substate = SUB_ERROR;		ctrl->sent = NO;	    }	    break;	    	  case NEED_SELECT:	    HTTRACE(PROT_TRACE, "FTP Data.... now in state NEED_SELECT\n");	    if (FTPMode & FTP_DATA_PASV && !data->pasv)		ctrl->substate = NEED_PASV;	    else if (ListenSocket(cnet, dnet, data))		ctrl->substate = NEED_PORT;	    else		ctrl->substate = SUB_ERROR;	    break;	  case NEED_PASV:	    HTTRACE(PROT_TRACE, "FTP Data.... now in state NEED_PASV\n");	    if (!ctrl->sent) {		status = SendCommand(request, ctrl, "PASV", NULL);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_ERROR)		    ctrl->substate = SUB_ERROR;		ctrl->sent = YES;	    } else {		status = HTHost_read(HTNet_host(cnet), cnet);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_LOADED) {		    if (ctrl->repcode == 227) {		    			/*			** If succes, we have to scan for the returned number.			** As the format for the response isn't standard,			** the best thing to do is to scan for the first digit			** after the status code, see RFC1123			*/			char *host = ctrl->reply;			int h0, h1, h2, h3, p0=0, p1=0;			while (*host && !isdigit((int) *host++));			if (!*host || sscanf(--host, "%d,%d,%d,%d,%d,%d",					     &h0,&h1,&h2,&h3,&p0,&p1) < 6) {			    HTTRACE(PROT_TRACE, "FTP Data.... PASV No addr\n");			    ctrl->substate = SUB_ERROR;			    break;			} else {			    int port = (p0<<8)+p1;			    sprintf(data->host, "ftp://%d.%d.%d.%d:%d/",				    h0, h1, h2, h3, port);			    data->pasv = YES;			    ctrl->substate = SUB_SUCCESS;			}		    } else {			ctrl->substate = ListenSocket(cnet, dnet, data) ?			    NEED_PORT : SUB_ERROR;		    }		} else		    ctrl->substate = SUB_ERROR;		ctrl->sent = NO;	    }	    break;	  case NEED_PORT:	    HTTRACE(PROT_TRACE, "FTP Data.... now in state NEED_PORT\n");	    if (!ctrl->sent) {		status = SendCommand(request, ctrl, "PORT", data->host);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_ERROR)		    ctrl->substate = SUB_ERROR;		ctrl->sent = YES;	    } else {		status = HTHost_read(HTNet_host(cnet), cnet);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_LOADED) {		    data->pasv = NO;		    ctrl->substate = (ctrl->repcode/100 == 2) ?			SUB_SUCCESS : SUB_ERROR;		} else		    ctrl->substate = SUB_ERROR;		ctrl->sent = NO;	    }	    break;	  case SUB_ERROR:	    HTTRACE(PROT_TRACE, "FTP Data.... now in state SUB_ERROR\n");	    HTTRACE(PROT_TRACE, "FTP Data.... Can't setup data connection\n");	    ctrl->substate = 0;	    return HT_ERROR;	    break;	  case SUB_SUCCESS:	    HTTRACE(PROT_TRACE, "FTP Data.... now in state SUB_SUCCESS\n");	    HTTRACE(PROT_TRACE, "FTP Data.... Data connection negotiated\n");	    ctrl->substate = 0;	    return HT_OK;	    break;	}    }}/*	HTFTPServerInfo**	---------------**	This function finds out what server we are talking to.**	Maybe we can upgrade from NLST to LIST.**	Returns HT_OK, HT_ERROR, or HT_WOULD_BLOCK**	Thanks to James.W.Matthews@Dartmouth.EDU (James W. Matthews) for making**	his code available.*/PRIVATE int HTFTPServerInfo (HTRequest *request, HTNet *cnet,			     ftp_ctrl *ctrl, ftp_data *data){    int status;    typedef enum _state {	SUB_ERROR = -2,	SUB_SUCCESS = -1,	NEED_SYST = 0,	CHECK_SYST,	NEED_PWD,	CHECK_PWD    } state;    /* Jump into a second level state machine */    while (1) {	switch ((state) ctrl->substate) {	  case NEED_SYST:	    HTTRACE(PROT_TRACE, "FTP Server.. now in state NEED_SYST\n");	    if (!ctrl->sent) {				if (ctrl->server != FTP_UNSURE) {		    FTPListType(data, ctrl->server);		    return HT_OK;		}		status = SendCommand(request, ctrl, "SYST", NULL);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_ERROR)		    ctrl->substate = SUB_ERROR;		ctrl->sent = YES;	    } else {		status = HTHost_read(HTNet_host(cnet), cnet);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_LOADED) {		    ctrl->substate=ctrl->repcode==215 ? CHECK_SYST : NEED_PWD;		} else		    ctrl->substate = SUB_ERROR;		ctrl->sent = NO;	    }	    break;	  case CHECK_SYST:	    HTTRACE(PROT_TRACE, "FTP Server.. now in state CHECK_SYST\n");	    {		char *reply = ctrl->reply;		if (!*reply) {		    HTTRACE(PROT_TRACE, "FTP Server.. No server info?\n");		    ctrl->substate = NEED_PWD;		    break;		}		if (strncmp(reply, "UNIX Type: L8MAC-OSMachTen", 28) == 0) {		    ctrl->server = FTP_MACHTEN;		} else if (strstr(reply, "UNIX") != NULL) {		    ctrl->server = FTP_UNIX;		} else if (strncmp(reply, "VMS", 3) == 0) {		    ctrl->server = FTP_VMS;		} else if ((strncmp(reply, "VM/CMS", 6) == 0) ||			   (strncmp(reply, "VM", 2) == 0)) {		    ctrl->server = FTP_CMS;		} else if (strncmp(reply, "DCTS", 4) == 0) {		    ctrl->server = FTP_DCTS;		} else if (strstr(reply, "MAC-OS TCP/ConnectII") != NULL) {		    /* Check old versions of TCP/C using / in pathnames */		    ctrl->server = FTP_TCPC + FTP_UNSURE;		} else if (strncmp(reply, "MACOS Peter's Server", 20) == 0) {		    ctrl->server = FTP_PETER_LEWIS;		} else if (strncmp(reply, "Windows_NT", 10) == 0) {		    ctrl->server = FTP_WINNT;		}				/* If we are unsure, try PWD to get more information */		if (ctrl->server & FTP_UNSURE)		    ctrl->substate = NEED_PWD;		else		    ctrl->substate = SUB_SUCCESS;	    }	    break;	  case NEED_PWD:	    HTTRACE(PROT_TRACE, "FTP Server.. now in state NEED_PWD\n");	    if (!ctrl->sent) {		status = SendCommand(request, ctrl, "PWD", NULL);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_ERROR)		    ctrl->substate = SUB_ERROR;		ctrl->sent = YES;	    } else {		status = HTHost_read(HTNet_host(cnet), cnet);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_LOADED) {		    ctrl->substate = (ctrl->repcode/100 == 2) ?			CHECK_PWD : SUB_ERROR;		} else		    ctrl->substate = SUB_ERROR;		ctrl->sent = NO;	    }	    break;	  case CHECK_PWD:	    HTTRACE(PROT_TRACE, "FTP Server.. now in state CHECK_PWD\n");	    {		char *start = strchr(ctrl->reply, '"');		char *end;		if (!start || (end = strchr(++start, '"')) == NULL) {		    HTTRACE(PROT_TRACE, "FTP Server.. No current directory?\n");		    ctrl->server = FTP_GENERIC;		} else {		    *end = '\0';		    if (ctrl->server & FTP_TCPC) {			ctrl->server = *start == '/' ? FTP_NCSA : FTP_TCPC;		    } else if (*start == '/') {			/* path names starting with / imply Unix, right? */			ctrl->server = FTP_UNIX;		    } else if (*(end-1) == ']') {			/* path names ending with ] imply VMS, right? */			ctrl->server = FTP_VMS;		    } else			ctrl->server = FTP_GENERIC;		}		ctrl->substate = SUB_SUCCESS;	    }	    break;	  case SUB_ERROR:	    HTTRACE(PROT_TRACE, "FTP Server.. now in state SUB_ERROR\n");	    HTTRACE(PROT_TRACE, "FTP Server.. Can't get server information\n");	    ctrl->substate = 0;	    ctrl->server = FTP_GENERIC;	    return HT_ERROR;	    break;	  case SUB_SUCCESS:	    HTTRACE(PROT_TRACE, "FTP Server.. now in state SUB_SUCCESS\n");	    {	      HTHost * host = HTNet_host(cnet);	      HTTRACE(PROT_TRACE, "FTP Server.. Guessed type %d\n" _ ctrl->server);	      HTHost_setVersion(host, ctrl->server);	      FTPListType(data, ctrl->server);	      ctrl->substate = 0;	      return HT_OK;	      break;	    }	}    }}/*	HTFTPGetData**	------------**    	This function asks for the file or a directory. First we try in one go,**	but if that doesn't work, then we use CWD for each segment and then**	try to retrieve it. If that also fails, then we try if it is a**	directory.**	Returns HT_OK, HT_LOADED, HT_ERROR, or HT_WOULD_BLOCK*/PRIVATE int HTFTPGetData (HTRequest *request, HTNet *cnet, SOCKET sockfd,			  ftp_ctrl *ctrl, ftp_data *data){    int status;    char *segment = NULL;    HTNet *dnet = ctrl->dnet;    BOOL data_is_active = (sockfd == HTNet_socket(dnet));    typedef enum _state {	SUB_ERROR = -2,	SUB_SUCCESS = -1,	NEED_SELECT = 0,	NEED_CONNECT,	NEED_ACCEPT,	NEED_ACTION,        NEED_CWD,	NEED_SEGMENT,	NEED_STREAM,	NEED_BODY    } state;    /* Jump into a second level state machine */    while (1) {	switch ((state) ctrl->substate) {	  case NEED_SELECT:	    HTTRACE(PROT_TRACE, "FTP Get Data now in state NEED_SELECT\n");	    ctrl->substate = data->pasv ? NEED_CONNECT : NEED_ACTION;	    break;	  case NEED_CONNECT:	    HTTRACE(PROT_TRACE, "FTP Get Data now in state NEED_CONNECT\n");	    status = HTHost_connect(HTNet_host(dnet), dnet, data->host, FTP_DATA);	    if (status == HT_WOULD_BLOCK)		return HT_WOULD_BLOCK;	    else if (status == HT_OK) {		HTTRACE(PROT_TRACE, "FTP Get Data.... Active data socket %d\n" _ 			    HTNet_socket(dnet));#if 0		/*		HTNet_setPersistent(dnet, YES, HT_TP_INTERLEAVE); */		HTNet_setPersistent(dnet, YES, HT_TP_SINGLE);#endif		ctrl->substate = NEED_ACTION;	    } else {			 	  /* Swap to PORT on the fly */		NETCLOSE(HTNet_socket(dnet));		HTNet_setSocket(dnet, INVSOC);		HTTRACE(PROT_TRACE, "FTP Get Data Swap to PORT on the fly\n");		ctrl->substate = NEED_SELECT;		HT_FREE(segment);		return HT_OK;	    }	    break;	  case NEED_ACCEPT:	    HTTRACE(PROT_TRACE, "FTP Get Data now in state NEED_ACCEPT\n");	    {		status = HTDoAccept(ctrl->dnet, &ctrl->dnet);		dnet = ctrl->dnet;		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_OK) {		    HTTRACE(PROT_TRACE, "FTP Get Data.... Passive data socket %d\n" _ 				HTNet_socket(dnet));		    ctrl->substate = NEED_STREAM;		} else		    ctrl->substate = SUB_ERROR;	    }	    break;	  case NEED_ACTION:	    HTTRACE(PROT_TRACE, "FTP Get Data now in state NEED_ACTION\n");	    if (!ctrl->sent) {		char *cmd = (data->type=='L') ? "LIST" :		    (data->type=='N') ? "NLST" : "RETR";		StrAllocCopy(segment, data->offset);		HTUnEscape(segment);		HTCleanTelnetString(segment);		status = SendCommand(request, ctrl, cmd, segment);		HT_FREE(segment);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_ERROR)		    ctrl->substate = SUB_ERROR;		ctrl->sent = YES;	    } else {		status = HTHost_read(HTNet_host(cnet), cnet);		if (status == HT_WOULD_BLOCK)		    return HT_WOULD_BLOCK;		else if (status == HT_LOADED) {		    int code = ctrl->repcode;		    if (code==125 || code==150 || code==225)			ctrl->substate = data->pasv ? NEED_STREAM : NEED_ACCEPT;		    else if (code/100==5 && !ctrl->cwd)			ctrl->substate = NEED_SEGMENT;/* begin _GM_ *//* Note: libwww bug ID: GM9 */		    /* else */		    /* 	ctrl->substate = SUB_ERROR; */		    else {			if (ctrl->repcode == 550) {			    HTTRACE(PROT_TRACE, "FTP Get Data no such file or directory\n");			    data->stream_error = YES;			}		    	ctrl->substate = SUB_ERROR;		    }/* end _GM_ */		} else		    ctrl->substate = SUB_ERROR;		ctrl->sent = NO;	    }	    break;	  case NEED_SEGMENT:

⌨️ 快捷键说明

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