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 libdom.
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
  6.  */
  7.  
  8. #include <assert.h>
  9. #include <stdlib.h>
  10.  
  11. #include "html/html_document.h"
  12. #include "html/html_element.h"
  13. #include "html/html_collection.h"
  14. #include "html/html_html_element.h"
  15. #include "html/html_head_element.h"
  16. #include "html/html_body_element.h"
  17. #include "html/html_link_element.h"
  18. #include "html/html_title_element.h"
  19. #include "html/html_meta_element.h"
  20. #include "html/html_form_element.h"
  21. #include "html/html_button_element.h"
  22. #include "html/html_input_element.h"
  23. #include "html/html_text_area_element.h"
  24. #include "html/html_opt_group_element.h"
  25. #include "html/html_option_element.h"
  26. #include "html/html_select_element.h"
  27.  
  28. #include "core/attr.h"
  29. #include "core/string.h"
  30. #include "utils/namespace.h"
  31. #include "utils/utils.h"
  32.  
  33. static struct dom_html_document_vtable html_document_vtable = {
  34.         {
  35.                 {
  36.                         {
  37.                                 DOM_NODE_EVENT_TARGET_VTABLE
  38.                         },
  39.                         DOM_NODE_VTABLE,
  40.                 },
  41.                 DOM_DOCUMENT_VTABLE_HTML
  42.         },
  43.         DOM_HTML_DOCUMENT_VTABLE
  44. };
  45.  
  46. static struct dom_node_protect_vtable html_document_protect_vtable = {
  47.         DOM_HTML_DOCUMENT_PROTECT_VTABLE
  48. };
  49.  
  50. /* Create a HTMLDocument */
  51. dom_exception _dom_html_document_create(
  52.                 dom_events_default_action_fetcher daf,
  53.                 void *daf_ctx,
  54.                 dom_html_document **doc)
  55. {
  56.         dom_exception error;
  57.         dom_html_document *result;
  58.  
  59.         result = malloc(sizeof(dom_html_document));
  60.         if (result == NULL)
  61.                 return DOM_NO_MEM_ERR;
  62.  
  63.         result->base.base.base.vtable = &html_document_vtable;
  64.         result->base.base.vtable = &html_document_protect_vtable;
  65.        
  66.         error = _dom_html_document_initialise(result, daf, daf_ctx);
  67.         if (error != DOM_NO_ERR) {
  68.                 free(result);
  69.                 return error;
  70.         }
  71.  
  72.         *doc = result;
  73.         return DOM_NO_ERR;
  74. }
  75.  
  76. /* Initialise a HTMLDocument */
  77. dom_exception _dom_html_document_initialise(dom_html_document *doc,
  78.                 dom_events_default_action_fetcher daf,
  79.                 void *daf_ctx)
  80. {
  81.         dom_exception error;
  82.         int sidx;
  83.  
  84.         error = _dom_document_initialise(&doc->base, daf, daf_ctx);
  85.         if (error != DOM_NO_ERR)
  86.                 return error;
  87.  
  88.         doc->title = NULL;
  89.         doc->referrer = NULL;
  90.         doc->domain = NULL;
  91.         doc->url = NULL;
  92.         doc->cookie = NULL;
  93.        
  94.         doc->memoised = calloc(sizeof(dom_string *), hds_COUNT);
  95.         if (doc->memoised == NULL) {
  96.                 error = DOM_NO_MEM_ERR;
  97.                 goto out;
  98.         }
  99.        
  100. #define HTML_DOCUMENT_STRINGS_ACTION(attr,str)                             \
  101.         error = dom_string_create_interned((const uint8_t *) #str,      \
  102.                                            SLEN(#str), &doc->memoised[hds_##attr]); \
  103.         if (error != DOM_NO_ERR) {                                      \
  104.                 goto out;                                               \
  105.         }
  106.  
  107. #include "html_document_strings.h"
  108. #undef HTML_DOCUMENT_STRINGS_ACTION
  109.  
  110. out:
  111.         if (doc->memoised != NULL && error != DOM_NO_ERR) {
  112.                 for(sidx = 0; sidx < hds_COUNT; ++sidx) {
  113.                         if (doc->memoised[sidx] != NULL) {
  114.                                 dom_string_unref(doc->memoised[sidx]);
  115.                         }
  116.                 }
  117.                 free(doc->memoised);
  118.                 doc->memoised = NULL;
  119.         }
  120.         return error;
  121. }
  122.  
  123. /* Finalise a HTMLDocument */
  124. bool _dom_html_document_finalise(dom_html_document *doc)
  125. {
  126.         int sidx;
  127.        
  128.         if (doc->cookie != NULL)
  129.                 dom_string_unref(doc->cookie);
  130.         if (doc->url != NULL)
  131.                 dom_string_unref(doc->url);
  132.         if (doc->domain != NULL)
  133.                 dom_string_unref(doc->domain);
  134.         if (doc->referrer != NULL)
  135.                 dom_string_unref(doc->referrer);
  136.         if (doc->title != NULL)
  137.                 dom_string_unref(doc->title);
  138.        
  139.         if (doc->memoised != NULL) {
  140.                 for(sidx = 0; sidx < hds_COUNT; ++sidx) {
  141.                         if (doc->memoised[sidx] != NULL) {
  142.                                 dom_string_unref(doc->memoised[sidx]);
  143.                         }
  144.                 }
  145.                 free(doc->memoised);
  146.                 doc->memoised = NULL;
  147.         }
  148.        
  149.         return _dom_document_finalise(&doc->base);
  150. }
  151.  
  152. /* Destroy a HTMLDocument */
  153. void _dom_html_document_destroy(dom_node_internal *node)
  154. {
  155.         dom_html_document *doc = (dom_html_document *) node;
  156.  
  157.         if (_dom_html_document_finalise(doc) == true)
  158.                 free(doc);
  159. }
  160.  
  161. dom_exception _dom_html_document_copy(dom_node_internal *old,
  162.                 dom_node_internal **copy)
  163. {
  164.         UNUSED(old);
  165.         UNUSED(copy);
  166.  
  167.         return DOM_NOT_SUPPORTED_ERR;
  168. }
  169.  
  170. /* Overloaded methods inherited from super class */
  171.  
  172. /** Internal method to support both kinds of create method */
  173. static dom_exception
  174. _dom_html_document_create_element_internal(dom_html_document *html,
  175.                                            dom_string *in_tag_name,
  176.                                            dom_string *namespace,
  177.                                            dom_string *prefix,
  178.                                            dom_html_element **result)
  179. {
  180.         dom_exception exc;
  181.         dom_string *tag_name;
  182.  
  183.         exc = dom_string_toupper(in_tag_name, true, &tag_name);
  184.         if (exc != DOM_NO_ERR)
  185.                 return exc;
  186.  
  187.         if (dom_string_caseless_isequal(tag_name, html->memoised[hds_HTML])) {
  188.                 exc = _dom_html_html_element_create(html, namespace, prefix,
  189.                                 (dom_html_html_element **) result);
  190.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_HEAD])) {
  191.                 exc = _dom_html_head_element_create(html, namespace, prefix,
  192.                                 (dom_html_head_element **) result);
  193.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_TITLE])) {
  194.                 exc = _dom_html_title_element_create(html, namespace, prefix,
  195.                                 (dom_html_title_element **) result);
  196.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_BODY])) {
  197.                 exc = _dom_html_body_element_create(html, namespace, prefix,
  198.                                 (dom_html_body_element **) result);
  199.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_FORM])) {
  200.                 exc = _dom_html_form_element_create(html, namespace, prefix,
  201.                                 (dom_html_form_element **) result);
  202.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_LINK])) {
  203.                 exc = _dom_html_link_element_create(html, namespace, prefix,
  204.                                 (dom_html_link_element **) result);
  205.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_BUTTON])) {
  206.                 exc = _dom_html_button_element_create(html, namespace, prefix,
  207.                                 (dom_html_button_element **) result);
  208.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_INPUT])) {
  209.                 exc = _dom_html_input_element_create(html, namespace, prefix,
  210.                                 (dom_html_input_element **) result);
  211.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_TEXTAREA])) {
  212.                 exc = _dom_html_text_area_element_create(html, namespace, prefix,
  213.                                 (dom_html_text_area_element **) result);
  214.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_OPTGROUP])) {
  215.                 exc = _dom_html_opt_group_element_create(html, namespace, prefix,
  216.                                 (dom_html_opt_group_element **) result);
  217.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_OPTION])) {
  218.                 exc = _dom_html_option_element_create(html, namespace, prefix,
  219.                                 (dom_html_option_element **) result);
  220.         } else if (dom_string_caseless_isequal(tag_name, html->memoised[hds_SELECT])) {
  221.                 exc = _dom_html_select_element_create(html, namespace, prefix,
  222.                                 (dom_html_select_element **) result);
  223.         } else {
  224.                 exc =  _dom_html_element_create(html, tag_name, namespace,
  225.                                                 prefix, result);
  226.         }
  227.  
  228.         dom_string_unref(tag_name);
  229.  
  230.         return exc;
  231. }
  232.  
  233. dom_exception _dom_html_document_create_element(dom_document *doc,
  234.                 dom_string *tag_name, dom_element **result)
  235. {
  236.         dom_html_document *html = (dom_html_document *) doc;
  237.  
  238.         return _dom_html_document_create_element_internal(html,
  239.                         tag_name, NULL, NULL,
  240.                         (dom_html_element **)result);
  241. }
  242.  
  243. dom_exception _dom_html_document_create_element_ns(dom_document *doc,
  244.                 dom_string *namespace, dom_string *qname,
  245.                 dom_element **result)
  246. {
  247.         dom_html_document *html = (dom_html_document *) doc;
  248.         dom_string *prefix, *localname;
  249.         dom_exception err;
  250.  
  251.         /* Divide QName into prefix/localname pair */
  252.         err = _dom_namespace_split_qname(qname, &prefix, &localname);
  253.         if (err != DOM_NO_ERR) {
  254.                 return err;
  255.         }
  256.  
  257.         /* Attempt to create element */
  258.         err = _dom_html_document_create_element_internal(html, localname,
  259.                         namespace, prefix, (dom_html_element **)result);
  260.  
  261.         /* Tidy up */
  262.         if (localname != NULL) {
  263.                 dom_string_unref(localname);
  264.         }
  265.  
  266.         if (prefix != NULL) {
  267.                 dom_string_unref(prefix);
  268.         }
  269.  
  270.         return err;
  271. }
  272.  
  273. /**
  274.  * Create an attribute
  275.  *
  276.  * \param doc     The document owning the attribute
  277.  * \param name    The name of the attribute
  278.  * \param result  Pointer to location to receive result
  279.  * \return DOM_NO_ERR                on success,
  280.  *
  281.  * The constructed attribute will always be classified as 'specified'.
  282.  *
  283.  * The returned node will have its reference count increased. It is
  284.  * the responsibility of the caller to unref the node once it has
  285.  * finished with it.
  286.  */
  287. dom_exception _dom_html_document_create_attribute(dom_document *doc,
  288.                 dom_string *name, dom_attr **result)
  289. {
  290.         return _dom_attr_create(doc, name, NULL, NULL, true, result);
  291. }
  292.  
  293. /**
  294.  * Create an attribute from the qualified name and namespace URI
  295.  *
  296.  * \param doc        The document owning the attribute
  297.  * \param namespace  The namespace URI to use
  298.  * \param qname      The qualified name of the attribute
  299.  * \param result     Pointer to location to receive result
  300.  * \return DOM_NO_ERR                on success,
  301.  *         DOM_NAMESPACE_ERR         if ::qname is malformed, or it has a
  302.  *                                   prefix and ::namespace is NULL, or
  303.  *                                   ::qname has a prefix "xml" and
  304.  *                                   ::namespace is not
  305.  *                                   "http://www.w3.org/XML/1998/namespace",
  306.  *                                   or ::qname has a prefix "xmlns" and
  307.  *                                   ::namespace is not
  308.  *                                   "http://www.w3.org/2000/xmlns", or
  309.  *                                   ::namespace is
  310.  *                                   "http://www.w3.org/2000/xmlns" and
  311.  *                                   ::qname is not (or is not prefixed by)
  312.  *                                   "xmlns",
  313.  *         DOM_NOT_SUPPORTED_ERR     if ::doc does not support the "XML"
  314.  *                                   feature.
  315.  *
  316.  * The returned node will have its reference count increased. It is
  317.  * the responsibility of the caller to unref the node once it has
  318.  * finished with it.
  319.  */
  320. dom_exception _dom_html_document_create_attribute_ns(dom_document *doc,
  321.                 dom_string *namespace, dom_string *qname,
  322.                 dom_attr **result)
  323. {
  324.         dom_string *prefix, *localname;
  325.         dom_exception err;
  326.  
  327.         /* Divide QName into prefix/localname pair */
  328.         err = _dom_namespace_split_qname(qname, &prefix, &localname);
  329.         if (err != DOM_NO_ERR) {
  330.                 return err;
  331.         }
  332.  
  333.         /* Attempt to create attribute */
  334.         err = _dom_attr_create(doc, localname, namespace, prefix, true, result);
  335.  
  336.         /* Tidy up */
  337.         if (localname != NULL) {
  338.                 dom_string_unref(localname);
  339.         }
  340.  
  341.         if (prefix != NULL) {
  342.                 dom_string_unref(prefix);
  343.         }
  344.  
  345.         return err;
  346. }
  347.  
  348. /**
  349.  * Retrieve a list of all elements with a given tag name
  350.  *
  351.  * \param doc      The document to search in
  352.  * \param tagname  The tag name to search for ("*" for all)
  353.  * \param result   Pointer to location to receive result
  354.  * \return DOM_NO_ERR.
  355.  *
  356.  * The returned list will have its reference count increased. It is
  357.  * the responsibility of the caller to unref the list once it has
  358.  * finished with it.
  359.  */
  360. dom_exception _dom_html_document_get_elements_by_tag_name(dom_document *doc,
  361.                 dom_string *tagname, dom_nodelist **result)
  362. {
  363.         return _dom_document_get_nodelist(doc, DOM_NODELIST_BY_NAME_CASELESS,
  364.                         (dom_node_internal *) doc,  tagname, NULL, NULL,
  365.                         result);
  366. }
  367.  
  368. /**
  369.  * Retrieve a list of all elements with a given local name and namespace URI
  370.  *
  371.  * \param doc        The document to search in
  372.  * \param namespace  The namespace URI
  373.  * \param localname  The local name
  374.  * \param result     Pointer to location to receive result
  375.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  376.  *
  377.  * The returned list will have its reference count increased. It is
  378.  * the responsibility of the caller to unref the list once it has
  379.  * finished with it.
  380.  */
  381. dom_exception _dom_html_document_get_elements_by_tag_name_ns(
  382.                 dom_document *doc, dom_string *namespace,
  383.                 dom_string *localname, dom_nodelist **result)
  384. {
  385.         return _dom_document_get_nodelist(doc, DOM_NODELIST_BY_NAMESPACE_CASELESS,
  386.                         (dom_node_internal *) doc, NULL, namespace, localname,
  387.                         result);
  388. }
  389.  
  390. /*-----------------------------------------------------------------------*/
  391. /* The DOM spec public API */
  392.  
  393. /**
  394.  * Get the title of this HTMLDocument
  395.  * \param doc    The document object
  396.  * \param title  The reutrned title string
  397.  * \return DOM_NO_ERR on success, appropriated dom_exception on failure.
  398.  *
  399.  * @note: this method find a title for the document as following:
  400.  * 1. If there is a title in the document object set by
  401.  *    dom_html_document_set_title, then use it;
  402.  * 2. If there is no such one, find the <title> element and use its text
  403.  *    as the returned title.
  404.  */
  405. dom_exception _dom_html_document_get_title(dom_html_document *doc,
  406.                 dom_string **title)
  407. {
  408.         dom_exception exc = DOM_NO_ERR;
  409.         *title = NULL;
  410.        
  411.         if (doc->title != NULL) {
  412.                 *title = dom_string_ref(doc->title);
  413.         } else {
  414.                 dom_element *node;
  415.                 dom_nodelist *nodes;
  416.                 uint32_t len;
  417.                
  418.                 exc = dom_document_get_elements_by_tag_name(doc,
  419.                                                             doc->memoised[hds_TITLE],
  420.                                                             &nodes);
  421.                 if (exc != DOM_NO_ERR) {
  422.                         return exc;
  423.                 }
  424.                
  425.                 exc = dom_nodelist_get_length(nodes, &len);
  426.                 if (exc != DOM_NO_ERR) {
  427.                         dom_nodelist_unref(nodes);
  428.                         return exc;
  429.                 }
  430.                
  431.                 if (len == 0) {
  432.                         dom_nodelist_unref(nodes);
  433.                         return DOM_NO_ERR;
  434.                 }
  435.                
  436.                 exc = dom_nodelist_item(nodes, 0, (void *) &node);
  437.                 dom_nodelist_unref(nodes);
  438.                 if (exc != DOM_NO_ERR) {
  439.                         return exc;
  440.                 }
  441.                
  442.                 exc = dom_node_get_text_content(node, title);
  443.                 dom_node_unref(node);
  444.         }
  445.  
  446.         return exc;
  447. }
  448.  
  449. dom_exception _dom_html_document_set_title(dom_html_document *doc,
  450.                 dom_string *title)
  451. {
  452.         if (doc->title != NULL)
  453.                 dom_string_unref(doc->title);
  454.  
  455.         doc->title = dom_string_ref(title);
  456.  
  457.         return DOM_NO_ERR;
  458. }
  459.  
  460. dom_exception _dom_html_document_get_referrer(dom_html_document *doc,
  461.                 dom_string **referrer)
  462. {
  463.         *referrer = dom_string_ref(doc->referrer);
  464.  
  465.         return DOM_NO_ERR;
  466. }
  467.  
  468. dom_exception _dom_html_document_get_domain(dom_html_document *doc,
  469.                 dom_string **domain)
  470. {
  471.         *domain = dom_string_ref(doc->domain);
  472.  
  473.         return DOM_NO_ERR;
  474. }
  475.  
  476. dom_exception _dom_html_document_get_url(dom_html_document *doc,
  477.                 dom_string **url)
  478. {
  479.         *url = dom_string_ref(doc->url);
  480.  
  481.         return DOM_NO_ERR;
  482. }
  483.  
  484. dom_exception _dom_html_document_get_body(dom_html_document *doc,
  485.                 struct dom_html_element **body)
  486. {
  487.         UNUSED(doc);
  488.         UNUSED(body);
  489.  
  490.         return DOM_NOT_SUPPORTED_ERR;
  491. }
  492.  
  493. dom_exception _dom_html_document_set_body(dom_html_document *doc,
  494.                 struct dom_html_element *body)
  495. {
  496.         UNUSED(doc);
  497.         UNUSED(body);
  498.  
  499.         return DOM_NOT_SUPPORTED_ERR;
  500. }
  501.  
  502. dom_exception _dom_html_document_get_images(dom_html_document *doc,
  503.                 struct dom_html_collection **col)
  504. {
  505.         UNUSED(doc);
  506.         UNUSED(col);
  507.  
  508.         return DOM_NOT_SUPPORTED_ERR;
  509. }
  510.  
  511. dom_exception _dom_html_document_get_applets(dom_html_document *doc,
  512.                 struct dom_html_collection **col)
  513. {
  514.         UNUSED(doc);
  515.         UNUSED(col);
  516.  
  517.         return DOM_NOT_SUPPORTED_ERR;
  518. }
  519.  
  520. dom_exception _dom_html_document_get_links(dom_html_document *doc,
  521.                 struct dom_html_collection **col)
  522. {
  523.         UNUSED(doc);
  524.         UNUSED(col);
  525.  
  526.         return DOM_NOT_SUPPORTED_ERR;
  527. }
  528.  
  529. static bool __dom_html_document_node_is_form(dom_node_internal *node,
  530.                                              void *ctx)
  531. {
  532.         dom_html_document *doc = (dom_html_document *)node->owner;
  533.        
  534.         UNUSED(ctx);
  535.        
  536.         return dom_string_caseless_isequal(node->name,
  537.                                            doc->memoised[hds_FORM]);
  538. }
  539.  
  540. dom_exception _dom_html_document_get_forms(dom_html_document *doc,
  541.                 struct dom_html_collection **col)
  542. {
  543.         dom_html_collection *result;
  544.         dom_element *root;
  545.         dom_exception err;
  546.  
  547.         err = dom_document_get_document_element(doc, &root);
  548.         if (err != DOM_NO_ERR)
  549.                 return err;
  550.  
  551.         err = _dom_html_collection_create(doc, (dom_node_internal *) root,
  552.                         __dom_html_document_node_is_form, NULL, &result);
  553.         if (err != DOM_NO_ERR) {
  554.                 dom_node_unref(root);
  555.                 return err;
  556.         }
  557.  
  558.         dom_node_unref(root);
  559.  
  560.         *col = result;
  561.  
  562.         return DOM_NO_ERR;
  563. }
  564.  
  565. dom_exception _dom_html_document_get_anchors(dom_html_document *doc,
  566.                 struct dom_html_collection **col)
  567. {
  568.         UNUSED(doc);
  569.         UNUSED(col);
  570.  
  571.         return DOM_NOT_SUPPORTED_ERR;
  572. }
  573.  
  574. dom_exception _dom_html_document_get_cookie(dom_html_document *doc,
  575.                 dom_string **cookie)
  576. {
  577.         UNUSED(doc);
  578.         UNUSED(cookie);
  579.  
  580.         return DOM_NOT_SUPPORTED_ERR;
  581. }
  582.  
  583. dom_exception _dom_html_document_set_cookie(dom_html_document *doc,
  584.                 dom_string *cookie)
  585. {
  586.         UNUSED(doc);
  587.         UNUSED(cookie);
  588.  
  589.         return DOM_NOT_SUPPORTED_ERR;
  590. }
  591.  
  592. dom_exception _dom_html_document_open(dom_html_document *doc)
  593. {
  594.         UNUSED(doc);
  595.  
  596.         return DOM_NOT_SUPPORTED_ERR;
  597. }
  598.  
  599. dom_exception _dom_html_document_close(dom_html_document *doc)
  600. {
  601.         UNUSED(doc);
  602.  
  603.         return DOM_NOT_SUPPORTED_ERR;
  604. }
  605.  
  606. dom_exception _dom_html_document_write(dom_html_document *doc,
  607.                 dom_string *text)
  608. {
  609.         UNUSED(doc);
  610.         UNUSED(text);
  611.  
  612.         return DOM_NOT_SUPPORTED_ERR;
  613. }
  614.  
  615. dom_exception _dom_html_document_writeln(dom_html_document *doc,
  616.                 dom_string *text)
  617. {
  618.         UNUSED(doc);
  619.         UNUSED(text);
  620.  
  621.         return DOM_NOT_SUPPORTED_ERR;
  622. }
  623.  
  624. dom_exception _dom_html_document_get_elements_by_name(dom_html_document *doc,
  625.                 dom_string *name, struct dom_nodelist **list)
  626. {
  627.         UNUSED(doc);
  628.         UNUSED(name);
  629.         UNUSED(list);
  630.  
  631.         return DOM_NOT_SUPPORTED_ERR;
  632. }
  633.  
  634.