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

📄 ftp.c

📁 -
💻 C
📖 第 1 页 / 共 5 页
字号:
ftpRestOrList(FtpStateData * ftpState){    debug(9, 3) ("This is ftpRestOrList\n");    if (ftpState->flags.put) {	debug(9, 3) ("ftpRestOrList: Sending STOR request...\n");	ftpSendStor(ftpState);    } else if (ftpState->typecode == 'D') {	/* XXX This should NOT be here */	ftpSendNlst(ftpState);	/* sec 3.2.2 of RFC 1738 */	ftpState->flags.isdir = 1;	ftpState->flags.use_base = 1;    } else if (ftpState->flags.isdir)	ftpSendList(ftpState);    else if (ftpRestartable(ftpState))	ftpSendRest(ftpState);    else	ftpSendRetr(ftpState);}static voidftpSendStor(FtpStateData * ftpState){    assert(ftpState->filepath != NULL);    snprintf(cbuf, 1024, "STOR %s\r\n", ftpState->filepath);    ftpWriteCommand(cbuf, ftpState);    ftpState->state = SENT_STOR;}static voidftpReadStor(FtpStateData * ftpState){    int code = ftpState->ctrl.replycode;    debug(9, 3) ("This is ftpReadStor\n");    if (code >= 100 && code < 200) {	/*	 * Cancel the timeout on the Control socket, pumpStart will	 * establish one on the data socket.	 */	commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL);	ftpPutStart(ftpState);	debug(9, 3) ("ftpReadStor: writing data channel\n");	ftpState->state = WRITING_DATA;    } else if (code == 553) {	/* directory does not exist, have to create, sigh */#if WORK_IN_PROGRESS	ftpTraverseDirectory(ftpState);#endif	ftpSendReply(ftpState);    } else {	debug(9, 3) ("ftpReadStor: that's all folks\n");	ftpSendReply(ftpState);    }}static voidftpSendRest(FtpStateData * ftpState){    snprintf(cbuf, 1024, "REST %d\r\n", ftpState->restart_offset);    ftpWriteCommand(cbuf, ftpState);    ftpState->state = SENT_REST;}static intftpRestartable(FtpStateData * ftpState){    if (ftpState->restart_offset > 0)	return 1;    if (!ftpState->request->range)	return 0;    if (!ftpState->flags.binary)	return 0;    if (ftpState->size <= 0)	return 0;    ftpState->restart_offset = httpHdrRangeLowestOffset(ftpState->request->range, (size_t) ftpState->size);    if (ftpState->restart_offset <= 0)	return 0;    return 1;}static voidftpReadRest(FtpStateData * ftpState){    int code = ftpState->ctrl.replycode;    debug(9, 3) ("This is ftpReadRest\n");    assert(ftpState->restart_offset > 0);    if (code == 350) {	ftpState->restarted_offset = ftpState->restart_offset;	ftpSendRetr(ftpState);    } else if (code > 0) {	debug(9, 3) ("ftpReadRest: REST not supported\n");	ftpState->flags.rest_supported = 0;	ftpSendRetr(ftpState);    } else {	ftpFail(ftpState);    }}static voidftpSendList(FtpStateData * ftpState){    if (ftpState->filepath) {	ftpState->flags.use_base = 1;	snprintf(cbuf, 1024, "LIST %s\r\n", ftpState->filepath);    } else {	snprintf(cbuf, 1024, "LIST\r\n");    }    ftpWriteCommand(cbuf, ftpState);    ftpState->state = SENT_LIST;}static voidftpSendNlst(FtpStateData * ftpState){    ftpState->flags.tried_nlst = 1;    if (ftpState->filepath) {	ftpState->flags.use_base = 1;	snprintf(cbuf, 1024, "NLST %s\r\n", ftpState->filepath);    } else {	snprintf(cbuf, 1024, "NLST\r\n");    }    ftpWriteCommand(cbuf, ftpState);    ftpState->state = SENT_NLST;}static voidftpReadList(FtpStateData * ftpState){    int code = ftpState->ctrl.replycode;    debug(9, 3) ("This is ftpReadList\n");    if (code == 125 || (code == 150 && ftpState->data.host)) {	/* Begin data transfer */	ftpAppendSuccessHeader(ftpState);	commSetSelect(ftpState->data.fd,	    COMM_SELECT_READ,	    ftpDataRead,	    ftpState,	    Config.Timeout.read);	commSetDefer(ftpState->data.fd, fwdCheckDeferRead, ftpState->entry);	ftpState->state = READING_DATA;	/*	 * Cancel the timeout on the Control socket and establish one	 * on the data socket	 */	commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL);	commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, ftpState);	return;    } else if (code == 150) {	/* Accept data channel */	commSetSelect(ftpState->data.fd,	    COMM_SELECT_READ,	    ftpAcceptDataConnection,	    ftpState,	    0);	/*	 * Cancel the timeout on the Control socket and establish one	 * on the data socket	 */	commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL);	commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, ftpState);	return;    } else if (!ftpState->flags.tried_nlst && code > 300) {	ftpSendNlst(ftpState);    } else {	ftpFail(ftpState);	return;    }}static voidftpSendRetr(FtpStateData * ftpState){    assert(ftpState->filepath != NULL);    snprintf(cbuf, 1024, "RETR %s\r\n", ftpState->filepath);    ftpWriteCommand(cbuf, ftpState);    ftpState->state = SENT_RETR;}static voidftpReadRetr(FtpStateData * ftpState){    int code = ftpState->ctrl.replycode;    debug(9, 3) ("This is ftpReadRetr\n");    if (code == 125 || (code == 150 && ftpState->data.host)) {	/* Begin data transfer */	debug(9, 3) ("ftpReadRetr: reading data channel\n");	ftpAppendSuccessHeader(ftpState);	commSetSelect(ftpState->data.fd,	    COMM_SELECT_READ,	    ftpDataRead,	    ftpState,	    Config.Timeout.read);	commSetDefer(ftpState->data.fd, fwdCheckDeferRead, ftpState->entry);	ftpState->state = READING_DATA;	/*	 * Cancel the timeout on the Control socket and establish one	 * on the data socket	 */	commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL);	commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout,	    ftpState);    } else if (code == 150) {	/* Accept data channel */	commSetSelect(ftpState->data.fd,	    COMM_SELECT_READ,	    ftpAcceptDataConnection,	    ftpState,	    0);	/*	 * Cancel the timeout on the Control socket and establish one	 * on the data socket	 */	commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL);	commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout,	    ftpState);    } else if (code >= 300) {	if (!ftpState->flags.try_slash_hack) {	    /* Try this as a directory missing trailing slash... */	    ftpHackShortcut(ftpState, ftpSendCwd);	} else {	    ftpFail(ftpState);	}    } else {	ftpFail(ftpState);    }}static voidftpReadTransferDone(FtpStateData * ftpState){    int code = ftpState->ctrl.replycode;    debug(9, 3) ("This is ftpReadTransferDone\n");    if (code != 226) {	debug(9, 1) ("ftpReadTransferDone: Got code %d after reading data\n",	    code);	debug(9, 1) ("--> releasing '%s'\n", storeUrl(ftpState->entry));	storeReleaseRequest(ftpState->entry);    }    ftpDataTransferDone(ftpState);}static voidftpDataTransferDone(FtpStateData * ftpState){    debug(9, 3) ("This is ftpDataTransferDone\n");    if (ftpState->data.fd > -1) {	comm_close(ftpState->data.fd);	ftpState->data.fd = -1;    }    ftpSendQuit(ftpState);}static voidftpSendQuit(FtpStateData * ftpState){    assert(ftpState->ctrl.fd > -1);    snprintf(cbuf, 1024, "QUIT\r\n");    ftpWriteCommand(cbuf, ftpState);    ftpState->state = SENT_QUIT;}static voidftpReadQuit(FtpStateData * ftpState){    comm_close(ftpState->ctrl.fd);}static voidftpTrySlashHack(FtpStateData * ftpState){    char *path;    ftpState->flags.try_slash_hack = 1;    /* Free old paths */    if (ftpState->pathcomps)	wordlistDestroy(&ftpState->pathcomps);    safe_free(ftpState->filepath);    /* Build the new path (urlpath begins with /) */    path = xstrdup(strBuf(ftpState->request->urlpath));    rfc1738_unescape(path);    ftpState->filepath = path;    /* And off we go */    ftpGetFile(ftpState);}static voidftpTryDatachannelHack(FtpStateData * ftpState){    ftpState->flags.datachannel_hack = 1;    /* we have to undo some of the slash hack... */    if (ftpState->old_filepath != NULL) {	ftpState->flags.try_slash_hack = 0;	safe_free(ftpState->filepath);	ftpState->filepath = ftpState->old_filepath;	ftpState->old_filepath = NULL;    }    ftpState->flags.tried_nlst = 0;    /* And off we go */    if (ftpState->flags.isdir) {	ftpListDir(ftpState);    } else {	ftpGetFile(ftpState);    }    return;}/* Forget hack status. Next error is shown to the user */static voidftpUnhack(FtpStateData * ftpState){    if (ftpState->old_request != NULL) {	safe_free(ftpState->old_request);	safe_free(ftpState->old_reply);    }}static voidftpHackShortcut(FtpStateData * ftpState, FTPSM * nextState){    /* Clear some unwanted state */    ftpState->restarted_offset = 0;    ftpState->restart_offset = 0;    /* Save old error message & some state info */    if (ftpState->old_request == NULL) {	ftpState->old_request = ftpState->ctrl.last_command;	ftpState->ctrl.last_command = NULL;	ftpState->old_reply = ftpState->ctrl.last_reply;	ftpState->ctrl.last_reply = NULL;	if (ftpState->pathcomps == NULL && ftpState->filepath != NULL)	    ftpState->old_filepath = xstrdup(ftpState->filepath);    }    /* Jump to the "hack" state */    nextState(ftpState);}static voidftpFail(FtpStateData * ftpState){    ErrorState *err;    debug(9, 3) ("ftpFail\n");    /* Try the / hack to support "Netscape" FTP URL's for retreiving files */    if (!ftpState->flags.isdir &&	/* Not a directory */	!ftpState->flags.try_slash_hack &&	/* Not in slash hack */	ftpState->mdtm <= 0 && ftpState->size < 0 &&	/* Not known as a file */	strNCaseCmp(ftpState->request->urlpath, "/%2f", 4) != 0) {	/* No slash encoded */	switch (ftpState->state) {	case SENT_CWD:	case SENT_RETR:	    /* Try the / hack */	    ftpHackShortcut(ftpState, ftpTrySlashHack);	    return;	default:	    break;	}    }    /* Try to reopen datachannel */    if (!ftpState->flags.datachannel_hack &&	ftpState->pathcomps == NULL) {	switch (ftpState->state) {	case SENT_RETR:	case SENT_LIST:	case SENT_NLST:	    /* Try to reopen datachannel */	    ftpHackShortcut(ftpState, ftpTryDatachannelHack);	    return;	default:	    break;	}    }    /* Translate FTP errors into HTTP errors */    err = NULL;    switch (ftpState->state) {    case SENT_USER:    case SENT_PASS:	if (ftpState->ctrl.replycode > 500)	    err = errorCon(ERR_FTP_FORBIDDEN, HTTP_FORBIDDEN);	else if (ftpState->ctrl.replycode == 421)	    err = errorCon(ERR_FTP_UNAVAILABLE, HTTP_SERVICE_UNAVAILABLE);	break;    case SENT_CWD:    case SENT_RETR:	if (ftpState->ctrl.replycode == 550)	    err = errorCon(ERR_FTP_NOT_FOUND, HTTP_NOT_FOUND);	break;    default:	break;    }    if (err == NULL)	err = errorCon(ERR_FTP_FAILURE, HTTP_BAD_GATEWAY);    err->request = requestLink(ftpState->request);    err->ftp_server_msg = ftpState->ctrl.message;    if (ftpState->old_request)	err->ftp.request = ftpState->old_request;    else	err->ftp.request = ftpState->ctrl.last_command;    if (err->ftp.request) {	if (!strncmp(err->ftp.request, "PASS", 4))	    err->ftp.request = "PASS <yourpassword>";    }    if (ftpState->old_reply)	err->ftp.reply = ftpState->old_reply;    else	err->ftp.reply = ftpState->ctrl.last_reply;    errorAppendEntry(ftpState->entry, err);    comm_close(ftpState->ctrl.fd);}voidftpPumpClosedData(int data_fd, void *data){    FtpStateData *ftpState = data;    assert(data_fd == ftpState->data.fd);    /*     * Ugly pump module closed our server-side.  Deal with it.     * The data FD is already closed, so just set it to -1.     */    ftpState->data.fd = -1;    /*     * Currently, thats all we have to do.  Because the upload failed,     * storeAbort() will be called on the reply entry.  That will     * call fwdAbort, which closes ftpState->ctrl.fd and then     * ftpStateFree gets called.     */}static voidftpPutStart(FtpStateData * ftpState){    debug(9, 3) ("ftpPutStart\n");    /*     * sigh, we need this gross hack to detect when ugly pump module     * aborts and wants to close the server-side.     */    comm_add_close_handler(ftpState->data.fd, ftpPumpClosedData, ftpState);    pumpStart(ftpState->data.fd, ftpState->fwd, ftpPutTransferDone, ftpState);}static voidftpPutTransferDone(int fd, char *bufnotused, size_t size, int errflag, void *data){    FtpStateData *ftpState = data;    if (ftpState->data.fd >= 0) {	comm_remove_close_handler(fd, ftpPumpClosedData, ftpState);	comm_close(ftpState->data.fd);	ftpState->data.fd = -1;    }    ftpReadComplete(ftpState);}static voidftpSendReply(FtpStateData * ftpState){    ErrorState *err;    int code = ftpState->ctrl.replycode;    http_status http_code;    err_type err_code = ERR_NONE;    debug(9, 5) ("ftpSendReply: %s, code %d\n",	storeUrl(ftpState->entry), code);    if (cbdataValid(ftpState))	debug(9, 5) ("ftpSendReply: ftpState (%p) is valid!\n", ftpState);    if (code == 226) {	err_code = (ftpState->mdtm > 0) ? ERR_FTP_PUT_MODIFIED : ERR_FTP_PUT_CREATED;	http_code = (ftpState->mdtm > 0) ? HTTP_ACCEPTED : HTTP_CREATED;    } else {	err_code = ERR_FTP_PUT_ERROR;	http_code = HTTP_INTERNAL_

⌨️ 快捷键说明

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