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 + -
显示快捷键?