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

📄 ftp.c

📁 -
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * $Id: ftp.c,v 1.280.2.9 1999/05/11 20:34:36 wessels Exp $ * * DEBUG: section 9     File Transfer Protocol (FTP) * AUTHOR: Harvest Derived * * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * *  Squid is the result of efforts by numerous individuals from the *  Internet community.  Development is led by Duane Wessels of the *  National Laboratory for Applied Network Research and funded by the *  National Science Foundation.  Squid is Copyrighted (C) 1998 by *  Duane Wessels and the University of California San Diego.  Please *  see the COPYRIGHT file for full details.  Squid incorporates *  software developed and/or copyrighted by other sources.  Please see *  the CREDITS file for full details. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. *   *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. *   *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"static const char *const crlf = "\r\n";static char cbuf[1024];typedef enum {    BEGIN,    SENT_USER,    SENT_PASS,    SENT_TYPE,    SENT_MDTM,    SENT_SIZE,    SENT_PORT,    SENT_PASV,    SENT_CWD,    SENT_LIST,    SENT_NLST,    SENT_REST,    SENT_RETR,    SENT_STOR,    SENT_QUIT,    READING_DATA,    WRITING_DATA,    SENT_MKDIR} ftp_state_t;struct _ftp_flags {    unsigned int isdir:1;    unsigned int pasv_supported:1;    unsigned int skip_whitespace:1;    unsigned int rest_supported:1;    unsigned int pasv_only:1;    unsigned int authenticated:1;    unsigned int http_header_sent:1;    unsigned int tried_nlst:1;    unsigned int use_base:1;    unsigned int root_dir:1;    unsigned int no_dotdot:1;    unsigned int html_header_sent:1;    unsigned int binary:1;    unsigned int try_slash_hack:1;    unsigned int put:1;    unsigned int put_mkdir:1;    unsigned int listformat_unknown:1;    unsigned int datachannel_hack:1;};typedef struct _Ftpdata {    StoreEntry *entry;    request_t *request;    char user[MAX_URL];    char password[MAX_URL];    char *reply_hdr;    int reply_hdr_state;    char *title_url;    int conn_att;    int login_att;    ftp_state_t state;    time_t mdtm;    int size;    wordlist *pathcomps;    char *filepath;    int restart_offset;    int restarted_offset;    int rest_att;    char *proxy_host;    size_t list_width;    wordlist *cwd_message;    char *old_request;    char *old_reply;    char *old_filepath;    char typecode;    struct {	int fd;	char *buf;	size_t size;	off_t offset;	FREE *freefunc;	wordlist *message;	char *last_command;	char *last_reply;	int replycode;    } ctrl;    struct {	int fd;	char *buf;	size_t size;	off_t offset;	FREE *freefunc;	char *host;	u_short port;    } data;    struct _ftp_flags flags;    FwdState *fwd;} FtpStateData;typedef struct {    char type;    int size;    char *date;    char *name;    char *showname;    char *link;} ftpListParts;typedef void (FTPSM) (FtpStateData *);#define FTP_LOGIN_ESCAPED 1#define FTP_LOGIN_NOT_ESCAPED 0/* Local functions */static CNCB ftpPasvCallback;static PF ftpDataRead;static PF ftpStateFree;static PF ftpPumpClosedData;static PF ftpTimeout;static PF ftpReadControlReply;static CWCB ftpWriteCommandCallback;static void ftpLoginParser(const char *, FtpStateData *, int escaped);static wordlist *ftpParseControlReply(char *, size_t, int *, int *);static int ftpRestartable(FtpStateData * ftpState);static void ftpAppendSuccessHeader(FtpStateData * ftpState);static void ftpAuthRequired(HttpReply * reply, request_t * request, const char *realm);static void ftpHackShortcut(FtpStateData * ftpState, FTPSM * nextState);static void ftpPutStart(FtpStateData *);static CWCB ftpPutTransferDone;static void ftpUnhack(FtpStateData * ftpState);static void ftpScheduleReadControlReply(FtpStateData *, int);static void ftpHandleControlReply(FtpStateData *);static char *ftpHtmlifyListEntry(char *line, FtpStateData * ftpState);/* State machine functions * send == state transition * read == wait for response, and select next state transition * other == Transition logic */static FTPSM ftpReadWelcome;static FTPSM ftpSendUser;static FTPSM ftpReadUser;static FTPSM ftpSendPass;static FTPSM ftpReadPass;static FTPSM ftpSendType;static FTPSM ftpReadType;static FTPSM ftpSendMdtm;static FTPSM ftpReadMdtm;static FTPSM ftpSendSize;static FTPSM ftpReadSize;static FTPSM ftpSendPort;static FTPSM ftpReadPort;static FTPSM ftpSendPasv;static FTPSM ftpReadPasv;static FTPSM ftpTraverseDirectory;static FTPSM ftpListDir;static FTPSM ftpGetFile;static FTPSM ftpSendCwd;static FTPSM ftpReadCwd;static FTPSM ftpSendList;static FTPSM ftpSendNlst;static FTPSM ftpReadList;static FTPSM ftpSendRest;static FTPSM ftpReadRest;static FTPSM ftpSendRetr;static FTPSM ftpReadRetr;static FTPSM ftpReadTransferDone;static FTPSM ftpSendQuit;static FTPSM ftpReadQuit;static FTPSM ftpFail;static FTPSM ftpDataTransferDone;static FTPSM ftpRestOrList;static FTPSM ftpSendStor;static FTPSM ftpReadStor;static FTPSM ftpSendReply;static FTPSM ftpTryMkdir;static FTPSM ftpReadMkdir;/************************************************** State Machine Description (excluding hacks) ***************************************************From			To---------------------------------------Welcome			UserUser			PassPass			TypeType			TraverseDirectory / GetFileTraverseDirectory	Cwd / GetFile / ListDirCwd			TraverseDirectoryGetFile			MdtmMdtm			SizeSize			PasvListDir			PasvPasv			RestOrListRestOrList		Rest / Retr / Nlst / ListRest			RetrRetr / Nlst / List	(ftpDataRead on datachannel)(ftpDataRead)		ReadTransferDoneReadTransferDone	DataTransferDoneDataTransferDone	QuitQuit			-************************************************/FTPSM *FTP_SM_FUNCS[] ={    ftpReadWelcome,    ftpReadUser,    ftpReadPass,    ftpReadType,    ftpReadMdtm,    ftpReadSize,    ftpReadPort,    ftpReadPasv,    ftpReadCwd,    ftpReadList,		/* SENT_LIST */    ftpReadList,		/* SENT_NLST */    ftpReadRest,    ftpReadRetr,    ftpReadStor,    ftpReadQuit,    ftpReadTransferDone,    ftpSendReply,    ftpReadMkdir};static voidftpStateFree(int fdnotused, void *data){    FtpStateData *ftpState = data;    if (ftpState == NULL)	return;    debug(9, 3) ("ftpStateFree: %s\n", storeUrl(ftpState->entry));    storeUnregisterAbort(ftpState->entry);    storeUnlockObject(ftpState->entry);    if (ftpState->reply_hdr) {	memFree(ftpState->reply_hdr, MEM_8K_BUF);	/* this seems unnecessary, but people report SEGV's	 * when freeing memory in this function */	ftpState->reply_hdr = NULL;    }    requestUnlink(ftpState->request);    if (ftpState->ctrl.buf) {	ftpState->ctrl.freefunc(ftpState->ctrl.buf);	/* this seems unnecessary, but people report SEGV's	 * when freeing memory in this function */	ftpState->ctrl.buf = NULL;    }    if (ftpState->data.buf) {	ftpState->data.freefunc(ftpState->data.buf);	/* this seems unnecessary, but people report SEGV's	 * when freeing memory in this function */	ftpState->data.buf = NULL;    }    if (ftpState->pathcomps)	wordlistDestroy(&ftpState->pathcomps);    if (ftpState->ctrl.message)	wordlistDestroy(&ftpState->ctrl.message);    if (ftpState->cwd_message)	wordlistDestroy(&ftpState->cwd_message);    safe_free(ftpState->ctrl.last_reply);    safe_free(ftpState->ctrl.last_command);    safe_free(ftpState->old_request);    safe_free(ftpState->old_reply);    safe_free(ftpState->old_filepath);    safe_free(ftpState->title_url);    safe_free(ftpState->filepath);    safe_free(ftpState->data.host);    if (ftpState->data.fd > -1) {	comm_close(ftpState->data.fd);	ftpState->data.fd = -1;    }    cbdataFree(ftpState);}static voidftpLoginParser(const char *login, FtpStateData * ftpState, int escaped){    char *s = NULL;    xstrncpy(ftpState->user, login, MAX_URL);    if ((s = strchr(ftpState->user, ':'))) {	*s = 0;	xstrncpy(ftpState->password, s + 1, MAX_URL);	if (escaped)	    rfc1738_unescape(ftpState->password);    } else {	xstrncpy(ftpState->password, null_string, MAX_URL);    }    if (escaped)	rfc1738_unescape(ftpState->user);    if (ftpState->user[0] || ftpState->password[0])	return;    xstrncpy(ftpState->user, "anonymous", MAX_URL);    xstrncpy(ftpState->password, Config.Ftp.anon_user, MAX_URL);}static voidftpTimeout(int fd, void *data){    FtpStateData *ftpState = data;    StoreEntry *entry = ftpState->entry;    debug(9, 4) ("ftpTimeout: FD %d: '%s'\n", fd, storeUrl(entry));    if (entry->store_status == STORE_PENDING) {	if (entry->mem_obj->inmem_hi == 0) {	    fwdFail(ftpState->fwd,		errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));	}    }    if (ftpState->data.fd > -1) {	comm_close(ftpState->data.fd);	ftpState->data.fd = -1;    }    comm_close(ftpState->ctrl.fd);    /* don't modify ftpState here, it has been freed */}static voidftpListingStart(FtpStateData * ftpState){    StoreEntry *e = ftpState->entry;    wordlist *w;    char *dirup;    int i, j, k;    storeBuffer(e);    storeAppendPrintf(e, "<!-- HTML listing generated by Squid %s -->\n",	version_string);    storeAppendPrintf(e, "<!-- %s -->\n", mkrfc1123(squid_curtime));    storeAppendPrintf(e, "<HTML><HEAD><TITLE>\n");    storeAppendPrintf(e, "FTP Directory: %s\n",	ftpState->title_url);    storeAppendPrintf(e, "</TITLE>\n");    if (ftpState->flags.use_base)	storeAppendPrintf(e, "<BASE HREF=\"%s\">\n",	    ftpState->title_url);    storeAppendPrintf(e, "</HEAD><BODY>\n");    if (ftpState->cwd_message) {	storeAppendPrintf(e, "<PRE>\n");	for (w = ftpState->cwd_message; w; w = w->next)	    storeAppendPrintf(e, "%s\n", w->key);	storeAppendPrintf(e, "</PRE>\n");	storeAppendPrintf(e, "<HR>\n");	wordlistDestroy(&ftpState->cwd_message);    }    storeAppendPrintf(e, "<H2>\n");    storeAppendPrintf(e, "FTP Directory: ");    /* "ftp://" == 6 characters */    assert(strlen(ftpState->title_url) >= 6);    for (i = 6, j = 0; ftpState->title_url[i]; j = i) {	storeAppendPrintf(e, "<A HREF=\"");	i += strcspn(&ftpState->title_url[i], "/");	if (ftpState->title_url[i] == '/')	    i++;	for (k = 0; k < i; k++)	    storeAppendPrintf(e, "%c", ftpState->title_url[k]);	storeAppendPrintf(e, "\">");	for (k = j; k < i - 1; k++)	    storeAppendPrintf(e, "%c", ftpState->title_url[k]);	if (ftpState->title_url[k] != '/')	    storeAppendPrintf(e, "%c", ftpState->title_url[k++]);	storeAppendPrintf(e, "</A>");	if (k < i)	    storeAppendPrintf(e, "%c", ftpState->title_url[k++]);	if (i == j) {	    /* Error guard, or "assert" */	    storeAppendPrintf(e, "ERROR: Failed to parse URL: %s\n",		ftpState->title_url);	    debug(9, 0) ("Failed to parse URL: %s\n", ftpState->title_url);	    break;	}    }    storeAppendPrintf(e, "</H2>\n");    storeAppendPrintf(e, "<PRE>\n");    dirup = ftpHtmlifyListEntry("<internal-dirup>", ftpState);    storeAppend(e, dirup, strlen(dirup));    storeBufferFlush(e);    ftpState->flags.html_header_sent = 1;}static voidftpListingFinish(FtpStateData * ftpState){    StoreEntry *e = ftpState->entry;    storeBuffer(e);    storeAppendPrintf(e, "</PRE>\n");    if (ftpState->flags.listformat_unknown && !ftpState->flags.tried_nlst) {	storeAppendPrintf(e, "<A HREF=\"./;type=d\">[As plain directory]</A>\n");    } else if (ftpState->typecode == 'D') {	storeAppendPrintf(e, "<A HREF=\"./\">[As extended directory]</A>\n");    }    storeAppendPrintf(e, "<HR>\n");    storeAppendPrintf(e, "<ADDRESS>\n");    storeAppendPrintf(e, "Generated %s by %s (<a href=\"http://squid.nlanr.net/Squid/\">%s</a>)\n",	mkrfc1123(squid_curtime),	getMyHostname(),	full_appname_string,	version_string);    storeAppendPrintf(e, "</ADDRESS></BODY></HTML>\n");    storeBufferFlush(e);}static const char *Month[] ={    "Jan", "Feb", "Mar", "Apr", "May", "Jun",    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};static intis_month(const char *buf){    int i;    for (i = 0; i < 12; i++)	if (!strcasecmp(buf, Month[i]))	    return 1;    return 0;}static voidftpListPartsFree(ftpListParts ** parts){    safe_free((*parts)->date);    safe_free((*parts)->name);    safe_free((*parts)->showname);    safe_free((*parts)->link);    safe_free(*parts);}#define MAX_TOKENS 64#define SCAN_FTP1       "%[0123456789]"#define SCAN_FTP2       "%[0123456789:]"#define SCAN_FTP3       "%[0123456789]-%[0123456789]-%[0123456789]"#define SCAN_FTP4       "%[0123456789]:%[0123456789]%[AaPp]%[Mm]"static ftpListParts *ftpListParseParts(const char *buf, struct _ftp_flags flags){

⌨️ 快捷键说明

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