mailcap.c

来自「一个很有名的浏览器」· C语言 代码 · 共 677 行 · 第 1/2 页

C
677
字号
		type = get_mailcap_field(&linepos);		if (!type) continue;		/* Next field is the viewcommand */		command = get_mailcap_field(&linepos);		if (!command) continue;		entry = init_mailcap_entry(command, priority);		if (!entry) continue;		if (!parse_optional_fields(entry, linepos)) {			done_mailcap_entry(entry);			usrerror(gettext("Badly formated mailcap entry "			         "for type %s in \"%s\" line %d"),			         type, filename, lineno);			continue;		}		basetypeend = strchr(type, '/');		typelen = strlen(type);		if (!basetypeend) {			unsigned char implicitwild[64];			if (typelen + 3 > sizeof(implicitwild)) {				done_mailcap_entry(entry);				continue;			}			memcpy(implicitwild, type, typelen);			implicitwild[typelen++] = '/';			implicitwild[typelen++] = '*';			implicitwild[typelen++] = '\0';			add_mailcap_entry(entry, implicitwild, typelen);			continue;		}		add_mailcap_entry(entry, type, typelen);	}	fclose(file);	mem_free_if(line); /* Alloced by file_read_line() */}/* When initializing the mailcap map/hash read, parse and build a hash mapping * content type to handlers. Map is built from a list of mailcap files. * * The RFC1524 specifies that a path of mailcap files should be used. *	o First we check to see if the user supplied any in mime.mailcap.path *	o Then we check the MAILCAP environment variable. *	o Finally fall back to reasonable default */static struct hash *init_mailcap_map(void){	unsigned char *path;	unsigned int priority = 0;	mailcap_map = init_hash(8, &strhash);	if (!mailcap_map) return NULL;	/* Try to setup mailcap_path */	path = get_mailcap_path();	if (!path || !*path) path = getenv("MAILCAP");	if (!path) path = DEFAULT_MAILCAP_PATH;	while (*path) {		unsigned char *filename = get_next_path_filename(&path, ':');		if (!filename) continue;		parse_mailcap_file(filename, priority++);		mem_free(filename);	}	return mailcap_map;}static voiddone_mailcap(struct module *module){	struct hash_item *item;	int i;	if (!mailcap_map) return;	foreach_hash_item (item, *mailcap_map, i) {		struct mailcap_hash_item *mitem = item->value;		if (!mitem) continue;		while (!list_empty(mitem->entries)) {			struct mailcap_entry *entry = mitem->entries.next;			del_from_list(entry);			done_mailcap_entry(entry);		}		mem_free(mitem);	}	free_hash(mailcap_map);	mailcap_map = NULL;	mailcap_map_size = 0;}static intchange_hook_mailcap(struct session *ses, struct option *current, struct option *changed){	if (changed == &get_opt_mailcap(MAILCAP_PATH)	    || (changed == &get_opt_mailcap(MAILCAP_ENABLE)		&& !get_mailcap_enable())) {		done_mailcap(&mailcap_mime_module);	}	return 0;}static voidinit_mailcap(struct module *module){	struct change_hook_info mimetypes_change_hooks[] = {		{ "mime.mailcap",		change_hook_mailcap },		{ NULL,				NULL },	};	register_change_hooks(mimetypes_change_hooks);	if (get_cmd_opt_bool("anonymous"))		get_mailcap_enable() = 0;}/* The command semantics include the following: * * %s		is the filename that contains the mail body data * %t		is the content type, like text/plain * %{parameter} is replaced by the parameter value from the content-type *		field * \%		is % * * Unsupported RFC1524 parameters: these would probably require some doing * by Mutt, and can probably just be done by piping the message to metamail: * * %n		is the integer number of sub-parts in the multipart * %F		is "content-type filename" repeated for each sub-part * Only % is supported by subst_file() which is equivalent to %s. *//* The formatting is postponed until the command is needed. This means * @type can be NULL. If '%t' is used in command we bail out. */static unsigned char *format_command(unsigned char *command, unsigned char *type, int copiousoutput){	struct string cmd;	if (!init_string(&cmd)) return NULL;	while (*command) {		unsigned char *start = command;		while (*command && *command != '%' && *command != '\\')			command++;		if (start < command)			add_bytes_to_string(&cmd, start, command - start);		if (*command == '%') {			command++;			if (!*command) {				done_string(&cmd);				return NULL;			} else if (*command == 's') {				add_char_to_string(&cmd, '%');			} else if (*command == 't') {				if (!type) {					done_string(&cmd);					return NULL;				}				add_to_string(&cmd, type);			}			command++;		} else if (*command == '\\') {			command++;			if (*command) {				add_char_to_string(&cmd, *command);				command++;			}		}	}	if (copiousoutput) {		unsigned char *pager = getenv("PAGER");		if (!pager && file_exists(DEFAULT_PAGER_PATH)) {			pager = DEFAULT_PAGER_PATH;		} else if (!pager && file_exists(DEFAULT_LESS_PATH)) {			pager = DEFAULT_LESS_PATH;		} else if (!pager && file_exists(DEFAULT_MORE_PATH)) {			pager = DEFAULT_MORE_PATH;		}		if (pager) {			add_char_to_string(&cmd, '|');			add_to_string(&cmd, pager);		}	}	return cmd.source;}/* Returns first usable mailcap_entry from a list where @entry is the head. * Use of @filename is not supported (yet). */static struct mailcap_entry *check_entries(struct mailcap_hash_item *item){	struct mailcap_entry *entry;	foreach (entry, item->entries) {		unsigned char *test;		/* Accept current if no test is needed */		if (!entry->testcommand)			return entry;		/* We have to run the test command */		test = format_command(entry->testcommand, NULL, 0);		if (test) {			int exitcode = exe(test);			mem_free(test);			if (!exitcode)				return entry;		}	}	return NULL;}/* Attempts to find the given type in the mailcap association map.  On success, * this returns the associated command, else NULL.  Type is a string with * syntax '<base>/<type>' (ex: 'text/plain') * * First the given type is looked up. Then the given <base>-type with added * wildcard '*' (ex: 'text/<star>'). For each lookup all the associated * entries are checked/tested. * * The lookup supports testing on files. If no file is given (NULL) any tests * that need a file will be taken as failed. */static struct mailcap_entry *get_mailcap_entry(unsigned char *type){	struct mailcap_entry *entry;	struct hash_item *item;	item = get_hash_item(mailcap_map, type, strlen(type));	/* Check list of entries */	entry = (item && item->value) ? check_entries(item->value) : NULL;	if (!entry || get_mailcap_prioritize()) {		/* The type lookup has either failed or we need to check		 * the priorities so get the wild card handler */		struct mailcap_entry *wildcard = NULL;		unsigned char *wildpos = strchr(type, '/');		if (wildpos) {			int wildlen = wildpos - type + 1; /* include '/' */			unsigned char *wildtype = memacpy(type, wildlen + 2);			if (!wildtype) return NULL;			wildtype[wildlen++] = '*';			wildtype[wildlen] = '\0';			item = get_hash_item(mailcap_map, wildtype, wildlen);			mem_free(wildtype);			if (item && item->value)				wildcard = check_entries(item->value);		}		/* Use @wildcard if its priority is better or @entry is NULL */		if (wildcard && (!entry || (wildcard->priority < entry->priority)))			entry = wildcard;	}	return entry;}static struct mime_handler *get_mime_handler_mailcap(unsigned char *type, int options){	struct mailcap_entry *entry;	struct mime_handler *handler;	unsigned char *program;	int block;	if (!get_mailcap_enable()	    || (!mailcap_map && !init_mailcap_map()))		return NULL;	entry = get_mailcap_entry(type);	if (!entry) return NULL;	program = format_command(entry->command, type, entry->copiousoutput);	if (!program) return NULL;	block = (entry->needsterminal || entry->copiousoutput);	handler = init_mime_handler(program, entry->description,				    mailcap_mime_module.name,				    get_mailcap_ask(), block);	mem_free(program);	return handler;}struct mime_backend mailcap_mime_backend = {	/* get_content_type: */	NULL,	/* get_mime_handler: */	get_mime_handler_mailcap,};/* Setup the exported module. */struct module mailcap_mime_module = struct_module(	/* name: */		N_("Mailcap"),	/* options: */		mailcap_options,	/* hooks: */		NULL,	/* submodules: */	NULL,	/* data: */		NULL,	/* init: */		init_mailcap,	/* done: */		done_mailcap);

⌨️ 快捷键说明

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