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

📄 user.c

📁 一个很有名的浏览器
💻 C
字号:
/* Internal "mailto", "telnet", "tn3270" and misc. protocol implementation *//* $Id: user.c,v 1.76.2.3 2005/04/06 09:12:06 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <ctype.h>#include <stdlib.h>#include <stdio.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "elinks.h"#include "bfu/dialog.h"#include "config/options.h"#include "intl/gettext/libintl.h"#include "modules/module.h"#include "osdep/osdep.h"#include "protocol/uri.h"#include "protocol/user.h"#include "sched/download.h"#include "sched/session.h"#include "terminal/terminal.h"#include "terminal/window.h"#include "util/conv.h"#include "util/file.h"#include "util/memory.h"#include "util/string.h"static struct option_info user_protocol_options[] = {	INIT_OPT_TREE("protocol", N_("User protocols"),		"user", OPT_AUTOCREATE,		N_("User protocols. Options in this tree specify external\n"		"handlers for the appropriate protocols. Ie.\n"		"protocol.user.mailto.unix.")),	/* FIXME: Poorly designed options structure. Ought to be able to specify	 * need_slashes, free_form and similar options as well :-(. --pasky */	/* Basically, it looks like protocol.user.mailto.win32 = "blah" */	INIT_OPT_TREE("protocol.user", NULL,		"_template_", OPT_AUTOCREATE,		N_("Handler (external program) for this protocol. Name the\n"		"options in this tree after your system (ie. unix, unix-xwin).")),	INIT_OPT_STRING("protocol.user._template_", NULL,		"_template_", 0, "",		N_("Handler (external program) for this protocol and system.\n"		"%f in the string means file name to include form data from\n"		"%h in the string means hostname (or email address)\n"		"%p in the string means port\n"		"%d in the string means path (everything after the port)\n"		"%s in the string means subject (?subject=<this>)\n"		"%u in the string means the whole URL")),#define INIT_OPT_USER_PROTOCOL(scheme, system, cmd) \	INIT_OPT_STRING("protocol.user." scheme, NULL, system, 0, cmd, NULL)#ifndef CONFIG_GOPHER	INIT_OPT_USER_PROTOCOL("gopher", "unix",	DEFAULT_AC_OPT_GOPHER),	INIT_OPT_USER_PROTOCOL("gopher", "unix-xwin",	DEFAULT_AC_OPT_GOPHER),#endif	INIT_OPT_USER_PROTOCOL("irc",	 "unix",	DEFAULT_AC_OPT_IRC),	INIT_OPT_USER_PROTOCOL("irc",	 "unix-xwin",	DEFAULT_AC_OPT_IRC),	INIT_OPT_USER_PROTOCOL("mailto", "unix",	DEFAULT_AC_OPT_MAILTO),	INIT_OPT_USER_PROTOCOL("mailto", "unix-xwin",	DEFAULT_AC_OPT_MAILTO),#ifndef CONFIG_NNTP	INIT_OPT_USER_PROTOCOL("news",	 "unix",	DEFAULT_AC_OPT_NEWS),	INIT_OPT_USER_PROTOCOL("news",	 "unix-xwin",	DEFAULT_AC_OPT_NEWS),#endif	INIT_OPT_USER_PROTOCOL("telnet", "unix",	DEFAULT_AC_OPT_TELNET),	INIT_OPT_USER_PROTOCOL("telnet", "unix-xwin",	DEFAULT_AC_OPT_TELNET),	INIT_OPT_USER_PROTOCOL("tn3270", "unix",	DEFAULT_AC_OPT_TN3270),	INIT_OPT_USER_PROTOCOL("tn3270", "unix-xwin",	DEFAULT_AC_OPT_TN3270),	NULL_OPTION_INFO,};struct module user_protocol_module = struct_module(	/* name: */		N_("User protocols"),	/* options: */		user_protocol_options,	/* hooks: */		NULL,	/* submodules: */	NULL,	/* data: */		NULL,	/* init: */		NULL,	/* done: */		NULL);unsigned char *get_user_program(struct terminal *term, unsigned char *progid, int progidlen){	struct option *opt;	int xwin = term ? term->environment & ENV_XWIN : 0;	struct string name;	if (!init_string(&name)) return NULL;	add_to_string(&name, "protocol.user.");	/* Now add lowercased progid part. Delicious. */	add_bytes_to_string(&name, progid, progidlen);	convert_to_lowercase(&name.source[sizeof("protocol.user.") - 1], progidlen);	add_char_to_string(&name, '.');	add_to_string(&name, get_system_str(xwin));	opt = get_opt_rec_real(config_options, name.source);	done_string(&name);	return (unsigned char *) (opt ? opt->value.string : NULL);}static unsigned char *subst_cmd(unsigned char *cmd, struct uri *uri, unsigned char *subj,	  unsigned char *formfile){	struct string string;	if (!init_string(&string)) return NULL;	while (*cmd) {		int p;		for (p = 0; cmd[p] && cmd[p] != '%'; p++);		add_bytes_to_string(&string, cmd, p);		cmd += p;		if (*cmd != '%') break;		cmd++;		/* TODO: Decode URI fragments before adding them. --jonas */		switch (*cmd) {			case 'u':			{				unsigned char *url = struri(uri);				int length = get_real_uri_length(uri);				add_shell_safe_to_string(&string, url, length);				break;			}			case 'h':				/* TODO	For some user protocols it would be				 *	better if substitution of each uri				 *	field was completely configurable. Now				 *	@host contains both the uri username				 *	field, (password field) and hostname				 *	field because it is useful for mailto				 *	protocol handling. */				/* It would break a lot of configurations so I				 * don't know. --jonas */				if (uri->userlen && uri->hostlen) {					int hostlen = uri->host + uri->hostlen - uri->user;					add_shell_safe_to_string(&string, uri->user,								 hostlen);				} else if (uri->host) {					add_shell_safe_to_string(&string, uri->host,								 uri->hostlen);				}				break;			case 'p':				if (uri->portlen)					add_shell_safe_to_string(&string, uri->port,								 uri->portlen);				break;			case 'd':				if (uri->datalen)					add_shell_safe_to_string(&string, uri->data,								 uri->datalen);				break;			case 's':				if (subj)					add_shell_safe_to_string(&string, subj,								 strlen(subj));				break;			case 'f':				if (formfile)					add_to_string(&string, formfile);				break;			default:				add_bytes_to_string(&string, cmd - 1, 2);				break;		}		if (*cmd) cmd++;	}	return string.source;}/* Stay silent about complete RFC 2368 support or do it yourself! ;-). * --pasky */static unsigned char *get_subject_from_query(unsigned char *query){	unsigned char *subject;	if (strncmp(query, "subject=", 8)) {		subject = strstr(query, "&subject=");		if (!subject) return NULL;		subject += 9;	} else {		subject = query + 8;	}	/* Return subject until next '&'-value or end of string */	return memacpy(subject, strcspn(subject, "&"));}static unsigned char *save_form_data_to_file(struct uri *uri){	unsigned char *filename = get_tempdir_filename("elinks-XXXXXX");	int formfd;	FILE *formfile;	if (!filename) return NULL;	formfd = safe_mkstemp(filename);	if (formfd < 0) {		mem_free(filename);		return NULL;	}	formfile = fdopen(formfd, "w");	if (!formfile) {		mem_free(filename);		close(formfd);		return NULL;	}	if (uri->post) {		/* Jump the content type */		unsigned char *formdata = strchr(uri->post, '\n');		formdata = formdata ? formdata + 1 : uri->post;		fwrite(formdata, strlen(formdata), 1, formfile);	}	fclose(formfile);	return filename;}voiduser_protocol_handler(struct session *ses, struct uri *uri){	unsigned char *subj = NULL, *prog;	unsigned char *formfilename;	prog = get_user_program(ses->tab->term, struri(uri), uri->protocollen);	if (!prog || !*prog) {		unsigned char *protocol = memacpy(struri(uri), uri->protocollen);		/* Shouldn't ever happen, but be paranoid. */		/* Happens when you're in X11 and you've no handler for it. */		info_box(ses->tab->term, MSGBOX_FREE_TEXT,			 N_("No program"), ALIGN_CENTER,			 msg_text(ses->tab->term,				 N_("No program specified for protocol %s."),				 empty_string_or_(protocol)));		mem_free_if(protocol);		return;	}	if (uri->data && uri->datalen) {		/* Some mailto specific stuff follows... */		unsigned char *query = get_uri_string(uri, URI_QUERY);		if (query) {			subj = get_subject_from_query(query);			mem_free(query);			if (subj) decode_uri(subj);		}	}	formfilename = save_form_data_to_file(uri);	prog = subst_cmd(prog, uri, subj, formfilename);	mem_free_if(subj);	if (prog) {		unsigned char *delete = empty_string_or_(formfilename);		exec_on_terminal(ses->tab->term, prog, delete, 1);		mem_free(prog);	} else if (formfilename) {		unlink(formfilename);	}	mem_free_if(formfilename);}

⌨️ 快捷键说明

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