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

📄 ftp.c

📁 -
💻 C
📖 第 1 页 / 共 5 页
字号:
    ftpListParts *p = NULL;    char *t = NULL;    const char *ct = NULL;    char *tokens[MAX_TOKENS];    int i;    int n_tokens;    static char sbuf[128];    char *xbuf = NULL;    if (buf == NULL)	return NULL;    if (*buf == '\0')	return NULL;    p = xcalloc(1, sizeof(ftpListParts));    n_tokens = 0;    for (i = 0; i < MAX_TOKENS; i++)	tokens[i] = (char *) NULL;    xbuf = xstrdup(buf);    if (flags.tried_nlst) {	/* Machine readable format, one name per line */	p->name = xbuf;	p->type = '\0';	return p;    }    for (t = strtok(xbuf, w_space); t && n_tokens < MAX_TOKENS; t = strtok(NULL, w_space))	tokens[n_tokens++] = xstrdup(t);    xfree(xbuf);    /* locate the Month field */    for (i = 3; i < n_tokens - 2; i++) {	if (!is_month(tokens[i]))	/* Month */	    continue;	if (!sscanf(tokens[i - 1], SCAN_FTP1, sbuf))	/* Size */	    continue;	if (!sscanf(tokens[i + 1], SCAN_FTP1, sbuf))	/* Day */	    continue;	if (!sscanf(tokens[i + 2], SCAN_FTP2, sbuf))	/* Yr | hh:mm */	    continue;	p->type = *tokens[0];	p->size = atoi(tokens[i - 1]);	snprintf(sbuf, 128, "%s %2s %5s",	    tokens[i], tokens[i + 1], tokens[i + 2]);	if (!strstr(buf, sbuf))	    snprintf(sbuf, 128, "%s %2s %-5s",		tokens[i], tokens[i + 1], tokens[i + 2]);	if ((t = strstr(buf, sbuf))) {	    p->date = xstrdup(sbuf);	    if (flags.skip_whitespace) {		t += strlen(sbuf);		while (strchr(w_space, *t))		    t++;	    } else {		/* XXX assumes a single space between date and filename		 * suggested by:  Nathan.Bailey@cc.monash.edu.au and		 * Mike Battersby <mike@starbug.bofh.asn.au> */		t += strlen(sbuf) + 1;	    }	    p->name = xstrdup(t);	    if ((t = strstr(p->name, " -> "))) {		*t = '\0';		p->link = xstrdup(t + 4);	    }	}	break;    }    /* try it as a DOS listing */    if (n_tokens > 3 && p->name == NULL &&	sscanf(tokens[0], SCAN_FTP3, sbuf, sbuf, sbuf) == 3 &&    /* 04-05-70 */	sscanf(tokens[1], SCAN_FTP4, sbuf, sbuf, sbuf, sbuf) == 4) {	/* 09:33PM */	if (!strcasecmp(tokens[2], "<dir>")) {	    p->type = 'd';	} else {	    p->type = '-';	    p->size = atoi(tokens[2]);	}	snprintf(sbuf, 128, "%s %s", tokens[0], tokens[1]);	p->date = xstrdup(sbuf);	if (p->type == 'd') {	    /* Directory.. name begins with first printable after <dir> */	    ct = strstr(buf, tokens[2]);	    ct += strlen(tokens[2]);	    while (xisspace(*ct))		ct++;	    if (!*ct)		ct = NULL;	} else {	    /* A file. Name begins after size, with a space in between */	    snprintf(sbuf, 128, " %s %s", tokens[2], tokens[3]);	    ct = strstr(buf, sbuf);	    if (ct) {		ct += strlen(tokens[2]) + 2;	    }	}	p->name = xstrdup(ct ? ct : tokens[3]);    }    /* Try EPLF format; carson@lehman.com */    if (p->name == NULL && buf[0] == '+') {	ct = buf + 1;	p->type = 0;	while (ct && *ct) {	    switch (*ct) {	    case '\t':		sscanf(ct + 1, "%[^,]", sbuf);		p->name = xstrdup(sbuf);		break;	    case 's':		sscanf(ct + 1, "%d", &(p->size));		break;	    case 'm':		sscanf(ct + 1, "%d", &i);		p->date = xstrdup(ctime((time_t *) & i));		*(strstr(p->date, "\n")) = '\0';		break;	    case '/':		p->type = 'd';		break;	    case 'r':		p->type = '-';		break;	    case 'i':		break;	    default:		break;	    }	    ct = strstr(ct, ",");	    if (ct) {		ct++;	    }	}	if (p->type == 0) {	    p->type = '-';	}    }    for (i = 0; i < n_tokens; i++)	xfree(tokens[i]);    if (p->name == NULL)	ftpListPartsFree(&p);    return p;}static const char *dots_fill(size_t len){    static char buf[256];    int i = 0;    if (len > Config.Ftp.list_width) {	memset(buf, ' ', 256);	buf[0] = '\n';	buf[Config.Ftp.list_width + 4] = '\0';	return buf;    }    for (i = (int) len; i < Config.Ftp.list_width; i++)	buf[i - len] = (i % 2) ? '.' : ' ';    buf[i - len] = '\0';    return buf;}static char *ftpHtmlifyListEntry(char *line, FtpStateData * ftpState){    LOCAL_ARRAY(char, icon, 2048);    LOCAL_ARRAY(char, href, 2048 + 40);    LOCAL_ARRAY(char, text, 2048);    LOCAL_ARRAY(char, size, 2048);    LOCAL_ARRAY(char, chdir, 2048 + 40);    LOCAL_ARRAY(char, view, 2048 + 40);    LOCAL_ARRAY(char, download, 2048 + 40);    LOCAL_ARRAY(char, link, 2048 + 40);    LOCAL_ARRAY(char, html, 8192);    size_t width = Config.Ftp.list_width;    ftpListParts *parts;    *icon = *href = *text = *size = *chdir = *view = *download = *link = *html = '\0';    if ((int) strlen(line) > 1024) {	snprintf(html, 8192, "%s\n", line);	return html;    }    /* Handle builtin <dirup> */    if (!strcmp(line, "<internal-dirup>")) {	/* <A HREF="{href}">{icon}</A> <A HREF="{href}">{text}</A> {link} */	snprintf(icon, 2048, "<IMG BORDER=0 SRC=\"%s\" ALT=\"%-6s\">",	    mimeGetIconURL("internal-dirup"),	    "[DIRUP]");	if (!ftpState->flags.no_dotdot && !ftpState->flags.root_dir) {	    /* Normal directory */	    strcpy(href, "../");	    strcpy(text, "Parent Directory");	} else if (!ftpState->flags.no_dotdot && ftpState->flags.root_dir) {	    /* "Top level" directory */	    strcpy(href, "%2e%2e/");	    strcpy(text, "Parent Directory");	    snprintf(link, 2048, "(<A HREF=\"%s\">%s</A>)",		"%2f/",		"Root Directory");	} else if (ftpState->flags.no_dotdot && !ftpState->flags.root_dir) {	    /* Normal directory where last component is / or ..  */	    strcpy(href, "%2e%2e/");	    strcpy(text, "Parent Directory");	    snprintf(link, 2048, "(<A HREF=\"%s\">%s</A>)",		"../",		"Back");	} else {		/* NO_DOTDOT && ROOT_DIR */	    /* "UNIX Root" directory */	    strcpy(href, "../");	    strcpy(text, "Home Directory");	}	snprintf(html, 8192, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A> %s\n",	    href, icon, href, text, link);	return html;    }    if ((parts = ftpListParseParts(line, ftpState->flags)) == NULL) {	char *p;	snprintf(html, 8192, "%s\n", line);	for (p = line; *p && xisspace(*p); p++);	if (*p && !xisspace(*p))	    ftpState->flags.listformat_unknown = 1;	return html;    }    if (!strcmp(parts->name, ".") || !strcmp(parts->name, "..")) {	*html = '\0';	ftpListPartsFree(&parts);	return html;    }    parts->size += 1023;    parts->size >>= 10;    parts->showname = xstrdup(parts->name);    if (!Config.Ftp.list_wrap) {	if (strlen(parts->showname) > width - 1) {	    *(parts->showname + width - 1) = '>';	    *(parts->showname + width - 0) = '\0';	}    }    /* {icon} {text} . . . {date}{size}{chdir}{view}{download}{link}\n  */    xstrncpy(href, rfc1738_escape(parts->name), 2048);    xstrncpy(text, parts->showname, 2048);    switch (parts->type) {    case 'd':	snprintf(icon, 2048, "<IMG BORDER=0 SRC=\"%s\" ALT=\"%-6s\">",	    mimeGetIconURL("internal-dir"),	    "[DIR]");	strncat(href, "/", 2048);	break;    case 'l':	snprintf(icon, 2048, "<IMG BORDER=0 SRC=\"%s\" ALT=\"%-6s\">",	    mimeGetIconURL("internal-link"),	    "[LINK]");	/* sometimes there is an 'l' flag, but no "->" link */	if (parts->link)	    snprintf(link, 2048, " -> <A HREF=\"%s\">%s</A>",		rfc1738_escape(parts->link),		parts->link);	break;    case '\0':	snprintf(icon, 2048, "<IMG BORDER=0 SRC=\"%s\" ALT=\"%-6s\">",	    mimeGetIconURL(parts->name),	    "[UNKNOWN]");	snprintf(chdir, 2048, " <A HREF=\"%s/;type=d\"><IMG BORDER=0 SRC=\"%s\" "	    "ALT=\"[DIR]\"></A>",	    rfc1738_escape(parts->name),	    mimeGetIconURL("internal-dir"));	break;    case '-':    default:	snprintf(icon, 2048, "<IMG BORDER=0 SRC=\"%s\" ALT=\"%-6s\">",	    mimeGetIconURL(parts->name),	    "[FILE]");	snprintf(size, 2048, " %6dk", parts->size);	break;    }    if (parts->type != 'd') {	if (mimeGetViewOption(parts->name)) {	    snprintf(view, 2048, " <A HREF=\"%s;type=a\"><IMG BORDER=0 SRC=\"%s\" "		"ALT=\"[VIEW]\"></A>",		href, mimeGetIconURL("internal-view"));	}	if (mimeGetDownloadOption(parts->name)) {	    snprintf(download, 2048, " <A HREF=\"%s;type=i\"><IMG BORDER=0 SRC=\"%s\" "		"ALT=\"[DOWNLOAD]\"></A>",		href, mimeGetIconURL("internal-download"));	}    }    /* <A HREF="{href}">{icon}</A> <A HREF="{href}">{text}</A> . . . {date}{size}{chdir}{view}{download}{link}\n  */    if (parts->type != '\0') {	snprintf(html, 8192, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A>%s "	    "%s%8s%s%s%s%s\n",	    href, icon, href, text, dots_fill(strlen(text)),	    parts->date, size, chdir, view, download, link);    } else {	/* Plain listing. {icon} {text} ... {chdir}{view}{download} */	snprintf(html, 8192, "<A HREF=\"%s\">%s</A> <A HREF=\"%s\">%s</A>%s "	    "%s%s%s%s\n",	    href, icon, href, text, dots_fill(strlen(text)),	    chdir, view, download, link);    }    ftpListPartsFree(&parts);    return html;}static voidftpParseListing(FtpStateData * ftpState){    char *buf = ftpState->data.buf;    char *sbuf;			/* NULL-terminated copy of buf */    char *end;    char *line;    char *s;    char *t;    size_t linelen;    size_t usable;    StoreEntry *e = ftpState->entry;    int len = ftpState->data.offset;    /*     * We need a NULL-terminated buffer for scanning, ick     */    sbuf = xmalloc(len + 1);    xstrncpy(sbuf, buf, len + 1);    end = sbuf + len - 1;    while (*end != '\r' && *end != '\n' && end > sbuf)	end--;    usable = end - sbuf;    debug(9, 3) ("ftpParseListing: usable = %d\n", usable);    if (usable == 0) {	debug(9, 3) ("ftpParseListing: didn't find end for %s\n", storeUrl(e));	xfree(sbuf);	return;    }    debug(9, 3) ("ftpParseListing: %d bytes to play with\n", len);    line = memAllocate(MEM_4K_BUF);    end++;    storeBuffer(e);    s = sbuf;    s += strspn(s, crlf);    for (; s < end; s += strcspn(s, crlf), s += strspn(s, crlf)) {	debug(9, 3) ("ftpParseListing: s = {%s}\n", s);	linelen = strcspn(s, crlf) + 1;	if (linelen < 2)	    break;	if (linelen > 4096)	    linelen = 4096;	xstrncpy(line, s, linelen);	debug(9, 7) ("ftpParseListing: {%s}\n", line);	if (!strncmp(line, "total", 5))	    continue;	t = ftpHtmlifyListEntry(line, ftpState);	assert(t != NULL);	storeAppend(e, t, strlen(t));    }    storeBufferFlush(e);    assert(usable <= len);    if (usable < len) {	/* must copy partial line to beginning of buf */	linelen = len - usable;	if (linelen > 4096)	    linelen = 4096;	xstrncpy(line, end, linelen);	xstrncpy(ftpState->data.buf, line, ftpState->data.size);	ftpState->data.offset = strlen(ftpState->data.buf);    }    memFree(line, MEM_4K_BUF);    xfree(sbuf);}static voidftpReadComplete(FtpStateData * ftpState){    debug(9, 3) ("ftpReadComplete\n");    /* Connection closed; retrieval done. */    if (ftpState->flags.html_header_sent)	ftpListingFinish(ftpState);    if (!ftpState->flags.put) {	storeTimestampsSet(ftpState->entry);	fwdComplete(ftpState->fwd);    }    /* expect the "transfer complete" message on the control socket */    ftpScheduleReadControlReply(ftpState, 1);}static voidftpDataRead(int fd, void *data){    FtpStateData *ftpState = data;    int len;    int j;    int bin;    StoreEntry *entry = ftpState->entry;    MemObject *mem = entry->mem_obj;    size_t read_sz;#if DELAY_POOLS    delay_id delay_id = delayMostBytesAllowed(mem);#endif    assert(fd == ftpState->data.fd);    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {	comm_close(ftpState->ctrl.fd);	return;    }    errno = 0;    read_sz = ftpState->data.size - ftpState->data.offset;#if DELAY_POOLS    read_sz = delayBytesWanted(delay_id, 1, read_sz);#endif    memset(ftpState->data.buf + ftpState->data.offset, '\0', read_sz);    Counter.syscalls.sock.reads++;    len = read(fd, ftpState->data.buf + ftpState->data.offset, read_sz);    if (len > 0) {	fd_bytes(fd, len, FD_READ);#if DELAY_POOLS	delayBytesIn(delay_id, len);#endif	kb_incr(&Counter.server.all.kbytes_in, len);	kb_incr(&Counter.server.ftp.kbytes_in, len);	ftpState->data.offset += len;    }    debug(9, 5) ("ftpDataRead: FD %d, Read %d bytes\n", fd, len);    if (len > 0) {	IOStats.Ftp.reads++;	for (j = len - 1, bin = 0; j; bin++)	    j >>= 1;	IOStats.Ftp.read_hist[bin]++;    }    if (ftpState->flags.isdir && !ftpState->flags.html_header_sent && len >= 0) {	ftpListingStart(ftpState);    }    if (len < 0) {	debug(50, 1) ("ftpDataRead: read error: %s\n", xstrerror());	if (ignoreErrno(errno)) {	    commSetSelect(fd,		COMM_SELECT_READ,		ftpDataRead,		data,		Config.Timeout.read);	} else {	    assert(mem->inmem_hi > 0);	    ftpDataTransferDone(ftpState);	}    } else if (len == 0) {	ftpReadComplete(ftpState);    } else {	if (ftpState->flags.isdir) {	    ftpParseListing(ftpState);	} else {	    storeAppend(entry, ftpState->data.buf, len);	    ftpState->data.offset = 0;	}	if (ftpState->size > 0 && mem->inmem_hi >= ftpState->size + mem->reply->hdr_sz)	    ftpReadComplete(ftpState);	else	    commSetSelect(fd,		COMM_SELECT_READ,		ftpDataRead,		data,		Config.Timeout.read);    }}/* * ftpCheckAuth * * Return 1 if we have everything needed to complete this request. * Return 0 if something is missing. */static intftpCheckAuth(FtpStateData * ftpState, const HttpHeader * req_hdr){    char *orig_user;    const char *auth;    ftpLoginParser(ftpState->request->login, ftpState, FTP_LOGIN_ESCAPED);    if (ftpState->user[0] && ftpState->password[0])	return 1;		/* name and passwd both in URL */

⌨️ 快捷键说明

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