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

📄 mailcap.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* RFC1524 (mailcap file) implementation *//* $Id: mailcap.c,v 1.87.2.4 2005/05/01 22:03:23 jonas Exp $ *//* This file contains various functions for implementing a fair subset of * rfc1524. * * The rfc1524 defines a format for the Multimedia Mail Configuration, which is * the standard mailcap file format under Unix which specifies what external * programs should be used to view/compose/edit multimedia files based on * content type. * * Copyright (C) 1996-2000 Michael R. Elkins <me@cs.hmc.edu> * Copyright (c) 2002-2004 The ELinks project * * This file was hijacked from the Mutt project <URL:http://www.mutt.org> * (version 1.4) on Saturday the 7th December 2002. It has been heavily * elinksified. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "elinks.h"#include "config/options.h"#include "intl/gettext/libintl.h"#include "mime/backend/common.h"#include "mime/backend/mailcap.h"#include "mime/mime.h"#include "modules/module.h"#include "osdep/osdep.h"		/* For exe() */#include "sched/session.h"#include "util/file.h"#include "util/hash.h"#include "util/lists.h"#include "util/memory.h"#include "util/string.h"struct mailcap_hash_item {	/* The entries associated with the type */	struct list_head entries; /* -> struct mailcap_entry */	/* The content type of all @entries. Must be last! */	unsigned char type[1];};struct mailcap_entry {	LIST_HEAD(struct mailcap_entry);	/* To verify if command qualifies. Cannot contain %s formats. */	unsigned char *testcommand;	/* Used to inform the user of the type or handler. */	unsigned char *description;	/* Used to determine between an exact match and a wildtype match. Lower	 * is better. Increased for each sourced file. */	unsigned int priority;	/* Whether the program "blocks" the term. */	unsigned int needsterminal:1;	/* If "| ${PAGER}" should be added. It would of course be better to	 * pipe the output into a buffer and let ELinks display it but this	 * will have to do for now. */	unsigned int copiousoutput:1;	/* The 'raw' unformatted (view)command from the mailcap files. */	unsigned char command[1];};enum mailcap_option {	MAILCAP_TREE,	MAILCAP_ENABLE,	MAILCAP_PATH,	MAILCAP_ASK,	MAILCAP_DESCRIPTION,	MAILCAP_PRIORITIZE,	MAILCAP_OPTIONS};static struct option_info mailcap_options[] = {	INIT_OPT_TREE("mime", N_("Mailcap"),		"mailcap", 0,		N_("Options for mailcap support.")),	INIT_OPT_BOOL("mime.mailcap", N_("Enable"),		"enable", 0, 1,		N_("Enable mailcap support.")),	INIT_OPT_STRING("mime.mailcap", N_("Path"),		"path", 0, DEFAULT_MAILCAP_PATH,		N_("Mailcap search path. Colon-separated list of files.\n"		"Leave as \"\" to use MAILCAP environment variable instead.")),	INIT_OPT_BOOL("mime.mailcap", N_("Ask before opening"),		"ask", 0, 1,		N_("Ask before using the handlers defined by mailcap.")),	INIT_OPT_INT("mime.mailcap", N_("Type query string"),		"description", 0, 0, 2, 0,		N_("Type of description to show in \"what to do with this file\"\n"		"query dialog:\n"		"0 is show \"mailcap\"\n"		"1 is show program to be run\n"		"2 is show mailcap description field if any; \"mailcap\" otherwise")),	INIT_OPT_BOOL("mime.mailcap", N_("Prioritize entries by file"),		"prioritize", 0, 1,		N_("Prioritize entries by the order of the files in the mailcap\n"		"path. This means that wildcard entries (like: image/*) will\n"		"also be checked before deciding the handler.")),	NULL_OPTION_INFO,};#define get_opt_mailcap(which)		mailcap_options[(which)].option#define get_mailcap(which)		get_opt_mailcap(which).value#define get_mailcap_ask()		get_mailcap(MAILCAP_ASK).number#define get_mailcap_description()	get_mailcap(MAILCAP_DESCRIPTION).number#define get_mailcap_enable()		get_mailcap(MAILCAP_ENABLE).number#define get_mailcap_prioritize()	get_mailcap(MAILCAP_PRIORITIZE).number#define get_mailcap_path()		get_mailcap(MAILCAP_PATH).string/* State variables */static struct hash *mailcap_map = NULL;static int mailcap_map_size = 0;static inline voiddone_mailcap_entry(struct mailcap_entry *entry){	if (!entry) return;	mem_free_if(entry->testcommand);	mem_free_if(entry->description);	mem_free(entry);}/* Takes care of all initialization of mailcap entries. * Clear memory to make freeing it safer later and we get * needsterminal and copiousoutput initialized for free. */static inline struct mailcap_entry *init_mailcap_entry(unsigned char *command, int priority){	struct mailcap_entry *entry;	int commandlen = strlen(command);	entry = mem_calloc(1, sizeof(*entry) + commandlen);	if (!entry) return NULL;	memcpy(entry->command, command, commandlen);	entry->priority = priority;	return entry;}static inline voidadd_mailcap_entry(struct mailcap_entry *entry, unsigned char *type, int typelen){	struct mailcap_hash_item *mitem;	struct hash_item *item;	/* Time to get the entry into the mailcap_map */	/* First check if the type is already checked in */	item = get_hash_item(mailcap_map, type, typelen);	if (!item) {		mitem = mem_alloc(sizeof(*mitem) + typelen);		if (!mitem) {			done_mailcap_entry(entry);			return;		}		safe_strncpy(mitem->type, type, typelen + 1);		init_list(mitem->entries);		item = add_hash_item(mailcap_map, mitem->type, typelen, mitem);		if (!item) {			mem_free(mitem);			done_mailcap_entry(entry);			return;		}	} else if (item->value) {		mitem = item->value;	} else {		done_mailcap_entry(entry);		return;	}	add_to_list_end(mitem->entries, entry);	mailcap_map_size++;}/* Parsing of a RFC1524 mailcap file *//* The format is: * *	base/type; command; extradefs * * type can be * for matching all; base with no /type is an implicit * wildcard; command contains a %s for the filename to pass, default to pipe on * stdin; extradefs are of the form: * *	def1="definition"; def2="define \;"; * * line wraps with a \ at the end of the line, # for comments. *//* TODO handle default pipe. Maybe by prepending "cat |" to the command. *//* Returns a NULL terminated RFC 1524 field, while modifying @next to point * to the next field. */static unsigned char *get_mailcap_field(unsigned char **next){	unsigned char *field;	unsigned char *fieldend;	if (!next || !*next) return NULL;	field = *next;	skip_space(field);	fieldend = field;	/* End field at the next occurence of ';' but not escaped '\;' */	do {		/* Handle both if ';' is the first char or if it's escaped */		if (*fieldend == ';')			fieldend++;		fieldend = strchr(fieldend, ';');	} while (fieldend && *(fieldend-1) == '\\');	if (fieldend) {		*fieldend = '\0';		*next = fieldend;		fieldend--;		(*next)++;		skip_space(*next);	} else {		*next = NULL;		fieldend = field + strlen(field) - 1;	}	/* Remove trailing whitespace */	while (field <= fieldend && isspace(*fieldend))		*fieldend-- = '\0';	return field;}/* Parses specific fields (ex: the '=TestCommand' part of 'test=TestCommand'). * Expects that @field is pointing right after the specifier (ex: 'test' * above). Allocates and returns a NULL terminated token, or NULL if parsing * fails. */static unsigned char *get_mailcap_field_text(unsigned char *field){	skip_space(field);	if (*field == '=') {		field++;		skip_space(field);		return stracpy(field);	}	return NULL;}/* Parse optional extra definitions. Zero return value means syntax error  */static inline intparse_optional_fields(struct mailcap_entry *entry, unsigned char *line){	while (0xf131d5) {		unsigned char *field = get_mailcap_field(&line);		if (!field) break;		if (!strncasecmp(field, "needsterminal", 13)) {				entry->needsterminal = 1;		} else if (!strncasecmp(field, "copiousoutput", 13)) {			entry->copiousoutput = 1;		} else if (!strncasecmp(field, "test", 4)) {			entry->testcommand = get_mailcap_field_text(field + 4);			if (!entry->testcommand)				return 0;			/* Find out wether testing requires filename */			for (field = entry->testcommand; *field; field++)				if (*field == '%' && *(field+1) == 's') {					mem_free(entry->testcommand);					return 0;				}		} else if (!strncasecmp(field, "description", 11)) {			entry->description = get_mailcap_field_text(field + 11);			if (!entry->description)				return 0;		}	}	return 1;}/* Parses whole mailcap files line-by-line adding entries to the map * assigning them the given @priority */static voidparse_mailcap_file(unsigned char *filename, unsigned int priority){	FILE *file = fopen(filename, "rb");	unsigned char *line = NULL;	size_t linelen = MAX_STR_LEN;	int lineno = 1;	if (!file) return;	while ((line = file_read_line(line, &linelen, file, &lineno))) {		struct mailcap_entry *entry;		unsigned char *linepos;		unsigned char *command;		unsigned char *basetypeend;		unsigned char *type;		int typelen;		/* Ignore comments */		if (*line == '#') continue;		linepos = line;		/* Get type */

⌨️ 快捷键说明

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