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

📄 download.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 2 页
字号:
	int sf = 0;#else	int sf = cdf_hop->safe;#endif	if (!file) goto finish;	wd = get_cwd();	set_cwd(term->cwd);	/* O_APPEND means repositioning at the end of file before each write(),	 * thus ignoring seek()s and that can hide mysterious bugs. IMHO.	 * --pasky */	h = open(file, O_CREAT | O_WRONLY | (resume ? 0 : O_TRUNC)			| (sf && !resume ? O_EXCL : 0),		 sf ? 0600 : 0666);	saved_errno = errno; /* Saved in case of ... --Zas */	if (wd) {		set_cwd(wd);		mem_free(wd);	}	if (h == -1) {		info_box(term, MSGBOX_FREE_TEXT,			 N_("Download error"), ALIGN_CENTER,			 msg_text(term, N_("Could not create file '%s':\n%s"),				  file, strerror(saved_errno)));		mem_free(file);		goto finish;	} else {		set_bin(h);		if (!cdf_hop->safe) {			unsigned char *download_dir = get_opt_str("document.download.directory");			int i;			safe_strncpy(download_dir, file, MAX_STR_LEN);			/* Find the used directory so it's available in history */			for (i = strlen(download_dir); i >= 0; i--)				if (dir_sep(download_dir[i]))					break;			download_dir[i + 1] = 0;		}	}	if (cdf_hop->real_file)		*cdf_hop->real_file = file;	else		mem_free(file);finish:	cdf_hop->callback(term, h, cdf_hop->data, resume);	mem_free(cdf_hop);}voidcreate_download_file(struct terminal *term, unsigned char *fi,		     unsigned char **real_file, int safe, int resume,		     void (*callback)(struct terminal *, int, void *, int),		     void *data){	struct cdf_hop *cdf_hop = mem_calloc(1, sizeof(*cdf_hop));	unsigned char *wd;	if (!cdf_hop) {		callback(term, -1, data, 0);		return;	}	cdf_hop->real_file = real_file;	cdf_hop->safe = safe;	cdf_hop->callback = callback;	cdf_hop->data = data;	/* FIXME: The wd bussiness is probably useless here? --pasky */	wd = get_cwd();	set_cwd(term->cwd);	/* Also the tilde will be expanded here. */	lookup_unique_name(term, fi, resume, create_download_file_do, cdf_hop);	if (wd) {		set_cwd(wd);		mem_free(wd);	}}static unsigned char *get_temp_name(struct uri *uri){	struct string name;	unsigned char *extension;	/* FIXME	 * We use tempnam() here, which is unsafe (race condition), for now.	 * This should be changed at some time, but it needs an in-depth work	 * of whole download code. --Zas */	unsigned char *nm = tempnam(NULL, ELINKS_TEMPNAME_PREFIX);	if (!nm) return NULL;	if (!init_string(&name)) {		free(nm);		return NULL;	}	add_to_string(&name, nm);	free(nm);	extension = get_extension_from_uri(uri);	if (extension) {		add_shell_safe_to_string(&name, extension, strlen(extension));		mem_free(extension);	}	return name.source;}static unsigned char *subst_file(unsigned char *prog, unsigned char *file){	struct string name;	if (!init_string(&name)) return NULL;	while (*prog) {		int p;		for (p = 0; prog[p] && prog[p] != '%'; p++);		add_bytes_to_string(&name, prog, p);		prog += p;		if (*prog == '%') {#if defined(HAVE_CYGWIN_CONV_TO_FULL_WIN32_PATH)#ifdef MAX_PATH			unsigned char new_path[MAX_PATH];#else			unsigned char new_path[1024];#endif			cygwin_conv_to_full_win32_path(file, new_path);			add_to_string(&name, new_path);#else			add_to_string(&name, file);#endif			prog++;		}	}	return name.source;}struct cmdw_hop {	struct session *ses;	unsigned char *real_file;};static voidcommon_download_do(struct terminal *term, int fd, void *data, int resume){	struct cmdw_hop *cmdw_hop = data;	unsigned char *file = cmdw_hop->real_file;	struct file_download *file_download;	struct session *ses = cmdw_hop->ses;	struct stat buf;	mem_free(cmdw_hop);	if (!file || fstat(fd, &buf)) return;	file_download = init_file_download(ses->download_uri, ses, file, fd);	if (!file_download) return;	file_download->last_pos = resume ? (int) buf.st_size : 0;	display_download(ses->tab->term, file_download, ses);	load_uri(file_download->uri, ses->referrer, &file_download->download,		 PRI_DOWNLOAD, CACHE_MODE_NORMAL, file_download->last_pos);}static voidcommon_download(struct session *ses, unsigned char *file, int resume){	struct cmdw_hop *cmdw_hop;	if (!ses->download_uri) return;	cmdw_hop = mem_calloc(1, sizeof(*cmdw_hop));	if (!cmdw_hop) return;	cmdw_hop->ses = ses;	kill_downloads_to_file(file);	create_download_file(ses->tab->term, file, &cmdw_hop->real_file, 0,			     resume, common_download_do, cmdw_hop);}voidstart_download(void *ses, unsigned char *file){	common_download(ses, file, 0);}voidresume_download(void *ses, unsigned char *file){	common_download(ses, file, 1);}struct codw_hop {	struct type_query *type_query;	unsigned char *real_file;	unsigned char *file;};static void tp_cancel(void *);static voidcontinue_download_do(struct terminal *term, int fd, void *data, int resume){	struct codw_hop *codw_hop = data;	struct file_download *file_download = NULL;	struct type_query *type_query;	assert(codw_hop);	assert(codw_hop->type_query);	assert(codw_hop->type_query->uri);	assert(codw_hop->type_query->ses);	type_query = codw_hop->type_query;	if (!codw_hop->real_file) goto cancel;	file_download = init_file_download(type_query->uri, type_query->ses,					   codw_hop->real_file, fd);	if (!file_download) goto cancel;	if (type_query->external_handler) {		file_download->external_handler = subst_file(type_query->external_handler,							     codw_hop->file);		file_download->delete = 1;		mem_free(codw_hop->file);		mem_free_set(&type_query->external_handler, NULL);	}	file_download->external_handler_flags = type_query->external_handler_flags;	/* Done here and not in init_file_download() so that the external	 * handler can become initialized. */	display_download(term, file_download, type_query->ses);	change_connection(&type_query->download, &file_download->download, PRI_DOWNLOAD, 0);	done_type_query(type_query);	mem_free(codw_hop);	return;cancel:	if (type_query->external_handler) mem_free_if(codw_hop->file);	tp_cancel(type_query);	mem_free(codw_hop);}static voidcontinue_download(void *data, unsigned char *file){	struct type_query *type_query = data;	struct codw_hop *codw_hop = mem_calloc(1, sizeof(*codw_hop));	if (!codw_hop) {		tp_cancel(type_query);		return;	}	if (type_query->external_handler) {		/* FIXME: get_temp_name() calls tempnam(). --Zas */		file = get_temp_name(type_query->uri);		if (!file) {			mem_free(codw_hop);			tp_cancel(type_query);			return;		}	}	codw_hop->type_query = type_query;	codw_hop->file = file;	kill_downloads_to_file(file);	create_download_file(type_query->ses->tab->term, file,			     &codw_hop->real_file,			     !!type_query->external_handler, 0,			     continue_download_do, codw_hop);}static struct type_query *init_type_query(struct session *ses, struct download *download,	struct cache_entry *cached){	struct type_query *type_query;	/* There can be only one ... */	foreach (type_query, ses->type_queries)		if (compare_uri(type_query->uri, ses->loading_uri, 0))			return NULL;	type_query = mem_calloc(1, sizeof(*type_query));	if (!type_query) return NULL;	type_query->uri = get_uri_reference(ses->loading_uri);	type_query->ses = ses;	type_query->target_frame = null_or_stracpy(ses->task.target_frame);	type_query->cached = cached;	object_lock(type_query->cached);	change_connection(download, &type_query->download, PRI_MAIN, 0);	download->state = S_OK;	add_to_list(ses->type_queries, type_query);	return type_query;}voiddone_type_query(struct type_query *type_query){	/* Unregister any active download */	if (is_in_progress_state(type_query->download.state))		change_connection(&type_query->download, NULL, PRI_CANCEL, 0);	object_unlock(type_query->cached);	done_uri(type_query->uri);	mem_free_if(type_query->external_handler);	mem_free_if(type_query->target_frame);	del_from_list(type_query);	mem_free(type_query);}static voidtp_cancel(void *data){	struct type_query *type_query = data;	/* XXX: Should we really abort? (1 vs 0 as the last param) --pasky */	change_connection(&type_query->download, NULL, PRI_CANCEL, 1);	done_type_query(type_query);}static voidtp_save(struct type_query *type_query){	mem_free_set(&type_query->external_handler, NULL);	query_file(type_query->ses, type_query->uri, type_query, continue_download, tp_cancel, 1);}static voidtp_open(struct type_query *type_query){	continue_download(type_query, "");}static voidtp_show_header(struct type_query *type_query){	cached_header_dialog(type_query->ses, type_query->cached);	done_type_query(type_query);}/* FIXME: We need to modify this function to take frame data instead, as we * want to use this function for frames as well (now, when frame has content * type text/plain, it is ignored and displayed as HTML). */static voidtp_display(struct type_query *type_query){	struct view_state *vs;	struct session *ses = type_query->ses;	struct uri *loading_uri = ses->loading_uri;	unsigned char *target_frame = ses->task.target_frame;	ses->loading_uri = type_query->uri;	ses->task.target_frame = type_query->target_frame;	vs = ses_forward(ses, type_query->frame);	if (vs) vs->plain = 1;	ses->loading_uri = loading_uri;	ses->task.target_frame = target_frame;	if (!type_query->frame) {		struct download *old = &type_query->download;		struct download *new = &cur_loc(ses)->download;		new->callback = (void (*)(struct download *, void *))				doc_loading_callback;		new->data = ses;		if (is_in_progress_state(old->state))			change_connection(old, new, PRI_MAIN, 0);		else			new->state = old->state;	}	display_timer(ses);	done_type_query(type_query);}static voiddo_type_query(struct type_query *type_query, unsigned char *ct, struct mime_handler *handler){	struct string filename;	mem_free_set(&type_query->external_handler, NULL);	if (handler) {		type_query->external_handler = stracpy(handler->program);		type_query->external_handler_flags = handler->block;		if (!handler->ask) {			tp_open(type_query);			return;		}	}	if (init_string(&filename))		add_mime_filename_to_string(&filename, type_query->uri);	/* Let's make the filename pretty for display & save */	decode_uri_string_for_display(&filename);	if (!handler) {		if (!get_cmd_opt_bool("anonymous")) {			msg_box(type_query->ses->tab->term, NULL, MSGBOX_FREE_TEXT,				N_("Unknown type"), ALIGN_CENTER,				msg_text(type_query->ses->tab->term, N_("Would you like to "					 "save the file '%s' (type: %s) "					 "or display it?"),					 filename.source, ct),				type_query, 4,				N_("Sa~ve"), tp_save, B_ENTER,				N_("~Display"), tp_display, 0,				N_("Show ~header"), tp_show_header, 0,				N_("~Cancel"), tp_cancel, B_ESC);		} else {			msg_box(type_query->ses->tab->term, NULL, MSGBOX_FREE_TEXT,				N_("Unknown type"), ALIGN_CENTER,				msg_text(type_query->ses->tab->term, N_("Would you like to "					 "display the file '%s' (type: %s)?"),					 filename.source, ct),				type_query, 3,				N_("~Display"), tp_display, B_ENTER,				N_("Show ~header"), tp_show_header, 0,				N_("~Cancel"), tp_cancel, B_ESC);		}	} else {		unsigned char *description = handler->description;		unsigned char *desc_sep = (*description) ? "; " : "";		if (!get_cmd_opt_bool("anonymous")) {			/* TODO: Improve the dialog to let the user correct the			 * used program. */			msg_box(type_query->ses->tab->term, NULL, MSGBOX_FREE_TEXT,				N_("What to do?"), ALIGN_CENTER,				msg_text(type_query->ses->tab->term, N_("Would you like to "					 "open the file '%s' (type: %s%s%s)\n"					 "with '%s', save it or display it?"),					 filename.source, ct, desc_sep,					 description, handler->program),				type_query, 5,				N_("~Open"), tp_open, B_ENTER,				N_("Sa~ve"), tp_save, 0,				N_("~Display"), tp_display, 0,				N_("Show ~header"), tp_show_header, 0,				N_("~Cancel"), tp_cancel, B_ESC);		} else {			msg_box(type_query->ses->tab->term, NULL, MSGBOX_FREE_TEXT,				N_("What to do?"), ALIGN_CENTER,				msg_text(type_query->ses->tab->term, N_("Would you like to "					 "open the file '%s' (type: %s%s%s)\n"					 "with '%s', or display it?"),					 filename.source, ct, desc_sep,					 description, handler->program),				type_query, 4,				N_("~Open"), tp_open, B_ENTER,				N_("~Display"), tp_display, 0,				N_("Show ~header"), tp_show_header, 0,				N_("~Cancel"), tp_cancel, B_ESC);		}	}	done_string(&filename);}struct {	unsigned char *type;	unsigned int plain:1;} static known_types[] = {	{ "text/html",			0 },	{ "application/xhtml+xml",	0 }, /* RFC 3236 */	{ "text/plain",			1 },	{ NULL,				1 },};intses_chktype(struct session *ses, struct download *loading, struct cache_entry *cached, int frame){	struct mime_handler *handler;	struct view_state *vs;	struct type_query *type_query;	unsigned char *ctype = get_content_type(cached);	int plaintext = 1;	int ret = 0;	int xwin, i;	if (!ctype || !*ctype)		goto plaintext_follow;	for (i = 0; known_types[i].type; i++) {		if (strcasecmp(ctype, known_types[i].type))			continue;		plaintext = known_types[i].plain;		goto plaintext_follow;	}	xwin = ses->tab->term->environment & ENV_XWIN;	handler = get_mime_type_handler(ctype, xwin);	if (!handler && strlen(ctype) >= 4 && !strncasecmp(ctype, "text", 4))		goto plaintext_follow;	type_query = init_type_query(ses, loading, cached);	if (type_query) {		ret = 1;		do_type_query(type_query, ctype, handler);	}	mem_free_if(handler);	return ret;plaintext_follow:	vs = ses_forward(ses, frame);	if (vs) vs->plain = plaintext;	return 0;}

⌨️ 快捷键说明

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