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

📄 ftp.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	response = get_ftp_response(conn, rb, 2, NULL);	if (response == -1) {		abort_conn_with_state(conn, S_FTP_ERROR);		return;	}	if (!response) {		read_from_socket(conn, &conn->socket, rb, ftp_retr_file);		set_connection_state(conn, S_GETH);		return;	}	if (response >= 100 && response < 200) {		/* We only need to parse response after RETR to		 * get filesize if needed. */		if (!c_i->dir && conn->est_length == -1) {			long int file_len =				get_filesize_from_RETR(rb->data, rb->len);			if (file_len > 0) {				/* FIXME: ..when downloads resuming				 * implemented.. */				conn->est_length = file_len + conn->progress.start;			}		}	}	set_handlers(conn->data_socket.fd,		     (void (*)(void *)) got_something_from_data_connection,		     NULL, NULL, conn);	/* read_from_socket(conn, &conn->socket, rb, ftp_got_final_response); */	ftp_got_final_response(conn, rb);}static voidftp_got_final_response(struct connection *conn, struct read_buffer *rb){	struct ftp_connection_info *c_i = conn->info;	int response = get_ftp_response(conn, rb, 0, NULL);	if (response == -1) {		abort_conn_with_state(conn, S_FTP_ERROR);		return;	}	if (!response) {		read_from_socket(conn, &conn->socket, rb, ftp_got_final_response);		if (conn->state != S_TRANS)			set_connection_state(conn, S_GETH);		return;	}	if (response >= 550 || response == 450) {		/* Requested action not taken.		 * File unavailable (e.g., file not found, no access). */		if (!conn->cached)			conn->cached = get_cache_entry(conn->uri);		if (!conn->cached		    || !redirect_cache(conn->cached, "/", 1, 0)) {			abort_conn_with_state(conn, S_OUT_OF_MEM);			return;		}		abort_conn_with_state(conn, S_OK);		return;	}	if (response >= 400) {		abort_conn_with_state(conn, S_FTP_FILE_ERROR);		return;	}	if (c_i->conn_state == 2) {		ftp_end_request(conn, S_OK);	} else {		c_i->conn_state = 1;		if (conn->state != S_TRANS)			set_connection_state(conn, S_GETH);	}}/* Display directory entry formatted in HTML. */static intdisplay_dir_entry(struct cache_entry *cached, int *pos, int *tries,		  int colorize_dir, unsigned char *dircolor,		  struct ftp_file_info *ftp_info){	struct string string;	unsigned char permissions[10] = "---------";	if (!init_string(&string)) return -1;	add_char_to_string(&string, ftp_info->type);	if (ftp_info->permissions) {		int p = ftp_info->permissions;#define FTP_PERM(perms, buffer, flag, index, id) \	if ((perms) & (flag)) (buffer)[(index)] = (id);		FTP_PERM(p, permissions, S_IRUSR, 0, 'r');		FTP_PERM(p, permissions, S_IWUSR, 1, 'w');		FTP_PERM(p, permissions, S_IXUSR, 2, 'x');		FTP_PERM(p, permissions, S_ISUID, 2, (p & S_IXUSR ? 's' : 'S'));		FTP_PERM(p, permissions, S_IRGRP, 3, 'r');		FTP_PERM(p, permissions, S_IWGRP, 4, 'w');		FTP_PERM(p, permissions, S_IXGRP, 5, 'x');		FTP_PERM(p, permissions, S_ISGID, 5, (p & S_IXGRP ? 's' : 'S'));		FTP_PERM(p, permissions, S_IROTH, 6, 'r');		FTP_PERM(p, permissions, S_IWOTH, 7, 'w');		FTP_PERM(p, permissions, S_IXOTH, 8, 'x');		FTP_PERM(p, permissions, S_ISVTX, 8, (p & 0001 ? 't' : 'T'));#undef FTP_PERM	}	add_to_string(&string, permissions);	add_char_to_string(&string, ' ');	add_to_string(&string, "   1 ftp      ftp ");	if (ftp_info->size != FTP_SIZE_UNKNOWN) {		add_format_to_string(&string, "%12lu ", ftp_info->size);	} else {		add_to_string(&string, "           - ");	}#ifdef HAVE_STRFTIME	if (ftp_info->mtime > 0) {		time_t current_time = time(NULL);		time_t when = ftp_info->mtime;		struct tm *when_tm;	       	unsigned char *fmt;		unsigned char date[13];		int wr;		if (ftp_info->local_time_zone)			when_tm = localtime(&when);		else			when_tm = gmtime(&when);		if (current_time > when + 6L * 30L * 24L * 60L * 60L		    || current_time < when - 60L * 60L)			fmt = "%b %e  %Y";		else			fmt = "%b %e %H:%M";		wr = strftime(date, sizeof(date), fmt, when_tm);		while (wr < sizeof(date) - 1) date[wr++] = ' ';		date[sizeof(date) - 1] = '\0';		add_to_string(&string, date);	} else#endif	add_to_string(&string, "            ");	add_char_to_string(&string, ' ');	if (ftp_info->type == FTP_FILE_DIRECTORY && colorize_dir) {		add_to_string(&string, "<font color=\"");		add_to_string(&string, dircolor);		add_to_string(&string, "\"><b>");	}	add_to_string(&string, "<a href=\"");	add_html_to_string(&string, ftp_info->name.source, ftp_info->name.length);	if (ftp_info->type == FTP_FILE_DIRECTORY)		add_char_to_string(&string, '/');	add_to_string(&string, "\">");	add_html_to_string(&string, ftp_info->name.source, ftp_info->name.length);	add_to_string(&string, "</a>");	if (ftp_info->type == FTP_FILE_DIRECTORY && colorize_dir) {		add_to_string(&string, "</b></font>");	}	if (ftp_info->symlink.length) {		add_to_string(&string, " -&gt; ");		add_html_to_string(&string, ftp_info->symlink.source,				ftp_info->symlink.length);	}	add_char_to_string(&string, '\n');	if (add_fragment(cached, *pos, string.source, string.length)) *tries = 0;	*pos += string.length;	done_string(&string);	return 0;}/* List a directory in html format. */static intftp_process_dirlist(struct cache_entry *cached, int *pos,		    unsigned char *buffer, int buflen, int last,		    int *tries, int colorize_dir, unsigned char *dircolor){	int ret = 0;#ifdef DEBUG_FTP_PARSER 	static int debug_ftp_parser = 1;	int buflen_orig = buflen;	unsigned char *response_orig = NULL;	if (debug_ftp_parser) {		buffer = get_ftp_debug_parse_responses(buffer, buflen);		buflen = strlen(buffer);		response_orig = buffer;		debug_ftp_parser = 0;	}#define	end_ftp_dirlist_processing()	do { mem_free_if(response_orig); } while (0)#define get_ftp_dirlist_offset(retval)	int_min(retval, buflen_orig)#else#define	end_ftp_dirlist_processing()	/* Nothing to free */#define	get_ftp_dirlist_offset(retval)	(retval)#endif	while (1) {		struct ftp_file_info ftp_info = INIT_FTP_FILE_INFO;		unsigned char *buf = buffer + ret;		int bufl = buflen - ret;		int bufp;		int newline = 0;		/* Newline quest. */		for (bufp = 0; bufp < bufl; bufp++) {			if (buf[bufp] == ASCII_LF) {				newline = 1;				break;			}		}		if (newline) {			ret += bufp + 1;			if (bufp && buf[bufp - 1] == ASCII_CR) bufp--;		} else {			if (!bufp || (!last && bufl < FTP_BUF_SIZE)) {				end_ftp_dirlist_processing();				return get_ftp_dirlist_offset(ret);			}			ret += bufp;		}		/* Process line whose end we've already found. */		if (parse_ftp_file_info(&ftp_info, buf, bufp)) {			int retv;			if ((ftp_info.name.length == 1 && ftp_info.name.source[0] == '.')			    || (ftp_info.name.length == 2 && ftp_info.name.source[0] == '.'				&& ftp_info.name.source[1] == '.'))				continue;			retv = display_dir_entry(cached, pos, tries, colorize_dir,						dircolor, &ftp_info);			if (retv < 0) {				end_ftp_dirlist_processing();				return get_ftp_dirlist_offset(ret);			}		}#ifdef DEBUG_FTP_PARSER		else {			ERROR("Error parsing: [%.*s]", bufp, buf);		}#endif	}}static intftp_data_accept(struct connection *conn){	struct ftp_connection_info *c_i = conn->info;	int newsock;	if (c_i->has_data) return 0;	c_i->has_data = 1;	clear_handlers(conn->data_socket.fd);	if ((conn->protocol_family != 1 && c_i->use_pasv)#ifdef CONFIG_IPV6	    || (conn->protocol_family == 1 && c_i->use_epsv)#endif	   ) {		newsock = conn->data_socket.fd;	} else {		newsock = accept(conn->data_socket.fd, NULL, NULL);		if (newsock < 0) {			retry_conn_with_state(conn, -errno);			return -1;		}		close(conn->data_socket.fd);	}	conn->data_socket.fd = newsock;	set_handlers(newsock,		     (void (*)(void *)) got_something_from_data_connection,		     NULL, NULL, conn);	return 0;}static voidgot_something_from_data_connection(struct connection *conn){	struct ftp_connection_info *c_i = conn->info;	unsigned char dircolor[8];	int colorize_dir = 0;	int len;	/* XXX: This probably belongs rather to connect.c ? */	set_connection_timeout(conn);	if (ftp_data_accept(conn)) return;	if (!conn->cached) conn->cached = get_cache_entry(conn->uri);	if (!conn->cached) {out_of_mem:		abort_conn_with_state(conn, S_OUT_OF_MEM);		return;	}	if (c_i->dir) {		colorize_dir = get_opt_bool("document.browse.links.color_dirs");		if (colorize_dir) {			color_to_string(get_opt_color("document.colors.dirs"),					(unsigned char *) &dircolor);		}	}	if (c_i->dir && !conn->from) {		struct string string;		unsigned char *uristring;		if (!conn->uri->data) {			abort_conn_with_state(conn, S_FTP_ERROR);			return;		}		uristring = get_uri_string(conn->uri, URI_PUBLIC);		if (!uristring) goto out_of_mem;		if (!init_string(&string)) {			mem_free(uristring);			goto out_of_mem;		}		add_html_to_string(&string, uristring, strlen(uristring));		mem_free(uristring);#define ADD_CONST(str) { \	add_fragment(conn->cached, conn->from, str, sizeof(str) - 1); \	conn->from += (sizeof(str) - 1); }#define ADD_STRING() { \	add_fragment(conn->cached, conn->from, string.source, string.length); \	conn->from += string.length; }		ADD_CONST("<html>\n<head><title>");		ADD_STRING();		ADD_CONST("</title></head>\n<body>\n<h2>FTP directory ");		ADD_STRING();		ADD_CONST("</h2>\n<pre>");		done_string(&string);		if (conn->uri->datalen) {			struct ftp_file_info ftp_info = INIT_FTP_FILE_INFO_ROOT;			display_dir_entry(conn->cached, &conn->from, &conn->tries,					  colorize_dir, dircolor, &ftp_info);		}		mem_free_set(&conn->cached->content_type, stracpy("text/html"));	}	len = safe_read(conn->data_socket.fd, c_i->ftp_buffer + c_i->buf_pos,		        FTP_BUF_SIZE - c_i->buf_pos);	if (len < 0) {		retry_conn_with_state(conn, -errno);		return;	}	if (len > 0) {		if (!c_i->dir) {			conn->received += len;			if (add_fragment(conn->cached, conn->from,					 c_i->ftp_buffer, len) == 1)				conn->tries = 0;			conn->from += len;		} else {			int proceeded;			conn->received += len;			proceeded = ftp_process_dirlist(conn->cached,							&conn->from,							c_i->ftp_buffer,							len + c_i->buf_pos,							0, &conn->tries,							colorize_dir,							(unsigned char *) dircolor);			if (proceeded == -1) goto out_of_mem;			c_i->buf_pos += len - proceeded;			memmove(c_i->ftp_buffer, c_i->ftp_buffer + proceeded,				c_i->buf_pos);		}		set_connection_state(conn, S_TRANS);		return;	}	if (ftp_process_dirlist(conn->cached, &conn->from,				c_i->ftp_buffer, c_i->buf_pos, 1,				&conn->tries, colorize_dir,				(unsigned char *) dircolor) == -1)		goto out_of_mem;	if (c_i->dir) ADD_CONST("</pre>\n<hr>\n</body>\n</html>");	clear_handlers(conn->data_socket.fd);	close_socket(NULL, &conn->data_socket);	if (c_i->conn_state == 1) {		ftp_end_request(conn, S_OK);	} else {		c_i->conn_state = 2;		set_connection_state(conn, S_TRANS);	}}static voidftp_end_request(struct connection *conn, enum connection_state state){	set_connection_state(conn, state);	if (conn->state == S_OK && conn->cached) {		truncate_entry(conn->cached, conn->from, 1);		conn->cached->incomplete = 0;	}	add_keepalive_connection(conn, FTP_KEEPALIVE_TIMEOUT, NULL);}

⌨️ 快捷键说明

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