diff options
author | John Mark Bell <jmb@netsurf-browser.org> | 2011-05-06 20:40:09 +0000 |
---|---|---|
committer | John Mark Bell <jmb@netsurf-browser.org> | 2011-05-06 20:40:09 +0000 |
commit | e71691bae890040b83cfd54a2d9a1097d5026866 (patch) | |
tree | 96b2680dc6559ca0ab88fa0b6a533c13b7c9487e /content/content_factory.c | |
parent | e77b1a29550e4753f771848705975295a6ebe99e (diff) | |
download | netsurf-e71691bae890040b83cfd54a2d9a1097d5026866.tar.gz netsurf-e71691bae890040b83cfd54a2d9a1097d5026866.tar.bz2 |
Merge branches/jmb/content-factory to trunk
svn path=/trunk/netsurf/; revision=12283
Diffstat (limited to 'content/content_factory.c')
-rw-r--r-- | content/content_factory.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/content/content_factory.c b/content/content_factory.c new file mode 100644 index 000000000..95e7679ad --- /dev/null +++ b/content/content_factory.c @@ -0,0 +1,195 @@ +/* + * Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** \file + * Content factory (implementation) + */ + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include "content/content.h" +#include "content/content_factory.h" +#include "content/content_protected.h" +#include "content/llcache.h" + +/** + * Entry in list of content handlers + */ +typedef struct content_handler_entry { + /** Next entry */ + struct content_handler_entry *next; + + /** MIME type handled by handler */ + lwc_string *mime_type; + /** Content handler object */ + const content_handler *handler; +} content_handler_entry; + +static content_handler_entry *content_handlers; + +/** + * Register a handler with the content factory + * + * \param mime_type MIME type to handle + * \param handler Content handler for MIME type + * \return NSERROR_OK on success, appropriate error otherwise + * + * \note Latest registration for a MIME type wins + */ +nserror content_factory_register_handler(lwc_string *mime_type, + const content_handler *handler) +{ + content_handler_entry *entry; + bool match; + + for (entry = content_handlers; entry != NULL; entry = entry->next) { + if (lwc_string_caseless_isequal(mime_type, entry->mime_type, + &match) == lwc_error_ok && match) + break; + } + + if (entry == NULL) { + entry = malloc(sizeof(content_handler_entry)); + if (entry == NULL) + return NSERROR_NOMEM; + + entry->next = content_handlers; + content_handlers = entry; + + entry->mime_type = lwc_string_ref(mime_type); + } + + entry->handler = handler; + + return NSERROR_OK; +} + +/** + * Find a handler for a MIME type. + * + * \param mime_type MIME type to search for + * \return Associated handler, or NULL if none + */ +static const content_handler *content_lookup(lwc_string *mime_type) +{ + content_handler_entry *entry; + bool match; + + for (entry = content_handlers; entry != NULL; entry = entry->next) { + if (lwc_string_caseless_isequal(mime_type, entry->mime_type, + &match) == lwc_error_ok && match) + break; + } + + if (entry != NULL) + return entry->handler; + + return NULL; +} + +/** + * Compute the generic content type for a MIME type + * + * \param mime_type MIME type to consider + * \return Generic content type + */ +content_type content_factory_type_from_mime_type(const char *mime_type) +{ + const content_handler *handler; + lwc_string *imime_type; + lwc_error lerror; + content_type type = CONTENT_NONE; + + lerror = lwc_intern_string(mime_type, strlen(mime_type), &imime_type); + if (lerror != lwc_error_ok) + return CONTENT_NONE; + + handler = content_lookup(imime_type); + if (handler != NULL) { + type = handler->type(imime_type); + } + + lwc_string_unref(imime_type); + + return type; +} + +/** + * Create a content object + * + * \param llcache Underlying source data handle + * \param fallback_charset Character set to fall back to if none specified + * \param quirks Quirkiness of containing document + * \return Pointer to content object, or NULL on failure + */ +struct content *content_factory_create_content(llcache_handle *llcache, + const char *fallback_charset, bool quirks) +{ + struct content *c; + const char *content_type_header; + const content_handler *handler; + char *mime_type; + http_parameter *params; + lwc_string *imime_type; + lwc_error lerr; + nserror error; + + content_type_header = + llcache_handle_get_header(llcache, "Content-Type"); + if (content_type_header == NULL) + content_type_header = "text/plain"; + + error = http_parse_content_type(content_type_header, &mime_type, + ¶ms); + if (error != NSERROR_OK) + return NULL; + + lerr = lwc_intern_string(mime_type, strlen(mime_type), &imime_type); + if (lerr != lwc_error_ok) { + http_parameter_list_destroy(params); + free(mime_type); + return NULL; + } + + free(mime_type); + + handler = content_lookup(imime_type); + if (handler == NULL) { + lwc_string_unref(imime_type); + http_parameter_list_destroy(params); + return NULL; + } + + assert(handler->create != NULL); + + error = handler->create(handler, imime_type, params, llcache, + fallback_charset, quirks, &c); + if (error != NSERROR_OK) { + lwc_string_unref(imime_type); + http_parameter_list_destroy(params); + return NULL; + } + + lwc_string_unref(imime_type); + http_parameter_list_destroy(params); + + return c; +} + |