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

📄 ftp.c

📁 ELinks is an advanced and well-established feature-rich text mode web (HTTP/FTP/..) browser. ELinks
💻 C
📖 第 1 页 / 共 2 页
字号:
									pc[3] = a;									goto pasv_ok;								}							}						}					}					goto pasv_ok;				}				i++;			}			no_pasv:			memset(pc, 0, sizeof pc);			pasv_ok:;		}		g = get_ftp_response(c, rb, 0);		if (g == -1) { setcstate(c, S_FTP_ERROR); abort_connection(c); return; }		if (!g) { read_from_socket(c, c->sock1, rb, ftp_retr_file); setcstate(c, S_GETH); return; }		inf->pending_commands--;		switch (inf->opc - inf->pending_commands) {			case 1:		/* TYPE */				goto rep;			case 2:		/* PORT */				if (g >= 400) { setcstate(c, S_FTP_PORT); abort_connection(c); return; }				if (inf->pasv) {#if 0					struct sockaddr_in sa;					if (!pc[0] && !pc[1] && !pc[2] && !pc[3] && !pc[4] && !pc[5]) {						setcstate(c, S_FTP_ERROR);						retry_connection(c);						return;					}					sa.sin_family = AF_INET;					sa.sin_port = htons((pc[4] << 8) + pc[5]);					sa.sin_addr.s_addr = htonl((pc[0] << 24) + (pc[1] << 16) + (pc[2] << 8) + pc[3]);					/*debug("%d.%d.%d.%d", pc[0], pc[1], pc[2], pc[3]);*/					if ((c->sock2 = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {						setcstate(c, -errno);						retry_connection(c);						return;					}					fcntl(c->sock2, F_SETFL, O_NONBLOCK);#ifdef HAVE_IPTOS					if (ftp_options.set_tos) {						int on = IPTOS_THROUGHPUT;						setsockopt(c->sock2, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int));					}#endif					if (connect(c->sock2, (struct sockaddr *)&sa, sizeof sa)) {						if (errno != EINPROGRESS && errno != EALREADY) {							setcstate(c, -errno);							retry_connection(c);							return;						}					}					inf->d = 1;					set_handlers(c->sock2, (void (*)(void *))got_something_from_data_connection, NULL, NULL, c);#else					make_connection(c, (pc[4] << 8) + pc[5], &c->sock2, created_data_connection);#endif				}				goto rep;			case 3:		/* REST / CWD */				if (g >= 400) {					if (!inf->dir) c->from = 0;					else { setcstate(c, S_FTP_NO_FILE); abort_connection(c); return; }				}				goto rep;		}		internal("WHAT???");	}	g = get_ftp_response(c, rb, 2);	if (!g) { read_from_socket(c, c->sock1, rb, ftp_retr_file); setcstate(c, S_GETH); return; }	if (g >= 100 && g < 200) {		unsigned char *d = rb->data;		int i, p = 0;		for (i = 0; i < rb->len && d[i] != 10; i++) if (d[i] == '(') p = i;		if (!p || p == rb->len - 1) goto nol;		p++;		if (d[p] < '0' || d[p] > '9') goto nol;		for (i = p; i < rb->len; i++) if (d[i] < '0' || d[i] > '9') goto quak;		goto nol;		quak:		for (; i < rb->len; i++) if (d[i] != ' ') break;		if (i + 4 > rb->len) goto nol;		if (casecmp(&d[i], "byte", 4)) goto nol;		{#if defined(HAVE_STRTOLL)			long long est = strtoll(&d[p], NULL, 10);#elif defined(HAVE_STRTOQ)			longlong est = strtoq(&d[p], NULL, 10);#else			long est = strtol(&d[p], NULL, 10);			if (est == MAXLONG) est = -1;#endif			if (est < 0 || (off_t)est < 0 || (off_t)est != est) est = 0;			if (est && !c->from) c->est_length = est; /* !!! FIXME: when I add appedning to downloaded file */		}		nol:;	}	if (!inf->pasv)		set_handlers(c->sock2, (void (*)(void *))got_something_from_data_connection, NULL, NULL, c);	/*read_from_socket(c, c->sock1, rb, ftp_got_final_response);*/	ftp_got_final_response(c, rb);}void ftp_got_final_response(struct connection *c, struct read_buffer *rb){	struct ftp_connection_info *inf = c->info;	int g = get_ftp_response(c, rb, 0);	if (g == -1) { setcstate(c, S_FTP_ERROR); abort_connection(c); return; }	if (!g) { read_from_socket(c, c->sock1, rb, ftp_got_final_response); if (c->state != S_TRANS) setcstate(c, S_GETH); return; }	if (g == 425 || g == 450 || g == 500 || g == 501 || g == 550) {		if (c->url[strlen(c->url) - 1] == '/') goto skip_redir;		if (!c->cache && get_cache_entry(c->url, &c->cache)) {			setcstate(c, S_OUT_OF_MEM);			abort_connection(c);			return;		}		if (c->cache->redirect) mem_free(c->cache->redirect);		c->cache->redirect = stracpy(c->url);		c->cache->redirect_get = 1;		add_to_strn(&c->cache->redirect, "/");		c->cache->incomplete = 0;		/*setcstate(c, S_FTP_NO_FILE);*/		setcstate(c, S_OK);		abort_connection(c);		return;	}	skip_redir:	if (g >= 400) { setcstate(c, S_FTP_FILE_ERROR); abort_connection(c); return; }	if (inf->conn_st == 2) {		setcstate(c, S_OK);		ftp_end_request(c);	} else {		inf->conn_st = 1;		if (c->state != S_TRANS) setcstate(c, S_GETH);	}}static int is_date(char *data)	/* can touch at most data[-4] --- "n 12 "<--if fed with this --- if you change it, fix the caller */{	/* fix for ftp://ftp.su.se/ */	if (*data == ' ') data--;	if (data[0] >= '0' && data[0] <= '9' && data[-1] >= '0' && data[-1] <= '9') data -= 2;	else if (data[0] >= '1' && data[0] <= '9' && data[-1] == ' ') data -= 1 + (data[-2] == ' ');	else return 0;	if (data[0] == ':') return 1;	if (data[0] != ' ') return 0;	if ((data[-1] < 'a' || data[-1] > 'z') && (data[-1] < 'A' || data[-1] > 'Z')) return 0;	return 1;}int ftp_process_dirlist(struct cache_entry *ce, off_t *pos, int *d, unsigned char *bf, int ln, int fin, int *tr){	unsigned char *str, *buf;	int sl;	int ret = 0;	int p;	int len;	int f;	again:	buf = bf + ret;	len = ln - ret;	for (p = 0; p < len; p++) if (buf[p] == '\n') goto lb;	if (p && (fin || len >= FTP_BUF)) {		ret += p;		goto pl;	}	return ret;	lb:	ret += p + 1;	if (p && buf[p - 1] == '\r') p--;	pl:	str = init_str();	sl = 0;	/*add_to_str(&str, &sl, "   ");*/	f = *d;	if (*d && *d < p && WHITECHAR(buf[*d - 1])) {		int ee, dir;		ppp:		for (ee = *d; ee <= p - 4; ee++)			if (!memcmp(buf + ee, " -> ", 4)) goto syml;		ee = p;		syml:		if (!f) {			if ((ee - *d != 1 || buf[*d] != '.') &&			    (ee - *d != 2 || buf[*d] != '.' || buf[*d + 1] != '.')) {				int i;				for (i = 0; i < *d; i++) add_chr_to_str(&str, &sl, ' ');				add_to_str(&str, &sl, "<a href=\"../\">..</a>\n");			}		}		dir = buf[0] == 'd';		if (!dir) {			unsigned char *p = memacpy(buf, *d);			if (strstr(p, "<DIR>")) dir = 1;			mem_free(p);		};		add_conv_str(&str, &sl, buf, *d, 0);		add_to_str(&str, &sl, "<a href=\"./");		add_conv_str(&str, &sl, buf + *d, ee - *d, 1);		if (dir) add_chr_to_str(&str, &sl, '/');		add_to_str(&str, &sl, "\">");		add_conv_str(&str, &sl, buf + *d, ee - *d, 0);		add_to_str(&str, &sl, "</a>");		add_conv_str(&str, &sl, buf + ee, p - ee, 0);	} else {		int pp, ppos;		int bp, bn;		if (p > 5 && !casecmp(buf, "total", 5)) goto raw;		for (pp = p - 1; pp >= 0; pp--) if (!WHITECHAR(buf[pp])) break;		if (pp < 0) goto raw;		ppos = -1;		for (; pp >= 10; pp--) if (WHITECHAR(buf[pp])) {			if (is_date(&buf[pp - 6]) &&			    buf[pp - 5] == ' ' &&			    ((buf[pp - 4] == '2' && buf[pp - 3] == '0') ||			     (buf[pp - 4] == '1' && buf[pp - 3] == '9')) &&			    buf[pp - 2] >= '0' && buf[pp - 2] <= '9' &&			    buf[pp - 1] >= '0' && buf[pp - 1] <= '9') {				if (pp < p - 1 && buf[pp + 1] == ' ') ppos = pp + 1;				else ppos = pp;			}			if (buf[pp - 6] == ' ' &&			    ((buf[pp - 5] >= '0' && buf[pp - 5] <= '2') || buf[pp - 5] == ' ') &&			    buf[pp - 4] >= '0' && buf[pp - 4] <= '9' &&			    buf[pp - 3] == ':' &&			    buf[pp - 2] >= '0' && buf[pp - 2] <= '5' &&			    buf[pp - 1] >= '0' && buf[pp - 1] <= '9') ppos = pp;		}		if (ppos != -1) {			pp = ppos;			goto done;		}		for (pp = 0; pp + 5 <= p; pp++)			if (!casecmp(&buf[pp], "<DIR>", 5)) {				pp += 4;				while (pp + 1 < p && WHITECHAR(buf[pp + 1])) pp++;				if (pp + 1 < p) goto done;			}				bn = -1;		bp = 0;		/* warning, go away */		for (pp = 0; pp < p; ) {			if (buf[pp] >= '0' && buf[pp] <= '9') {				int i;				for (i = pp; i < p; i++)					if (buf[i] < '0' || buf[i] > '9') break;				if (i < p && WHITECHAR(buf[i])) {					if (i - pp > bn) {						bn = i - pp;						bp = pp;					}				}				pp = i;			}			while (pp < p && !WHITECHAR(buf[pp])) pp++;			while (pp < p && WHITECHAR(buf[pp])) pp++;		}		if (bn >= 0) {			pp = bp + bn;			while (pp + 1 < p && WHITECHAR(buf[pp + 1])) pp++;			if (pp + 1 < p) goto done;		}		for (pp = p - 1; pp >= 0; pp--) if (!WHITECHAR(buf[pp])) break;		if (pp < 0) goto raw;		for (; pp >= 0; pp--) if (WHITECHAR(buf[pp]) && (pp < 3 || memcmp(buf + pp - 3, " -> ", 4)) && (pp > p - 4 || memcmp(buf + pp, " -> ", 4))) break;		done:		*d = pp + 1;		goto ppp;		raw:		add_conv_str(&str, &sl, buf, p, 0);	}	add_chr_to_str(&str, &sl, '\n');	if (add_fragment(ce, *pos, str, sl)) *tr = 0;	*pos += sl;	mem_free(str);	goto again;}void created_data_connection(struct connection *c){	struct ftp_connection_info *inf = c->info;#ifdef HAVE_IPTOS	if (ftp_options.set_tos) {		int on = IPTOS_THROUGHPUT;		setsockopt(c->sock2, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int));	}#endif	inf->d = 1;	set_handlers(c->sock2, (void (*)(void *))got_something_from_data_connection, NULL, NULL, c);}void got_something_from_data_connection(struct connection *c){	struct ftp_connection_info *inf = c->info;	int l;	set_timeout(c);	if (!inf->d) {		int ns;		inf->d = 1;		set_handlers(c->sock2, NULL, NULL, NULL, NULL);		if ((ns = accept(c->sock2, NULL, NULL)) == -1) goto e;		close(c->sock2);		c->sock2 = ns;		set_handlers(ns, (void (*)(void *))got_something_from_data_connection, NULL, NULL, c);		return;	}	if (!c->cache && get_cache_entry(c->url, &c->cache)) {		setcstate(c, S_OUT_OF_MEM);		abort_connection(c);		return;	}	if (inf->dir && !c->from) {		unsigned char *ud;		unsigned char *s0;		int s0l;		static unsigned char ftp_head[] = "<html><head><title>/";		static unsigned char ftp_head2[] = "</title></head><body><h2>Directory /";		static unsigned char ftp_head3[] = "</h2><pre>";#define A(s) add_fragment(c->cache, c->from, s, strlen(s)), c->from += strlen(s)		A(ftp_head);		ud = stracpy(get_url_data(c->url));		if (strchr(ud, POST_CHAR)) *strchr(ud, POST_CHAR) = 0;		s0 = init_str();		s0l = 0;		add_conv_str(&s0, &s0l, ud, strlen(ud), -1);		mem_free(ud);		A(s0);		A(ftp_head2);		A(s0);		A(ftp_head3);		mem_free(s0);		if (!c->cache->head) c->cache->head = stracpy("\r\n");		add_to_strn(&c->cache->head, "Content-Type: text/html\r\n");#undef A	}	if ((l = read(c->sock2, inf->ftp_buffer + inf->buf_pos, FTP_BUF - inf->buf_pos)) == -1) {		e:		if (inf->conn_st != 1 && !inf->dir && !c->from) {			set_handlers(c->sock2, NULL, NULL, NULL, NULL);			close_socket(&c->sock2);			inf->conn_st = 2;			return;		}		setcstate(c, -errno);		retry_connection(c);		return;	}	if (l > 0) {		if (!inf->dir) {			if (c->from + l < 0) {				setcstate(c, S_LARGE_FILE);				abort_connection(c);				return;			}			c->received += l;			if (add_fragment(c->cache, c->from, inf->ftp_buffer, l) == 1) c->tries = 0;			c->from += l;		} else {			int m;			c->received += l;			m = ftp_process_dirlist(c->cache, &c->from, &inf->dpos, inf->ftp_buffer, l + inf->buf_pos, 0, &c->tries);			memmove(inf->ftp_buffer, inf->ftp_buffer + m, inf->buf_pos + l - m);			inf->buf_pos += l - m;		}		setcstate(c, S_TRANS);		return;	}	ftp_process_dirlist(c->cache, &c->from, &inf->dpos, inf->ftp_buffer, inf->buf_pos, 1, &c->tries);	set_handlers(c->sock2, NULL, NULL, NULL, NULL);	close_socket(&c->sock2);	if (inf->conn_st == 1) {		setcstate(c, S_OK);		ftp_end_request(c);	} else {		inf->conn_st = 2;	}}void ftp_end_request(struct connection *c){	if (c->state == S_OK) {		if (c->cache) {			truncate_entry(c->cache, c->from, 1);			c->cache->incomplete = 0;		}	}	add_keepalive_socket(c, FTP_KEEPALIVE_TIMEOUT);}

⌨️ 快捷键说明

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