Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of Hubbub.
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2008 John-Mark Bell <jmb@netsurf-browser.org>
  6.  */
  7.  
  8. #include <assert.h>
  9. #include <string.h>
  10.  
  11. #include <parserutils/charset/mibenum.h>
  12.  
  13. #include "treebuilder/modes.h"
  14. #include "treebuilder/internal.h"
  15. #include "treebuilder/treebuilder.h"
  16.  
  17. #include "charset/detect.h"
  18.  
  19. #include "utils/utils.h"
  20. #include "utils/string.h"
  21.  
  22.  
  23. /**
  24.  * Process a meta tag as if "in head".
  25.  *
  26.  * \param treebuilder  The treebuilder instance
  27.  * \param token        The token to process
  28.  */
  29. static hubbub_error process_meta_in_head(hubbub_treebuilder *treebuilder,
  30.                 const hubbub_token *token)
  31. {
  32.         static uint16_t utf16, utf16be, utf16le;
  33.         uint16_t charset_enc = 0;
  34.         uint16_t content_type_enc = 0;
  35.         size_t i;
  36.         hubbub_error err = HUBBUB_OK;
  37.  
  38.         err = insert_element(treebuilder, &token->data.tag, false);
  39.         if (err != HUBBUB_OK)
  40.                 return err;
  41.  
  42.         /** \todo ack sc flag */
  43.  
  44.         if (treebuilder->tree_handler->encoding_change == NULL)
  45.                 return err;
  46.  
  47.         /* Grab UTF-16 MIBenums */
  48.         if (utf16 == 0) {
  49.                 utf16 = parserutils_charset_mibenum_from_name(
  50.                                 "utf-16", SLEN("utf-16"));
  51.                 utf16be = parserutils_charset_mibenum_from_name(
  52.                                 "utf-16be", SLEN("utf-16be"));
  53.                 utf16le = parserutils_charset_mibenum_from_name(
  54.                                 "utf-16le", SLEN("utf-16le"));
  55.                 assert(utf16 != 0 && utf16be != 0 && utf16le != 0);
  56.         }
  57.  
  58.         for (i = 0; i < token->data.tag.n_attributes; i++) {
  59.                 hubbub_attribute *attr = &token->data.tag.attributes[i];
  60.  
  61.                 if (hubbub_string_match(attr->name.ptr, attr->name.len,
  62.                                 (const uint8_t *) "charset",
  63.                                 SLEN("charset")) == true) {
  64.                         /* Extract charset */
  65.                         charset_enc = parserutils_charset_mibenum_from_name(
  66.                                         (const char *) attr->value.ptr,
  67.                                         attr->value.len);
  68.                 } else if (hubbub_string_match(attr->name.ptr, attr->name.len,
  69.                                 (const uint8_t *) "content",
  70.                                 SLEN("content")) == true) {
  71.                         /* Extract charset from Content-Type */
  72.                         content_type_enc = hubbub_charset_parse_content(
  73.                                         attr->value.ptr, attr->value.len);
  74.                 }
  75.         }
  76.  
  77.         /* Fall back, if necessary */
  78.         if (charset_enc == 0 && content_type_enc != 0)
  79.                 charset_enc = content_type_enc;
  80.  
  81.         if (charset_enc != 0) {
  82.                 const char *name;
  83.  
  84.                 hubbub_charset_fix_charset(&charset_enc);
  85.  
  86.                 /* Change UTF-16 to UTF-8 */
  87.                 if (charset_enc == utf16le || charset_enc == utf16be ||
  88.                                 charset_enc == utf16) {
  89.                         charset_enc = parserutils_charset_mibenum_from_name(
  90.                                         "UTF-8", SLEN("UTF-8"));
  91.                 }
  92.  
  93.                 name = parserutils_charset_mibenum_to_name(charset_enc);
  94.  
  95.                 err = treebuilder->tree_handler->encoding_change(
  96.                                 treebuilder->tree_handler->ctx, name);
  97.         }
  98.  
  99.         return err;
  100. }
  101.  
  102. /**
  103.  * Handle token in "in head" insertion mode
  104.  *
  105.  * \param treebuilder  The treebuilder instance
  106.  * \param token        The token to handle
  107.  * \return True to reprocess token, false otherwise
  108.  */
  109. hubbub_error handle_in_head(hubbub_treebuilder *treebuilder,
  110.                 const hubbub_token *token)
  111. {
  112.         hubbub_error err = HUBBUB_OK;
  113.         bool handled = false;
  114.  
  115.         switch (token->type) {
  116.         case HUBBUB_TOKEN_CHARACTER:
  117.                 err = process_characters_expect_whitespace(treebuilder,
  118.                                 token, true);
  119.                 break;
  120.         case HUBBUB_TOKEN_COMMENT:
  121.                 err = process_comment_append(treebuilder, token,
  122.                                 treebuilder->context.element_stack[
  123.                                 treebuilder->context.current_node].node);
  124.                 break;
  125.         case HUBBUB_TOKEN_DOCTYPE:
  126.                 /** \todo parse error */
  127.                 break;
  128.         case HUBBUB_TOKEN_START_TAG:
  129.         {
  130.                 element_type type = element_type_from_name(treebuilder,
  131.                                 &token->data.tag.name);
  132.  
  133.                 if (type == HTML) {
  134.                         /* Process as if "in body" */
  135.                         err = handle_in_body(treebuilder, token);
  136.                 } else if (type == BASE || type == COMMAND || type == LINK) {
  137.                         err = insert_element(treebuilder, &token->data.tag,
  138.                                         false);
  139.  
  140.                         /** \todo ack sc flag */
  141.                 } else if (type == META) {
  142.                         err = process_meta_in_head(treebuilder, token);
  143.                 } else if (type == TITLE) {
  144.                         err = parse_generic_rcdata(treebuilder, token, true);
  145.                 } else if (type == NOFRAMES || type == STYLE) {
  146.                         err = parse_generic_rcdata(treebuilder, token, false);
  147.                 } else if (type == NOSCRIPT) {
  148.                         if (treebuilder->context.enable_scripting) {
  149.                                 err = parse_generic_rcdata(treebuilder, token,
  150.                                                 false);
  151.                         } else {
  152.                                 err = insert_element(treebuilder,
  153.                                                 &token->data.tag, true);
  154.                                 if (err != HUBBUB_OK)
  155.                                         return err;
  156.  
  157.                                 treebuilder->context.mode = IN_HEAD_NOSCRIPT;
  158.                         }
  159.                 } else if (type == SCRIPT) {
  160.                         /** \todo need to ensure that the client callback
  161.                          * sets the parser-inserted/already-executed script
  162.                          * flags. */
  163.                         err = parse_generic_rcdata(treebuilder, token, false);
  164.                 } else if (type == HEAD) {
  165.                         /** \todo parse error */
  166.                 } else {
  167.                         err = HUBBUB_REPROCESS;
  168.                 }
  169.         }
  170.                 break;
  171.         case HUBBUB_TOKEN_END_TAG:
  172.         {
  173.                 element_type type = element_type_from_name(treebuilder,
  174.                                 &token->data.tag.name);
  175.  
  176.                 if (type == HEAD) {
  177.                         handled = true;
  178.                 } else if (type == HTML || type == BODY || type == BR) {
  179.                         err = HUBBUB_REPROCESS;
  180.                 } /** \todo parse error */
  181.         }
  182.                 break;
  183.         case HUBBUB_TOKEN_EOF:
  184.                 err = HUBBUB_REPROCESS;
  185.                 break;
  186.         }
  187.  
  188.         if (handled || err == HUBBUB_REPROCESS) {
  189.                 hubbub_ns ns;
  190.                 element_type otype;
  191.                 void *node;
  192.  
  193.                 element_stack_pop(treebuilder, &ns, &otype, &node);
  194.  
  195.                 treebuilder->tree_handler->unref_node(
  196.                                 treebuilder->tree_handler->ctx,
  197.                                 node);
  198.  
  199.                 treebuilder->context.mode = AFTER_HEAD;
  200.         }
  201.  
  202.         return err;
  203. }
  204.