📄 mime.c
字号:
/* Functionality for handling mime types *//* $Id: mime.c,v 1.70 2004/10/14 18:50:37 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include "elinks.h"#include "cache/cache.h"#include "config/options.h"#include "encoding/encoding.h"#include "intl/gettext/libintl.h"#include "mime/backend/common.h"#include "mime/mime.h"#include "modules/module.h"#include "protocol/header.h" /* For parse_header() */#include "protocol/uri.h"#include "util/conv.h"#include "util/file.h"#include "util/memory.h"#include "util/string.h"enum mime_options { MIME_TREE, MIME_DEFAULT_TYPE, MIME_OPTIONS,};static struct option_info mime_options[] = { INIT_OPT_TREE("", N_("MIME"), "mime", OPT_SORT, N_("MIME-related options (handlers of various MIME types).")), INIT_OPT_STRING("mime", N_("Default MIME-type"), "default_type", 0, DEFAULT_MIME_TYPE, N_("Document MIME-type to assume by default (when we are unable to\n" "guess it properly from known information about the document).")), NULL_OPTION_INFO,};#define get_opt_mime(which) mime_options[(which)].option#define get_default_mime_type() get_opt_mime(MIME_DEFAULT_TYPE).value.string/* Checks protocols headers for a suitable filename */static unsigned char *get_content_filename(struct uri *uri, struct cache_entry *cached){ unsigned char *filename, *pos; if (!cached) cached = find_in_cache(uri); if (!cached || !cached->head) return NULL; pos = parse_header(cached->head, "Content-Disposition", NULL); if (!pos) return NULL; filename = parse_header_param(pos, "filename"); mem_free(pos); if (!filename) return NULL; /* We don't want to add any directories from the path so make sure we * only add the filename. */ pos = get_filename_position(filename); if (!*pos) { mem_free(filename); return NULL; } if (pos > filename) memmove(filename, pos, strlen(pos) + 1); return filename;}/* Checks if application/x-<extension> has any handlers. */static inline unsigned char *check_extension_type(unsigned char *extension){ /* Trim the extension so only last .<extension> is used. */ unsigned char *trimmed = strrchr(extension, '.'); struct mime_handler *handler; unsigned char *content_type; if (!trimmed) return NULL; content_type = straconcat("application/x-", trimmed + 1, NULL); if (!content_type) return NULL; handler = get_mime_type_handler(content_type, 1); if (handler) { mem_free(handler); return content_type; } mem_free(content_type); return NULL;}/* Check if part of the extension coresponds to a supported encoding and if it * has any handlers. */static inline unsigned char *check_encoding_type(unsigned char *extension){ enum stream_encoding encoding = guess_encoding(extension); unsigned char **extension_list; unsigned char *last_extension = strrchr(extension, '.'); if (encoding == ENCODING_NONE || !last_extension) return NULL; for (extension_list = listext_encoded(encoding); extension_list && *extension_list; extension_list++) { unsigned char *content_type; if (strcmp(*extension_list, last_extension)) continue; *last_extension = '\0'; content_type = get_content_type_backends(extension); *last_extension = '.'; return content_type; } return NULL;}#if 0#define DEBUG_CONTENT_TYPE#endif#ifdef DEBUG_CONTENT_TYPE#define debug_get_content_type_params(cached) \ DBG("get_content_type(head, url)\n=== head ===\n%s\n=== url ===\n%s\n", (cached)->head, struri((cached)->uri))#define debug_ctype(ctype__) DBG("ctype= %s", (ctype__))#define debug_extension(extension__) DBG("extension= %s", (extension__))#else#define debug_get_content_type_params(cached)#define debug_ctype(ctype__)#define debug_extension(extension__)#endifunsigned char *get_extension_content_type(unsigned char *extension){ unsigned char *ctype; assert(extension && *extension); ctype = get_content_type_backends(extension); debug_ctype(ctype); if (ctype) return ctype; ctype = check_encoding_type(extension); debug_ctype(ctype); if (ctype) return ctype; ctype = check_extension_type(extension); debug_ctype(ctype); return ctype;}unsigned char *get_cache_header_content_type(struct cache_entry *cached){ unsigned char *extension, *ctype; ctype = parse_header(cached->head, "Content-Type", NULL); if (ctype) { unsigned char *end = strchr(ctype, ';'); int ctypelen; if (end) *end = '\0'; ctypelen = strlen(ctype); while (ctypelen && ctype[--ctypelen] <= ' ') ctype[ctypelen] = '\0'; debug_ctype(ctype); if (*ctype) { return ctype; } mem_free(ctype); } /* This searches cached->head for filename so put here */ extension = get_content_filename(cached->uri, cached); debug_extension(extension); if (extension) { ctype = get_extension_content_type(extension); mem_free(extension); if (ctype) { return ctype; } } return NULL;}unsigned char *get_content_type(struct cache_entry *cached){ unsigned char *extension, *ctype; debug_get_content_type_params(cached); if (cached->content_type) return cached->content_type; /* If there's one in header, it's simple.. */ if (cached->head) { ctype = get_cache_header_content_type(cached); if (ctype && *ctype) { cached->content_type = ctype; return ctype; } mem_free_if(ctype); } /* We can't use the extension string we are getting below, because we * want to support also things like "ps.gz" - that'd never work, as we * would always compare only to "gz". */ /* Guess type accordingly to the extension */ extension = get_extension_from_uri(cached->uri); debug_extension(extension); if (extension) { /* XXX: A little hack for making extension handling case * insensitive. We could probably do it better by making * guess_encoding() case independent the real problem however * is with default (via option system) and mimetypes resolving * doing that option and hash lookup will not be easy to * convert. --jonas */ convert_to_lowercase(extension, strlen(extension)); ctype = get_extension_content_type(extension); mem_free(extension); if (ctype && *ctype) { cached->content_type = ctype; return ctype; } mem_free_if(ctype); } debug_ctype(get_default_mime_type()); /* Fallback.. use some hardwired default */ cached->content_type = stracpy(get_default_mime_type()); return cached->content_type;}struct mime_handler *get_mime_type_handler(unsigned char *content_type, int xwin){ return get_mime_handler_backends(content_type, xwin);}struct string *add_mime_filename_to_string(struct string *string, struct uri *uri){ unsigned char *filename = get_content_filename(uri, NULL); assert(uri->data); if (filename) { add_shell_safe_to_string(string, filename, strlen(filename)); mem_free(filename); return string; } return add_uri_to_string(string, uri, URI_FILENAME);}/* Backends dynamic area: */#include "mime/backend/default.h"#include "mime/backend/mailcap.h"#include "mime/backend/mimetypes.h"static struct module *mime_submodules[] = { &default_mime_module,#ifdef CONFIG_MAILCAP &mailcap_mime_module,#endif#ifdef CONFIG_MIMETYPES &mimetypes_mime_module,#endif NULL,};struct module mime_module = struct_module( /* name: */ N_("MIME"), /* options: */ mime_options, /* hooks: */ NULL, /* submodules: */ mime_submodules, /* data: */ NULL, /* init: */ NULL, /* done: */ NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -