1/*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2014 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Authors: Christian Stocker <chregu@php.net>                          |
16   |          Rob Richards <rrichards@php.net>                            |
17   +----------------------------------------------------------------------+
18*/
19
20/* $Id$ */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include "php.h"
27#if HAVE_LIBXML && HAVE_DOM
28#include "php_dom.h"
29#include <libxml/SAX.h>
30#ifdef LIBXML_SCHEMAS_ENABLED
31#include <libxml/relaxng.h>
32#include <libxml/xmlschemas.h>
33#endif
34
35typedef struct _idsIterator idsIterator;
36struct _idsIterator {
37    xmlChar *elementId;
38    xmlNode *element;
39};
40
41#define DOM_LOAD_STRING 0
42#define DOM_LOAD_FILE 1
43
44/* {{{ arginfo */
45ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_element, 0, 0, 1)
46    ZEND_ARG_INFO(0, tagName)
47    ZEND_ARG_INFO(0, value)
48ZEND_END_ARG_INFO();
49
50ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_document_fragment, 0, 0, 0)
51ZEND_END_ARG_INFO();
52
53ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_text_node, 0, 0, 1)
54    ZEND_ARG_INFO(0, data)
55ZEND_END_ARG_INFO();
56
57ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_comment, 0, 0, 1)
58    ZEND_ARG_INFO(0, data)
59ZEND_END_ARG_INFO();
60
61ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_cdatasection, 0, 0, 1)
62    ZEND_ARG_INFO(0, data)
63ZEND_END_ARG_INFO();
64
65ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_processing_instruction, 0, 0, 2)
66    ZEND_ARG_INFO(0, target)
67    ZEND_ARG_INFO(0, data)
68ZEND_END_ARG_INFO();
69
70ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_attribute, 0, 0, 1)
71    ZEND_ARG_INFO(0, name)
72ZEND_END_ARG_INFO();
73
74ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_entity_reference, 0, 0, 1)
75    ZEND_ARG_INFO(0, name)
76ZEND_END_ARG_INFO();
77
78ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_get_elements_by_tag_name, 0, 0, 1)
79    ZEND_ARG_INFO(0, tagName)
80ZEND_END_ARG_INFO();
81
82ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_import_node, 0, 0, 2)
83    ZEND_ARG_OBJ_INFO(0, importedNode, DOMNode, 0)
84    ZEND_ARG_INFO(0, deep)
85ZEND_END_ARG_INFO();
86
87ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_element_ns, 0, 0, 2)
88    ZEND_ARG_INFO(0, namespaceURI)
89    ZEND_ARG_INFO(0, qualifiedName)
90    ZEND_ARG_INFO(0, value)
91ZEND_END_ARG_INFO();
92
93ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_attribute_ns, 0, 0, 2)
94    ZEND_ARG_INFO(0, namespaceURI)
95    ZEND_ARG_INFO(0, qualifiedName)
96ZEND_END_ARG_INFO();
97
98ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_get_elements_by_tag_name_ns, 0, 0, 2)
99    ZEND_ARG_INFO(0, namespaceURI)
100    ZEND_ARG_INFO(0, localName)
101ZEND_END_ARG_INFO();
102
103ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_get_element_by_id, 0, 0, 1)
104    ZEND_ARG_INFO(0, elementId)
105ZEND_END_ARG_INFO();
106
107ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_adopt_node, 0, 0, 1)
108    ZEND_ARG_OBJ_INFO(0, source, DOMNode, 0)
109ZEND_END_ARG_INFO();
110
111ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_normalize_document, 0, 0, 0)
112ZEND_END_ARG_INFO();
113
114ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_rename_node, 0, 0, 3)
115    ZEND_ARG_OBJ_INFO(0, node, DOMNode, 0)
116    ZEND_ARG_INFO(0, namespaceURI)
117    ZEND_ARG_INFO(0, qualifiedName)
118ZEND_END_ARG_INFO();
119
120ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_load, 0, 0, 1)
121    ZEND_ARG_INFO(0, source)
122    ZEND_ARG_INFO(0, options)
123ZEND_END_ARG_INFO();
124
125ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_save, 0, 0, 1)
126    ZEND_ARG_INFO(0, file)
127ZEND_END_ARG_INFO();
128
129ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_loadxml, 0, 0, 1)
130    ZEND_ARG_INFO(0, source)
131    ZEND_ARG_INFO(0, options)
132ZEND_END_ARG_INFO();
133
134ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_savexml, 0, 0, 0)
135    ZEND_ARG_OBJ_INFO(0, node, DOMNode, 1)
136ZEND_END_ARG_INFO();
137
138ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_construct, 0, 0, 0)
139    ZEND_ARG_INFO(0, version)
140    ZEND_ARG_INFO(0, encoding)
141ZEND_END_ARG_INFO();
142
143ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_validate, 0, 0, 0)
144ZEND_END_ARG_INFO();
145
146ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_xinclude, 0, 0, 0)
147    ZEND_ARG_INFO(0, options)
148ZEND_END_ARG_INFO();
149
150ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_loadhtml, 0, 0, 1)
151    ZEND_ARG_INFO(0, source)
152    ZEND_ARG_INFO(0, options)
153ZEND_END_ARG_INFO();
154
155ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_loadhtmlfile, 0, 0, 1)
156    ZEND_ARG_INFO(0, source)
157    ZEND_ARG_INFO(0, options)
158ZEND_END_ARG_INFO();
159
160ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_savehtml, 0, 0, 0)
161ZEND_END_ARG_INFO();
162
163ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_savehtmlfile, 0, 0, 1)
164    ZEND_ARG_INFO(0, file)
165ZEND_END_ARG_INFO();
166
167ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_schema_validate_file, 0, 0, 1)
168    ZEND_ARG_INFO(0, filename)
169ZEND_END_ARG_INFO();
170
171ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_schema_validate_xml, 0, 0, 1)
172    ZEND_ARG_INFO(0, source)
173ZEND_END_ARG_INFO();
174
175ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_relaxNG_validate_file, 0, 0, 1)
176    ZEND_ARG_INFO(0, filename)
177ZEND_END_ARG_INFO();
178
179ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_relaxNG_validate_xml, 0, 0, 1)
180    ZEND_ARG_INFO(0, source)
181ZEND_END_ARG_INFO();
182
183ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_registernodeclass, 0, 0, 2)
184    ZEND_ARG_INFO(0, baseClass)
185    ZEND_ARG_INFO(0, extendedClass)
186ZEND_END_ARG_INFO();
187/* }}} */
188
189/*
190* class DOMDocument extends DOMNode
191*
192* URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-i-Document
193* Since:
194*/
195
196const zend_function_entry php_dom_document_class_functions[] = { /* {{{ */
197    PHP_FALIAS(createElement, dom_document_create_element, arginfo_dom_document_create_element)
198    PHP_FALIAS(createDocumentFragment, dom_document_create_document_fragment, arginfo_dom_document_create_document_fragment)
199    PHP_FALIAS(createTextNode, dom_document_create_text_node, arginfo_dom_document_create_text_node)
200    PHP_FALIAS(createComment, dom_document_create_comment, arginfo_dom_document_create_comment)
201    PHP_FALIAS(createCDATASection, dom_document_create_cdatasection, arginfo_dom_document_create_cdatasection)
202    PHP_FALIAS(createProcessingInstruction, dom_document_create_processing_instruction, arginfo_dom_document_create_processing_instruction)
203    PHP_FALIAS(createAttribute, dom_document_create_attribute, arginfo_dom_document_create_attribute)
204    PHP_FALIAS(createEntityReference, dom_document_create_entity_reference, arginfo_dom_document_create_entity_reference)
205    PHP_FALIAS(getElementsByTagName, dom_document_get_elements_by_tag_name, arginfo_dom_document_get_elements_by_tag_name)
206    PHP_FALIAS(importNode, dom_document_import_node, arginfo_dom_document_import_node)
207    PHP_FALIAS(createElementNS, dom_document_create_element_ns, arginfo_dom_document_create_element_ns)
208    PHP_FALIAS(createAttributeNS, dom_document_create_attribute_ns, arginfo_dom_document_create_attribute_ns)
209    PHP_FALIAS(getElementsByTagNameNS, dom_document_get_elements_by_tag_name_ns, arginfo_dom_document_get_elements_by_tag_name_ns)
210    PHP_FALIAS(getElementById, dom_document_get_element_by_id, arginfo_dom_document_get_element_by_id)
211    PHP_FALIAS(adoptNode, dom_document_adopt_node, arginfo_dom_document_adopt_node)
212    PHP_FALIAS(normalizeDocument, dom_document_normalize_document, arginfo_dom_document_normalize_document)
213    PHP_FALIAS(renameNode, dom_document_rename_node, arginfo_dom_document_rename_node)
214    PHP_ME(domdocument, load, arginfo_dom_document_load, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
215    PHP_FALIAS(save, dom_document_save, arginfo_dom_document_save)
216    PHP_ME(domdocument, loadXML, arginfo_dom_document_loadxml, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
217    PHP_FALIAS(saveXML, dom_document_savexml, arginfo_dom_document_savexml)
218    PHP_ME(domdocument, __construct, arginfo_dom_document_construct, ZEND_ACC_PUBLIC)
219    PHP_FALIAS(validate, dom_document_validate, arginfo_dom_document_validate)
220    PHP_FALIAS(xinclude, dom_document_xinclude, arginfo_dom_document_xinclude)
221#if defined(LIBXML_HTML_ENABLED)
222    PHP_ME(domdocument, loadHTML, arginfo_dom_document_loadhtml, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
223    PHP_ME(domdocument, loadHTMLFile, arginfo_dom_document_loadhtmlfile, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
224    PHP_FALIAS(saveHTML, dom_document_save_html, arginfo_dom_document_savehtml)
225    PHP_FALIAS(saveHTMLFile, dom_document_save_html_file, arginfo_dom_document_savehtmlfile)
226#endif  /* defined(LIBXML_HTML_ENABLED) */
227#if defined(LIBXML_SCHEMAS_ENABLED)
228    PHP_FALIAS(schemaValidate, dom_document_schema_validate_file, arginfo_dom_document_schema_validate_file)
229    PHP_FALIAS(schemaValidateSource, dom_document_schema_validate_xml, arginfo_dom_document_schema_validate_xml)
230    PHP_FALIAS(relaxNGValidate, dom_document_relaxNG_validate_file, arginfo_dom_document_relaxNG_validate_file)
231    PHP_FALIAS(relaxNGValidateSource, dom_document_relaxNG_validate_xml, arginfo_dom_document_relaxNG_validate_xml)
232#endif
233    PHP_ME(domdocument, registerNodeClass, arginfo_dom_document_registernodeclass, ZEND_ACC_PUBLIC)
234    PHP_FE_END
235};
236/* }}} */
237
238/* {{{ docType  DOMDocumentType
239readonly=yes
240URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-B63ED1A31
241Since:
242*/
243int dom_document_doctype_read(dom_object *obj, zval **retval TSRMLS_DC)
244{
245    xmlDoc *docp;
246    xmlDtdPtr dtdptr;
247    int ret;
248
249    docp = (xmlDocPtr) dom_object_get_node(obj);
250
251    if (docp == NULL) {
252        php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
253        return FAILURE;
254    }
255
256    ALLOC_ZVAL(*retval);
257
258    dtdptr = xmlGetIntSubset(docp);
259    if (!dtdptr) {
260        ZVAL_NULL(*retval);
261        return SUCCESS;
262    }
263
264    if (NULL == (*retval = php_dom_create_object((xmlNodePtr) dtdptr, &ret, *retval, obj TSRMLS_CC))) {
265        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
266        return FAILURE;
267    }
268    return SUCCESS;
269
270}
271
272/* }}} */
273
274/* {{{ implementation   DOMImplementation
275readonly=yes
276URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1B793EBA
277Since:
278*/
279int dom_document_implementation_read(dom_object *obj, zval **retval TSRMLS_DC)
280{
281    ALLOC_ZVAL(*retval);
282    php_dom_create_implementation(retval TSRMLS_CC);
283    return SUCCESS;
284}
285
286/* }}} */
287
288/* {{{ documentElement  DOMElement
289readonly=yes
290URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-87CD092
291Since:
292*/
293int dom_document_document_element_read(dom_object *obj, zval **retval TSRMLS_DC)
294{
295    xmlDoc *docp;
296    xmlNode *root;
297    int ret;
298
299    docp = (xmlDocPtr) dom_object_get_node(obj);
300
301    if (docp == NULL) {
302        php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
303        return FAILURE;
304    }
305
306    ALLOC_ZVAL(*retval);
307
308    root = xmlDocGetRootElement(docp);
309    if (!root) {
310        ZVAL_NULL(*retval);
311        return SUCCESS;
312    }
313
314    if (NULL == (*retval = php_dom_create_object(root, &ret, *retval, obj TSRMLS_CC))) {
315        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
316        return FAILURE;
317    }
318    return SUCCESS;
319}
320
321/* }}} */
322
323/* {{{ encoding string
324URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-encoding
325Since: DOM Level 3
326*/
327int dom_document_encoding_read(dom_object *obj, zval **retval TSRMLS_DC)
328{
329    xmlDoc *docp;
330    char *encoding;
331
332    docp = (xmlDocPtr) dom_object_get_node(obj);
333
334    if (docp == NULL) {
335        php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
336        return FAILURE;
337    }
338
339    encoding = (char *) docp->encoding;
340    ALLOC_ZVAL(*retval);
341
342    if (encoding != NULL) {
343        ZVAL_STRING(*retval, encoding, 1);
344    } else {
345        ZVAL_NULL(*retval);
346    }
347
348    return SUCCESS;
349}
350
351int dom_document_encoding_write(dom_object *obj, zval *newval TSRMLS_DC)
352{
353    zval value_copy;
354    xmlDoc *docp;
355    xmlCharEncodingHandlerPtr handler;
356
357    docp = (xmlDocPtr) dom_object_get_node(obj);
358
359    if (docp == NULL) {
360        php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
361        return FAILURE;
362    }
363
364    convert_to_string_copy(newval, value_copy);
365
366    handler = xmlFindCharEncodingHandler(Z_STRVAL_P(newval));
367
368    if (handler != NULL) {
369        xmlCharEncCloseFunc(handler);
370        if (docp->encoding != NULL) {
371            xmlFree((xmlChar *)docp->encoding);
372        }
373        docp->encoding = xmlStrdup((const xmlChar *) Z_STRVAL_P(newval));
374    } else {
375        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Document Encoding");
376    }
377
378    if (newval == &value_copy) {
379        zval_dtor(newval);
380    }
381
382    return SUCCESS;
383}
384
385/* }}} */
386
387/* {{{ standalone   boolean
388readonly=no
389URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-standalone
390Since: DOM Level 3
391*/
392int dom_document_standalone_read(dom_object *obj, zval **retval TSRMLS_DC)
393{
394    xmlDoc *docp;
395    int standalone;
396
397    docp = (xmlDocPtr) dom_object_get_node(obj);
398
399    if (docp == NULL) {
400        php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
401        return FAILURE;
402    }
403
404    ALLOC_ZVAL(*retval);
405    standalone = docp->standalone;
406    ZVAL_BOOL(*retval, standalone);
407
408    return SUCCESS;
409}
410
411int dom_document_standalone_write(dom_object *obj, zval *newval TSRMLS_DC)
412{
413    zval value_copy;
414    xmlDoc *docp;
415    int standalone;
416
417    docp = (xmlDocPtr) dom_object_get_node(obj);
418
419    if (docp == NULL) {
420        php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
421        return FAILURE;
422    }
423
424    convert_to_long_copy(newval, value_copy);
425
426    standalone = Z_LVAL_P(newval);
427    if (standalone > 0) {
428        docp->standalone = 1;
429    }
430    else if (standalone < 0) {
431        docp->standalone = -1;
432    }
433    else {
434        docp->standalone = 0;
435    }
436
437    if (newval == &value_copy) {
438        zval_dtor(newval);
439    }
440
441    return SUCCESS;
442}
443
444/* }}} */
445
446/* {{{ version  string
447readonly=no
448URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-version
449Since: DOM Level 3
450*/
451int dom_document_version_read(dom_object *obj, zval **retval TSRMLS_DC)
452{
453    xmlDoc *docp;
454    char *version;
455
456    docp = (xmlDocPtr) dom_object_get_node(obj);
457
458    if (docp == NULL) {
459        php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
460        return FAILURE;
461    }
462
463    version = (char *) docp->version;
464    ALLOC_ZVAL(*retval);
465
466    if (version != NULL) {
467        ZVAL_STRING(*retval, version, 1);
468    } else {
469        ZVAL_NULL(*retval);
470    }
471
472    return SUCCESS;
473}
474
475int dom_document_version_write(dom_object *obj, zval *newval TSRMLS_DC)
476{
477    zval value_copy;
478    xmlDoc *docp;
479
480    docp = (xmlDocPtr) dom_object_get_node(obj);
481
482    if (docp == NULL) {
483        php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
484        return FAILURE;
485    }
486
487    if (docp->version != NULL) {
488        xmlFree((xmlChar *) docp->version );
489    }
490
491    convert_to_string_copy(newval, value_copy);
492
493    docp->version = xmlStrdup((const xmlChar *) Z_STRVAL_P(newval));
494
495    if (newval == &value_copy) {
496        zval_dtor(newval);
497    }
498
499    return SUCCESS;
500}
501
502/* }}} */
503
504/* {{{ strictErrorChecking  boolean
505readonly=no
506URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-strictErrorChecking
507Since: DOM Level 3
508*/
509int dom_document_strict_error_checking_read(dom_object *obj, zval **retval TSRMLS_DC)
510{
511    dom_doc_propsptr doc_prop;
512
513    ALLOC_ZVAL(*retval);
514    if (obj->document) {
515        doc_prop = dom_get_doc_props(obj->document);
516        ZVAL_BOOL(*retval, doc_prop->stricterror);
517    } else {
518        ZVAL_FALSE(*retval);
519    }
520    return SUCCESS;
521}
522
523int dom_document_strict_error_checking_write(dom_object *obj, zval *newval TSRMLS_DC)
524{
525    zval value_copy;
526    dom_doc_propsptr doc_prop;
527
528    convert_to_boolean_copy(newval, value_copy);
529
530    if (obj->document) {
531        doc_prop = dom_get_doc_props(obj->document);
532        doc_prop->stricterror = Z_LVAL_P(newval);
533    }
534
535    if (newval == &value_copy) {
536        zval_dtor(newval);
537    }
538
539    return SUCCESS;
540}
541
542/* }}} */
543
544/* {{{ formatOutput boolean
545readonly=no
546*/
547int dom_document_format_output_read(dom_object *obj, zval **retval TSRMLS_DC)
548{
549    dom_doc_propsptr doc_prop;
550
551    ALLOC_ZVAL(*retval);
552    if (obj->document) {
553        doc_prop = dom_get_doc_props(obj->document);
554        ZVAL_BOOL(*retval, doc_prop->formatoutput);
555    } else {
556        ZVAL_FALSE(*retval);
557    }
558    return SUCCESS;
559}
560
561int dom_document_format_output_write(dom_object *obj, zval *newval TSRMLS_DC)
562{
563    zval value_copy;
564    dom_doc_propsptr doc_prop;
565
566    convert_to_boolean_copy(newval, value_copy);
567
568    if (obj->document) {
569        doc_prop = dom_get_doc_props(obj->document);
570        doc_prop->formatoutput = Z_LVAL_P(newval);
571    }
572
573    if (newval == &value_copy) {
574        zval_dtor(newval);
575    }
576
577    return SUCCESS;
578}
579/* }}} */
580
581/* {{{ validateOnParse  boolean
582readonly=no
583*/
584int dom_document_validate_on_parse_read(dom_object *obj, zval **retval TSRMLS_DC)
585{
586    dom_doc_propsptr doc_prop;
587
588    ALLOC_ZVAL(*retval);
589    if (obj->document) {
590        doc_prop = dom_get_doc_props(obj->document);
591        ZVAL_BOOL(*retval, doc_prop->validateonparse);
592    } else {
593        ZVAL_FALSE(*retval);
594    }
595    return SUCCESS;
596}
597
598int dom_document_validate_on_parse_write(dom_object *obj, zval *newval TSRMLS_DC)
599{
600    zval value_copy;
601    dom_doc_propsptr doc_prop;
602
603    convert_to_boolean_copy(newval, value_copy);
604
605    if (obj->document) {
606        doc_prop = dom_get_doc_props(obj->document);
607        doc_prop->validateonparse = Z_LVAL_P(newval);
608    }
609
610    if (newval == &value_copy) {
611        zval_dtor(newval);
612    }
613
614    return SUCCESS;
615}
616/* }}} */
617
618/* {{{ resolveExternals boolean
619readonly=no
620*/
621int dom_document_resolve_externals_read(dom_object *obj, zval **retval TSRMLS_DC)
622{
623    dom_doc_propsptr doc_prop;
624
625    ALLOC_ZVAL(*retval);
626    if (obj->document) {
627        doc_prop = dom_get_doc_props(obj->document);
628        ZVAL_BOOL(*retval, doc_prop->resolveexternals);
629    } else {
630        ZVAL_FALSE(*retval);
631    }
632    return SUCCESS;
633}
634
635int dom_document_resolve_externals_write(dom_object *obj, zval *newval TSRMLS_DC)
636{
637    zval value_copy;
638    dom_doc_propsptr doc_prop;
639
640    convert_to_boolean_copy(newval, value_copy);
641
642    if (obj->document) {
643        doc_prop = dom_get_doc_props(obj->document);
644        doc_prop->resolveexternals = Z_LVAL_P(newval);
645    }
646
647    if (newval == &value_copy) {
648        zval_dtor(newval);
649    }
650
651    return SUCCESS;
652}
653/* }}} */
654
655/* {{{ preserveWhiteSpace   boolean
656readonly=no
657*/
658int dom_document_preserve_whitespace_read(dom_object *obj, zval **retval TSRMLS_DC)
659{
660    dom_doc_propsptr doc_prop;
661
662    ALLOC_ZVAL(*retval);
663    if (obj->document) {
664        doc_prop = dom_get_doc_props(obj->document);
665        ZVAL_BOOL(*retval, doc_prop->preservewhitespace);
666    } else {
667        ZVAL_FALSE(*retval);
668    }
669    return SUCCESS;
670}
671
672int dom_document_preserve_whitespace_write(dom_object *obj, zval *newval TSRMLS_DC)
673{
674    zval value_copy;
675    dom_doc_propsptr doc_prop;
676
677    convert_to_boolean_copy(newval, value_copy);
678
679    if (obj->document) {
680        doc_prop = dom_get_doc_props(obj->document);
681        doc_prop->preservewhitespace = Z_LVAL_P(newval);
682    }
683
684    if (newval == &value_copy) {
685        zval_dtor(newval);
686    }
687
688    return SUCCESS;
689}
690/* }}} */
691
692/* {{{ recover  boolean
693readonly=no
694*/
695int dom_document_recover_read(dom_object *obj, zval **retval TSRMLS_DC)
696{
697    dom_doc_propsptr doc_prop;
698
699    ALLOC_ZVAL(*retval);
700    if (obj->document) {
701        doc_prop = dom_get_doc_props(obj->document);
702        ZVAL_BOOL(*retval, doc_prop->recover);
703    } else {
704        ZVAL_FALSE(*retval);
705    }
706    return SUCCESS;
707}
708
709int dom_document_recover_write(dom_object *obj, zval *newval TSRMLS_DC)
710{
711    zval value_copy;
712    dom_doc_propsptr doc_prop;
713
714    convert_to_boolean_copy(newval, value_copy);
715
716    if (obj->document) {
717        doc_prop = dom_get_doc_props(obj->document);
718        doc_prop->recover = Z_LVAL_P(newval);
719    }
720
721    if (newval == &value_copy) {
722        zval_dtor(newval);
723    }
724
725    return SUCCESS;
726}
727/* }}} */
728
729/* {{{ substituteEntities   boolean
730readonly=no
731*/
732int dom_document_substitue_entities_read(dom_object *obj, zval **retval TSRMLS_DC)
733{
734    dom_doc_propsptr doc_prop;
735
736    ALLOC_ZVAL(*retval);
737    if (obj->document) {
738        doc_prop = dom_get_doc_props(obj->document);
739        ZVAL_BOOL(*retval, doc_prop->substituteentities);
740    } else {
741        ZVAL_FALSE(*retval);
742    }
743    return SUCCESS;
744}
745
746int dom_document_substitue_entities_write(dom_object *obj, zval *newval TSRMLS_DC)
747{
748    zval value_copy;
749    dom_doc_propsptr doc_prop;
750
751    convert_to_boolean_copy(newval, value_copy);
752
753    if (obj->document) {
754        doc_prop = dom_get_doc_props(obj->document);
755        doc_prop->substituteentities = Z_LVAL_P(newval);
756    }
757
758    if (newval == &value_copy) {
759        zval_dtor(newval);
760    }
761
762    return SUCCESS;
763}
764/* }}} */
765
766/* {{{ documentURI  string
767readonly=no
768URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-documentURI
769Since: DOM Level 3
770*/
771int dom_document_document_uri_read(dom_object *obj, zval **retval TSRMLS_DC)
772{
773    xmlDoc *docp;
774    char *url;
775
776    docp = (xmlDocPtr) dom_object_get_node(obj);
777
778    if (docp == NULL) {
779        php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
780        return FAILURE;
781    }
782
783    ALLOC_ZVAL(*retval);
784    url = (char *) docp->URL;
785    if (url != NULL) {
786        ZVAL_STRING(*retval, url, 1);
787    } else {
788        ZVAL_NULL(*retval);
789    }
790
791    return SUCCESS;
792}
793
794int dom_document_document_uri_write(dom_object *obj, zval *newval TSRMLS_DC)
795{
796    zval value_copy;
797    xmlDoc *docp;
798
799    docp = (xmlDocPtr) dom_object_get_node(obj);
800
801    if (docp == NULL) {
802        php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
803        return FAILURE;
804    }
805
806    if (docp->URL != NULL) {
807        xmlFree((xmlChar *) docp->URL);
808    }
809
810    convert_to_string_copy(newval, value_copy);
811
812    docp->URL = xmlStrdup((const xmlChar *) Z_STRVAL_P(newval));
813
814    if (newval == &value_copy) {
815        zval_dtor(newval);
816    }
817
818    return SUCCESS;
819}
820
821/* }}} */
822
823/* {{{ config   DOMConfiguration
824readonly=yes
825URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-config
826Since: DOM Level 3
827*/
828int dom_document_config_read(dom_object *obj, zval **retval TSRMLS_DC)
829{
830    ALLOC_ZVAL(*retval);
831    ZVAL_NULL(*retval);
832    return SUCCESS;
833}
834
835/* }}} */
836
837/* {{{ proto DOMElement dom_document_create_element(string tagName [, string value]);
838URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-2141741547
839Since:
840*/
841PHP_FUNCTION(dom_document_create_element)
842{
843    zval *id;
844    xmlNode *node;
845    xmlDocPtr docp;
846    dom_object *intern;
847    int ret, name_len, value_len;
848    char *name, *value = NULL;
849
850    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|s", &id, dom_document_class_entry, &name, &name_len, &value, &value_len) == FAILURE) {
851        return;
852    }
853
854    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
855
856    if (xmlValidateName((xmlChar *) name, 0) != 0) {
857        php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
858        RETURN_FALSE;
859    }
860
861    node = xmlNewDocNode(docp, NULL, name, value);
862    if (!node) {
863        RETURN_FALSE;
864    }
865
866    DOM_RET_OBJ(node, &ret, intern);
867}
868/* }}} end dom_document_create_element */
869
870/* {{{ proto DOMDocumentFragment dom_document_create_document_fragment();
871URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-35CB04B5
872Since:
873*/
874PHP_FUNCTION(dom_document_create_document_fragment)
875{
876    zval *id;
877    xmlNode *node;
878    xmlDocPtr docp;
879    dom_object *intern;
880    int ret;
881
882    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &id, dom_document_class_entry) == FAILURE) {
883        return;
884    }
885
886    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
887
888    node =  xmlNewDocFragment(docp);
889    if (!node) {
890        RETURN_FALSE;
891    }
892
893    DOM_RET_OBJ(node, &ret, intern);
894}
895/* }}} end dom_document_create_document_fragment */
896
897/* {{{ proto DOMText dom_document_create_text_node(string data);
898URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1975348127
899Since:
900*/
901PHP_FUNCTION(dom_document_create_text_node)
902{
903    zval *id;
904    xmlNode *node;
905    xmlDocPtr docp;
906    int ret, value_len;
907    dom_object *intern;
908    char *value;
909
910    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &value, &value_len) == FAILURE) {
911        return;
912    }
913
914    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
915
916    node = xmlNewDocText(docp, (xmlChar *) value);
917    if (!node) {
918        RETURN_FALSE;
919    }
920
921    DOM_RET_OBJ(node, &ret, intern);
922}
923/* }}} end dom_document_create_text_node */
924
925/* {{{ proto DOMComment dom_document_create_comment(string data);
926URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1334481328
927Since:
928*/
929PHP_FUNCTION(dom_document_create_comment)
930{
931    zval *id;
932    xmlNode *node;
933    xmlDocPtr docp;
934    int ret, value_len;
935    dom_object *intern;
936    char *value;
937
938    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &value, &value_len) == FAILURE) {
939        return;
940    }
941
942    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
943
944    node = xmlNewDocComment(docp, (xmlChar *) value);
945    if (!node) {
946        RETURN_FALSE;
947    }
948
949    DOM_RET_OBJ(node, &ret, intern);
950}
951/* }}} end dom_document_create_comment */
952
953/* {{{ proto DOMCdataSection dom_document_create_cdatasection(string data);
954URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D26C0AF8
955Since:
956*/
957PHP_FUNCTION(dom_document_create_cdatasection)
958{
959    zval *id;
960    xmlNode *node;
961    xmlDocPtr docp;
962    int ret, value_len;
963    dom_object *intern;
964    char *value;
965
966    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &value, &value_len) == FAILURE) {
967        return;
968    }
969
970    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
971
972    node = xmlNewCDataBlock(docp, (xmlChar *) value, value_len);
973    if (!node) {
974        RETURN_FALSE;
975    }
976
977    DOM_RET_OBJ(node, &ret, intern);
978}
979/* }}} end dom_document_create_cdatasection */
980
981/* {{{ proto DOMProcessingInstruction dom_document_create_processing_instruction(string target, string data);
982URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-135944439
983Since:
984*/
985PHP_FUNCTION(dom_document_create_processing_instruction)
986{
987    zval *id;
988    xmlNode *node;
989    xmlDocPtr docp;
990    int ret, value_len, name_len = 0;
991    dom_object *intern;
992    char *name, *value = NULL;
993
994    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|s", &id, dom_document_class_entry, &name, &name_len, &value, &value_len) == FAILURE) {
995        return;
996    }
997
998    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
999
1000    if (xmlValidateName((xmlChar *) name, 0) != 0) {
1001        php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
1002        RETURN_FALSE;
1003    }
1004
1005    node = xmlNewPI((xmlChar *) name, (xmlChar *) value);
1006    if (!node) {
1007        RETURN_FALSE;
1008    }
1009
1010    node->doc = docp;
1011
1012    DOM_RET_OBJ(node, &ret, intern);
1013}
1014/* }}} end dom_document_create_processing_instruction */
1015
1016/* {{{ proto DOMAttr dom_document_create_attribute(string name);
1017URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1084891198
1018Since:
1019*/
1020PHP_FUNCTION(dom_document_create_attribute)
1021{
1022    zval *id;
1023    xmlAttrPtr node;
1024    xmlDocPtr docp;
1025    int ret, name_len;
1026    dom_object *intern;
1027    char *name;
1028
1029    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &name, &name_len) == FAILURE) {
1030        return;
1031    }
1032
1033    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1034
1035    if (xmlValidateName((xmlChar *) name, 0) != 0) {
1036        php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
1037        RETURN_FALSE;
1038    }
1039
1040    node = xmlNewDocProp(docp, (xmlChar *) name, NULL);
1041    if (!node) {
1042        RETURN_FALSE;
1043    }
1044
1045    DOM_RET_OBJ((xmlNodePtr) node, &ret, intern);
1046
1047}
1048/* }}} end dom_document_create_attribute */
1049
1050/* {{{ proto DOMEntityReference dom_document_create_entity_reference(string name);
1051URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-392B75AE
1052Since:
1053*/
1054PHP_FUNCTION(dom_document_create_entity_reference)
1055{
1056    zval *id;
1057    xmlNode *node;
1058    xmlDocPtr docp = NULL;
1059    dom_object *intern;
1060    int ret, name_len;
1061    char *name;
1062
1063    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &name, &name_len) == FAILURE) {
1064        return;
1065    }
1066
1067    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1068
1069    if (xmlValidateName((xmlChar *) name, 0) != 0) {
1070        php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
1071        RETURN_FALSE;
1072    }
1073
1074    node = xmlNewReference(docp, name);
1075    if (!node) {
1076        RETURN_FALSE;
1077    }
1078
1079    DOM_RET_OBJ((xmlNodePtr) node, &ret, intern);
1080}
1081/* }}} end dom_document_create_entity_reference */
1082
1083/* {{{ proto DOMNodeList dom_document_get_elements_by_tag_name(string tagname);
1084URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-A6C9094
1085Since:
1086*/
1087PHP_FUNCTION(dom_document_get_elements_by_tag_name)
1088{
1089    zval *id;
1090    xmlDocPtr docp;
1091    int name_len;
1092    dom_object *intern, *namednode;
1093    char *name;
1094    xmlChar *local;
1095
1096    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &name, &name_len) == FAILURE) {
1097        return;
1098    }
1099
1100    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1101
1102    php_dom_create_interator(return_value, DOM_NODELIST TSRMLS_CC);
1103    namednode = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC);
1104    local = xmlCharStrndup(name, name_len);
1105    dom_namednode_iter(intern, 0, namednode, NULL, local, NULL TSRMLS_CC);
1106}
1107/* }}} end dom_document_get_elements_by_tag_name */
1108
1109/* {{{ proto DOMNode dom_document_import_node(DOMNode importedNode, boolean deep);
1110URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Core-Document-importNode
1111Since: DOM Level 2
1112*/
1113PHP_FUNCTION(dom_document_import_node)
1114{
1115    zval *id, *node;
1116    xmlDocPtr docp;
1117    xmlNodePtr nodep, retnodep;
1118    dom_object *intern, *nodeobj;
1119    int ret;
1120    long recursive = 0;
1121
1122    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO|l", &id, dom_document_class_entry, &node, dom_node_class_entry, &recursive) == FAILURE) {
1123        return;
1124    }
1125
1126    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1127
1128    DOM_GET_OBJ(nodep, node, xmlNodePtr, nodeobj);
1129
1130    if (nodep->type == XML_HTML_DOCUMENT_NODE || nodep->type == XML_DOCUMENT_NODE
1131        || nodep->type == XML_DOCUMENT_TYPE_NODE) {
1132        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot import: Node Type Not Supported");
1133        RETURN_FALSE;
1134    }
1135
1136    if (nodep->doc == docp) {
1137        retnodep = nodep;
1138    } else {
1139        if ((recursive == 0) && (nodep->type == XML_ELEMENT_NODE)) {
1140            recursive = 2;
1141        }
1142        retnodep = xmlDocCopyNode(nodep, docp, recursive);
1143        if (!retnodep) {
1144            RETURN_FALSE;
1145        }
1146
1147        if ((retnodep->type == XML_ATTRIBUTE_NODE) && (nodep->ns != NULL)) {
1148            xmlNsPtr nsptr = NULL;
1149            xmlNodePtr root = xmlDocGetRootElement(docp);
1150
1151            nsptr = xmlSearchNsByHref (nodep->doc, root, nodep->ns->href);
1152            if (nsptr == NULL) {
1153                int errorcode;
1154                nsptr = dom_get_ns(root, (char *) nodep->ns->href, &errorcode, (char *) nodep->ns->prefix);
1155            }
1156            xmlSetNs(retnodep, nsptr);
1157        }
1158    }
1159
1160    DOM_RET_OBJ((xmlNodePtr) retnodep, &ret, intern);
1161}
1162/* }}} end dom_document_import_node */
1163
1164/* {{{ proto DOMElement dom_document_create_element_ns(string namespaceURI, string qualifiedName [,string value]);
1165URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-DocCrElNS
1166Since: DOM Level 2
1167*/
1168PHP_FUNCTION(dom_document_create_element_ns)
1169{
1170    zval *id;
1171    xmlDocPtr docp;
1172    xmlNodePtr nodep = NULL;
1173    xmlNsPtr nsptr = NULL;
1174    int ret, uri_len = 0, name_len = 0, value_len = 0;
1175    char *uri, *name, *value = NULL;
1176    char *localname = NULL, *prefix = NULL;
1177    int errorcode;
1178    dom_object *intern;
1179
1180    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os!s|s", &id, dom_document_class_entry, &uri, &uri_len, &name, &name_len, &value, &value_len) == FAILURE) {
1181        return;
1182    }
1183
1184    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1185
1186    errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len);
1187
1188    if (errorcode == 0) {
1189        if (xmlValidateName((xmlChar *) localname, 0) == 0) {
1190            nodep = xmlNewDocNode (docp, NULL, localname, value);
1191            if (nodep != NULL && uri != NULL) {
1192                nsptr = xmlSearchNsByHref (nodep->doc, nodep, uri);
1193                if (nsptr == NULL) {
1194                    nsptr = dom_get_ns(nodep, uri, &errorcode, prefix);
1195                }
1196                xmlSetNs(nodep, nsptr);
1197            }
1198        } else {
1199            errorcode = INVALID_CHARACTER_ERR;
1200        }
1201    }
1202
1203    xmlFree(localname);
1204    if (prefix != NULL) {
1205        xmlFree(prefix);
1206    }
1207
1208    if (errorcode != 0) {
1209        if (nodep != NULL) {
1210            xmlFreeNode(nodep);
1211        }
1212        php_dom_throw_error(errorcode, dom_get_strict_error(intern->document) TSRMLS_CC);
1213        RETURN_FALSE;
1214    }
1215
1216    if (nodep == NULL) {
1217        RETURN_FALSE;
1218    }
1219
1220
1221    nodep->ns = nsptr;
1222
1223    DOM_RET_OBJ(nodep, &ret, intern);
1224}
1225/* }}} end dom_document_create_element_ns */
1226
1227/* {{{ proto DOMAttr dom_document_create_attribute_ns(string namespaceURI, string qualifiedName);
1228URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-DocCrAttrNS
1229Since: DOM Level 2
1230*/
1231PHP_FUNCTION(dom_document_create_attribute_ns)
1232{
1233    zval *id;
1234    xmlDocPtr docp;
1235    xmlNodePtr nodep = NULL, root;
1236    xmlNsPtr nsptr;
1237    int ret, uri_len = 0, name_len = 0;
1238    char *uri, *name;
1239    char *localname = NULL, *prefix = NULL;
1240    dom_object *intern;
1241    int errorcode;
1242
1243    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os!s", &id, dom_document_class_entry, &uri, &uri_len, &name, &name_len) == FAILURE) {
1244        return;
1245    }
1246
1247    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1248
1249    root = xmlDocGetRootElement(docp);
1250    if (root != NULL) {
1251        errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len);
1252        if (errorcode == 0) {
1253            if (xmlValidateName((xmlChar *) localname, 0) == 0) {
1254                nodep = (xmlNodePtr) xmlNewDocProp(docp, localname, NULL);
1255                if (nodep != NULL && uri_len > 0) {
1256                    nsptr = xmlSearchNsByHref (nodep->doc, root, uri);
1257                    if (nsptr == NULL) {
1258                        nsptr = dom_get_ns(root, uri, &errorcode, prefix);
1259                    }
1260                    xmlSetNs(nodep, nsptr);
1261                }
1262            } else {
1263                errorcode = INVALID_CHARACTER_ERR;
1264            }
1265        }
1266    } else {
1267        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Document Missing Root Element");
1268        RETURN_FALSE;
1269    }
1270
1271    xmlFree(localname);
1272    if (prefix != NULL) {
1273        xmlFree(prefix);
1274    }
1275
1276    if (errorcode != 0) {
1277        if (nodep != NULL) {
1278            xmlFreeProp((xmlAttrPtr) nodep);
1279        }
1280        php_dom_throw_error(errorcode, dom_get_strict_error(intern->document) TSRMLS_CC);
1281        RETURN_FALSE;
1282    }
1283
1284    if (nodep == NULL) {
1285        RETURN_FALSE;
1286    }
1287
1288    DOM_RET_OBJ(nodep, &ret, intern);
1289}
1290/* }}} end dom_document_create_attribute_ns */
1291
1292/* {{{ proto DOMNodeList dom_document_get_elements_by_tag_name_ns(string namespaceURI, string localName);
1293URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-getElBTNNS
1294Since: DOM Level 2
1295*/
1296PHP_FUNCTION(dom_document_get_elements_by_tag_name_ns)
1297{
1298    zval *id;
1299    xmlDocPtr docp;
1300    int uri_len, name_len;
1301    dom_object *intern, *namednode;
1302    char *uri, *name;
1303    xmlChar *local, *nsuri;
1304
1305    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oss", &id, dom_document_class_entry, &uri, &uri_len, &name, &name_len) == FAILURE) {
1306        return;
1307    }
1308
1309    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1310
1311    php_dom_create_interator(return_value, DOM_NODELIST TSRMLS_CC);
1312    namednode = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC);
1313    local = xmlCharStrndup(name, name_len);
1314    nsuri = xmlCharStrndup(uri, uri_len);
1315    dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri TSRMLS_CC);
1316}
1317/* }}} end dom_document_get_elements_by_tag_name_ns */
1318
1319/* {{{ proto DOMElement dom_document_get_element_by_id(string elementId);
1320URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-getElBId
1321Since: DOM Level 2
1322*/
1323PHP_FUNCTION(dom_document_get_element_by_id)
1324{
1325    zval *id;
1326    xmlDocPtr docp;
1327    xmlAttrPtr  attrp;
1328    int ret, idname_len;
1329    dom_object *intern;
1330    char *idname;
1331
1332    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &idname, &idname_len) == FAILURE) {
1333        return;
1334    }
1335
1336    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1337
1338    attrp = xmlGetID(docp, (xmlChar *) idname);
1339
1340    if (attrp && attrp->parent) {
1341        DOM_RET_OBJ((xmlNodePtr) attrp->parent, &ret, intern);
1342    } else {
1343        RETVAL_NULL();
1344    }
1345
1346}
1347/* }}} end dom_document_get_element_by_id */
1348
1349/* {{{ proto DOMNode dom_document_adopt_node(DOMNode source);
1350URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-adoptNode
1351Since: DOM Level 3
1352*/
1353PHP_FUNCTION(dom_document_adopt_node)
1354{
1355 DOM_NOT_IMPLEMENTED();
1356}
1357/* }}} end dom_document_adopt_node */
1358
1359/* {{{ proto void dom_document_normalize_document();
1360URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-normalizeDocument
1361Since: DOM Level 3
1362*/
1363PHP_FUNCTION(dom_document_normalize_document)
1364{
1365    zval *id;
1366    xmlDocPtr docp;
1367    dom_object *intern;
1368
1369    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &id, dom_document_class_entry) == FAILURE) {
1370        return;
1371    }
1372
1373    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1374
1375    dom_normalize((xmlNodePtr) docp TSRMLS_CC);
1376}
1377/* }}} end dom_document_normalize_document */
1378
1379/* {{{ proto DOMNode dom_document_rename_node(node n, string namespaceURI, string qualifiedName);
1380URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-renameNode
1381Since: DOM Level 3
1382*/
1383PHP_FUNCTION(dom_document_rename_node)
1384{
1385 DOM_NOT_IMPLEMENTED();
1386}
1387/* }}} end dom_document_rename_node */
1388
1389/* {{{ proto void DOMDocument::__construct([string version], [string encoding]); */
1390PHP_METHOD(domdocument, __construct)
1391{
1392
1393    zval *id;
1394    xmlDoc *docp = NULL, *olddoc;
1395    dom_object *intern;
1396    char *encoding, *version = NULL;
1397    int encoding_len = 0, version_len = 0, refcount;
1398    zend_error_handling error_handling;
1399
1400    zend_replace_error_handling(EH_THROW, dom_domexception_class_entry, &error_handling TSRMLS_CC);
1401    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|ss", &id, dom_document_class_entry, &version, &version_len, &encoding, &encoding_len) == FAILURE) {
1402        zend_restore_error_handling(&error_handling TSRMLS_CC);
1403        return;
1404    }
1405
1406    zend_restore_error_handling(&error_handling TSRMLS_CC);
1407    docp = xmlNewDoc(version);
1408
1409    if (!docp) {
1410        php_dom_throw_error(INVALID_STATE_ERR, 1 TSRMLS_CC);
1411        RETURN_FALSE;
1412    }
1413
1414    if (encoding_len > 0) {
1415        docp->encoding = (const xmlChar*)xmlStrdup(encoding);
1416    }
1417
1418    intern = (dom_object *)zend_object_store_get_object(id TSRMLS_CC);
1419    if (intern != NULL) {
1420        olddoc = (xmlDocPtr) dom_object_get_node(intern);
1421        if (olddoc != NULL) {
1422            php_libxml_decrement_node_ptr((php_libxml_node_object *) intern TSRMLS_CC);
1423            refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern TSRMLS_CC);
1424            if (refcount != 0) {
1425                olddoc->_private = NULL;
1426            }
1427        }
1428        intern->document = NULL;
1429        if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, docp TSRMLS_CC) == -1) {
1430            RETURN_FALSE;
1431        }
1432        php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)docp, (void *)intern TSRMLS_CC);
1433    }
1434}
1435/* }}} end DOMDocument::__construct */
1436
1437char *_dom_get_valid_file_path(char *source, char *resolved_path, int resolved_path_len  TSRMLS_DC) /* {{{ */
1438{
1439    xmlURI *uri;
1440    xmlChar *escsource;
1441    char *file_dest;
1442    int isFileUri = 0;
1443
1444    uri = xmlCreateURI();
1445    escsource = xmlURIEscapeStr(source, ":");
1446    xmlParseURIReference(uri, escsource);
1447    xmlFree(escsource);
1448
1449    if (uri->scheme != NULL) {
1450        /* absolute file uris - libxml only supports localhost or empty host */
1451#ifdef PHP_WIN32
1452        if (strncasecmp(source, "file://",7) == 0 && ':' == source[8]) {
1453            isFileUri = 1;
1454            source += 7;
1455        } else
1456#endif
1457        if (strncasecmp(source, "file:///",8) == 0) {
1458            isFileUri = 1;
1459#ifdef PHP_WIN32
1460            source += 8;
1461#else
1462            source += 7;
1463#endif
1464        } else if (strncasecmp(source, "file://localhost/",17) == 0) {
1465            isFileUri = 1;
1466#ifdef PHP_WIN32
1467            source += 17;
1468#else
1469            source += 16;
1470#endif
1471        }
1472    }
1473
1474    file_dest = source;
1475
1476    if ((uri->scheme == NULL || isFileUri)) {
1477        /* XXX possible buffer overflow if VCWD_REALPATH does not know size of resolved_path */
1478        if (!VCWD_REALPATH(source, resolved_path) && !expand_filepath(source, resolved_path TSRMLS_CC)) {
1479            xmlFreeURI(uri);
1480            return NULL;
1481        }
1482        file_dest = resolved_path;
1483    }
1484
1485    xmlFreeURI(uri);
1486
1487    return file_dest;
1488}
1489/* }}} */
1490
1491static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, int source_len, int options TSRMLS_DC) /* {{{ */
1492{
1493    xmlDocPtr ret;
1494    xmlParserCtxtPtr ctxt = NULL;
1495    dom_doc_propsptr doc_props;
1496    dom_object *intern;
1497    php_libxml_ref_obj *document = NULL;
1498    int validate, recover, resolve_externals, keep_blanks, substitute_ent;
1499    int resolved_path_len;
1500    int old_error_reporting = 0;
1501    char *directory=NULL, resolved_path[MAXPATHLEN];
1502
1503    if (id != NULL) {
1504        intern = (dom_object *)zend_object_store_get_object(id TSRMLS_CC);
1505        document = intern->document;
1506    }
1507
1508    doc_props = dom_get_doc_props(document);
1509    validate = doc_props->validateonparse;
1510    resolve_externals = doc_props->resolveexternals;
1511    keep_blanks = doc_props->preservewhitespace;
1512    substitute_ent = doc_props->substituteentities;
1513    recover = doc_props->recover;
1514
1515    if (document == NULL) {
1516        efree(doc_props);
1517    }
1518
1519    xmlInitParser();
1520
1521    if (mode == DOM_LOAD_FILE) {
1522        char *file_dest = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN  TSRMLS_CC);
1523        if (file_dest) {
1524            ctxt = xmlCreateFileParserCtxt(file_dest);
1525        }
1526
1527    } else {
1528        ctxt = xmlCreateMemoryParserCtxt(source, source_len);
1529    }
1530
1531    if (ctxt == NULL) {
1532        return(NULL);
1533    }
1534
1535    /* If loading from memory, we need to set the base directory for the document */
1536    if (mode != DOM_LOAD_FILE) {
1537#if HAVE_GETCWD
1538        directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
1539#elif HAVE_GETWD
1540        directory = VCWD_GETWD(resolved_path);
1541#endif
1542        if (directory) {
1543            if(ctxt->directory != NULL) {
1544                xmlFree((char *) ctxt->directory);
1545            }
1546            resolved_path_len = strlen(resolved_path);
1547            if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) {
1548                resolved_path[resolved_path_len] = DEFAULT_SLASH;
1549                resolved_path[++resolved_path_len] = '\0';
1550            }
1551            ctxt->directory = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
1552        }
1553    }
1554
1555    ctxt->vctxt.error = php_libxml_ctx_error;
1556    ctxt->vctxt.warning = php_libxml_ctx_warning;
1557
1558    if (ctxt->sax != NULL) {
1559        ctxt->sax->error = php_libxml_ctx_error;
1560        ctxt->sax->warning = php_libxml_ctx_warning;
1561    }
1562
1563    if (validate && ! (options & XML_PARSE_DTDVALID)) {
1564        options |= XML_PARSE_DTDVALID;
1565    }
1566    if (resolve_externals && ! (options & XML_PARSE_DTDATTR)) {
1567        options |= XML_PARSE_DTDATTR;
1568    }
1569    if (substitute_ent && ! (options & XML_PARSE_NOENT)) {
1570        options |= XML_PARSE_NOENT;
1571    }
1572    if (keep_blanks == 0 && ! (options & XML_PARSE_NOBLANKS)) {
1573        options |= XML_PARSE_NOBLANKS;
1574    }
1575
1576    xmlCtxtUseOptions(ctxt, options);
1577
1578    ctxt->recovery = recover;
1579    if (recover) {
1580        old_error_reporting = EG(error_reporting);
1581        EG(error_reporting) = old_error_reporting | E_WARNING;
1582    }
1583
1584    xmlParseDocument(ctxt);
1585
1586    if (ctxt->wellFormed || recover) {
1587        ret = ctxt->myDoc;
1588        if (ctxt->recovery) {
1589            EG(error_reporting) = old_error_reporting;
1590        }
1591        /* If loading from memory, set the base reference uri for the document */
1592        if (ret && ret->URL == NULL && ctxt->directory != NULL) {
1593            ret->URL = xmlStrdup(ctxt->directory);
1594        }
1595    } else {
1596        ret = NULL;
1597        xmlFreeDoc(ctxt->myDoc);
1598        ctxt->myDoc = NULL;
1599    }
1600
1601    xmlFreeParserCtxt(ctxt);
1602
1603    return(ret);
1604}
1605/* }}} */
1606
1607/* {{{ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) */
1608static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) {
1609    zval *id;
1610    xmlDoc *docp = NULL, *newdoc;
1611    dom_doc_propsptr doc_prop;
1612    dom_object *intern;
1613    char *source;
1614    int source_len, refcount, ret;
1615    long options = 0;
1616
1617    id = getThis();
1618    if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), dom_document_class_entry TSRMLS_CC)) {
1619        id = NULL;
1620    }
1621
1622    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &options) == FAILURE) {
1623        return;
1624    }
1625
1626    if (!source_len) {
1627        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string supplied as input");
1628        RETURN_FALSE;
1629    }
1630
1631    newdoc = dom_document_parser(id, mode, source, source_len, options TSRMLS_CC);
1632
1633    if (!newdoc)
1634        RETURN_FALSE;
1635
1636    if (id != NULL) {
1637        intern = (dom_object *)zend_object_store_get_object(id TSRMLS_CC);
1638        if (intern != NULL) {
1639            docp = (xmlDocPtr) dom_object_get_node(intern);
1640            doc_prop = NULL;
1641            if (docp != NULL) {
1642                php_libxml_decrement_node_ptr((php_libxml_node_object *) intern TSRMLS_CC);
1643                doc_prop = intern->document->doc_props;
1644                intern->document->doc_props = NULL;
1645                refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern TSRMLS_CC);
1646                if (refcount != 0) {
1647                    docp->_private = NULL;
1648                }
1649            }
1650            intern->document = NULL;
1651            if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc TSRMLS_CC) == -1) {
1652                RETURN_FALSE;
1653            }
1654            intern->document->doc_props = doc_prop;
1655        }
1656
1657        php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern TSRMLS_CC);
1658
1659        RETURN_TRUE;
1660    } else {
1661        DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
1662    }
1663}
1664/* }}} end dom_parser_document */
1665
1666/* {{{ proto DOMNode dom_document_load(string source [, int options]);
1667URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-load
1668Since: DOM Level 3
1669*/
1670PHP_METHOD(domdocument, load)
1671{
1672    dom_parse_document(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
1673}
1674/* }}} end dom_document_load */
1675
1676/* {{{ proto DOMNode dom_document_loadxml(string source [, int options]);
1677URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-loadXML
1678Since: DOM Level 3
1679*/
1680PHP_METHOD(domdocument, loadXML)
1681{
1682    dom_parse_document(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
1683}
1684/* }}} end dom_document_loadxml */
1685
1686/* {{{ proto int dom_document_save(string file);
1687Convenience method to save to file
1688*/
1689PHP_FUNCTION(dom_document_save)
1690{
1691    zval *id;
1692    xmlDoc *docp;
1693    int file_len = 0, bytes, format, saveempty = 0;
1694    dom_object *intern;
1695    dom_doc_propsptr doc_props;
1696    char *file;
1697    long options = 0;
1698
1699    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|l", &id, dom_document_class_entry, &file, &file_len, &options) == FAILURE) {
1700        return;
1701    }
1702
1703    if (file_len == 0) {
1704        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Filename");
1705        RETURN_FALSE;
1706    }
1707
1708    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1709
1710    /* encoding handled by property on doc */
1711
1712    doc_props = dom_get_doc_props(intern->document);
1713    format = doc_props->formatoutput;
1714    if (options & LIBXML_SAVE_NOEMPTYTAG) {
1715        saveempty = xmlSaveNoEmptyTags;
1716        xmlSaveNoEmptyTags = 1;
1717    }
1718    bytes = xmlSaveFormatFileEnc(file, docp, NULL, format);
1719    if (options & LIBXML_SAVE_NOEMPTYTAG) {
1720        xmlSaveNoEmptyTags = saveempty;
1721    }
1722    if (bytes == -1) {
1723        RETURN_FALSE;
1724    }
1725    RETURN_LONG(bytes);
1726}
1727/* }}} end dom_document_save */
1728
1729/* {{{ proto string dom_document_savexml([node n]);
1730URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-saveXML
1731Since: DOM Level 3
1732*/
1733PHP_FUNCTION(dom_document_savexml)
1734{
1735    zval *id, *nodep = NULL;
1736    xmlDoc *docp;
1737    xmlNode *node;
1738    xmlBufferPtr buf;
1739    xmlChar *mem;
1740    dom_object *intern, *nodeobj;
1741    dom_doc_propsptr doc_props;
1742    int size, format, saveempty = 0;
1743    long options = 0;
1744
1745    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|O!l", &id, dom_document_class_entry, &nodep, dom_node_class_entry, &options) == FAILURE) {
1746        return;
1747    }
1748
1749    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1750
1751    doc_props = dom_get_doc_props(intern->document);
1752    format = doc_props->formatoutput;
1753
1754    if (nodep != NULL) {
1755        /* Dump contents of Node */
1756        DOM_GET_OBJ(node, nodep, xmlNodePtr, nodeobj);
1757        if (node->doc != docp) {
1758            php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
1759            RETURN_FALSE;
1760        }
1761        buf = xmlBufferCreate();
1762        if (!buf) {
1763            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch buffer");
1764            RETURN_FALSE;
1765        }
1766        if (options & LIBXML_SAVE_NOEMPTYTAG) {
1767            saveempty = xmlSaveNoEmptyTags;
1768            xmlSaveNoEmptyTags = 1;
1769        }
1770        xmlNodeDump(buf, docp, node, 0, format);
1771        if (options & LIBXML_SAVE_NOEMPTYTAG) {
1772            xmlSaveNoEmptyTags = saveempty;
1773        }
1774        mem = (xmlChar*) xmlBufferContent(buf);
1775        if (!mem) {
1776            xmlBufferFree(buf);
1777            RETURN_FALSE;
1778        }
1779        RETVAL_STRING(mem, 1);
1780        xmlBufferFree(buf);
1781    } else {
1782        if (options & LIBXML_SAVE_NOEMPTYTAG) {
1783            saveempty = xmlSaveNoEmptyTags;
1784            xmlSaveNoEmptyTags = 1;
1785        }
1786        /* Encoding is handled from the encoding property set on the document */
1787        xmlDocDumpFormatMemory(docp, &mem, &size, format);
1788        if (options & LIBXML_SAVE_NOEMPTYTAG) {
1789            xmlSaveNoEmptyTags = saveempty;
1790        }
1791        if (!size) {
1792            RETURN_FALSE;
1793        }
1794        RETVAL_STRINGL(mem, size, 1);
1795        xmlFree(mem);
1796    }
1797}
1798/* }}} end dom_document_savexml */
1799
1800static xmlNodePtr php_dom_free_xinclude_node(xmlNodePtr cur TSRMLS_DC) /* {{{ */
1801{
1802    xmlNodePtr xincnode;
1803
1804    xincnode = cur;
1805    cur = cur->next;
1806    xmlUnlinkNode(xincnode);
1807    php_libxml_node_free_resource(xincnode TSRMLS_CC);
1808
1809    return cur;
1810}
1811/* }}} */
1812
1813static void php_dom_remove_xinclude_nodes(xmlNodePtr cur TSRMLS_DC) /* {{{ */
1814{
1815    while(cur) {
1816        if (cur->type == XML_XINCLUDE_START) {
1817            cur = php_dom_free_xinclude_node(cur TSRMLS_CC);
1818
1819            /* XML_XINCLUDE_END node will be a sibling of XML_XINCLUDE_START */
1820            while(cur && cur->type != XML_XINCLUDE_END) {
1821                /* remove xinclude processing nodes from recursive xincludes */
1822                if (cur->type == XML_ELEMENT_NODE) {
1823                       php_dom_remove_xinclude_nodes(cur->children TSRMLS_CC);
1824                }
1825                cur = cur->next;
1826            }
1827
1828            if (cur && cur->type == XML_XINCLUDE_END) {
1829                cur = php_dom_free_xinclude_node(cur TSRMLS_CC);
1830            }
1831        } else {
1832            if (cur->type == XML_ELEMENT_NODE) {
1833                php_dom_remove_xinclude_nodes(cur->children TSRMLS_CC);
1834            }
1835            cur = cur->next;
1836        }
1837    }
1838}
1839/* }}} */
1840
1841/* {{{ proto int dom_document_xinclude([int options])
1842   Substitutues xincludes in a DomDocument */
1843PHP_FUNCTION(dom_document_xinclude)
1844{
1845    zval *id;
1846    xmlDoc *docp;
1847    xmlNodePtr root;
1848    long flags = 0;
1849    int err;
1850    dom_object *intern;
1851
1852    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &id, dom_document_class_entry, &flags) == FAILURE) {
1853        return;
1854    }
1855
1856    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1857
1858    err = xmlXIncludeProcessFlags(docp, flags);
1859
1860    /* XML_XINCLUDE_START and XML_XINCLUDE_END nodes need to be removed as these
1861    are added via xmlXIncludeProcess to mark beginning and ending of xincluded document
1862    but are not wanted in resulting document - must be done even if err as it could fail after
1863    having processed some xincludes */
1864    root = (xmlNodePtr) docp->children;
1865    while(root && root->type != XML_ELEMENT_NODE && root->type != XML_XINCLUDE_START) {
1866        root = root->next;
1867    }
1868    if (root) {
1869        php_dom_remove_xinclude_nodes(root TSRMLS_CC);
1870    }
1871
1872    if (err) {
1873        RETVAL_LONG(err);
1874    } else {
1875        RETVAL_FALSE;
1876    }
1877
1878}
1879/* }}} */
1880
1881/* {{{ proto boolean dom_document_validate();
1882Since: DOM extended
1883*/
1884PHP_FUNCTION(dom_document_validate)
1885{
1886    zval *id;
1887    xmlDoc *docp;
1888    dom_object *intern;
1889    xmlValidCtxt *cvp;
1890
1891    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &id, dom_document_class_entry) == FAILURE) {
1892        return;
1893    }
1894
1895    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1896
1897    cvp = xmlNewValidCtxt();
1898
1899    cvp->userData = NULL;
1900    cvp->error    = (xmlValidityErrorFunc) php_libxml_error_handler;
1901    cvp->warning  = (xmlValidityErrorFunc) php_libxml_error_handler;
1902
1903    if (xmlValidateDocument(cvp, docp)) {
1904        RETVAL_TRUE;
1905    } else {
1906        RETVAL_FALSE;
1907    }
1908
1909    xmlFreeValidCtxt(cvp);
1910
1911}
1912/* }}} */
1913
1914#if defined(LIBXML_SCHEMAS_ENABLED)
1915static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
1916{
1917    zval *id;
1918    xmlDoc *docp;
1919    dom_object *intern;
1920    char *source = NULL, *valid_file = NULL;
1921    int source_len = 0, valid_opts = 0;
1922    long flags = 0;
1923    xmlSchemaParserCtxtPtr  parser;
1924    xmlSchemaPtr            sptr;
1925    xmlSchemaValidCtxtPtr   vptr;
1926    int                     is_valid;
1927    char resolved_path[MAXPATHLEN + 1];
1928
1929    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Op|l", &id, dom_document_class_entry, &source, &source_len, &flags) == FAILURE) {
1930        return;
1931    }
1932
1933    if (source_len == 0) {
1934        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema source");
1935        RETURN_FALSE;
1936    }
1937
1938    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1939
1940    switch (type) {
1941    case DOM_LOAD_FILE:
1942        valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN  TSRMLS_CC);
1943        if (!valid_file) {
1944            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema file source");
1945            RETURN_FALSE;
1946        }
1947        parser = xmlSchemaNewParserCtxt(valid_file);
1948        break;
1949    case DOM_LOAD_STRING:
1950        parser = xmlSchemaNewMemParserCtxt(source, source_len);
1951        /* If loading from memory, we need to set the base directory for the document
1952           but it is not apparent how to do that for schema's */
1953        break;
1954    default:
1955        return;
1956    }
1957
1958    xmlSchemaSetParserErrors(parser,
1959        (xmlSchemaValidityErrorFunc) php_libxml_error_handler,
1960        (xmlSchemaValidityWarningFunc) php_libxml_error_handler,
1961        parser);
1962    sptr = xmlSchemaParse(parser);
1963    xmlSchemaFreeParserCtxt(parser);
1964    if (!sptr) {
1965        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema");
1966        RETURN_FALSE;
1967    }
1968
1969    docp = (xmlDocPtr) dom_object_get_node(intern);
1970
1971    vptr = xmlSchemaNewValidCtxt(sptr);
1972    if (!vptr) {
1973        xmlSchemaFree(sptr);
1974        php_error(E_ERROR, "Invalid Schema Validation Context");
1975        RETURN_FALSE;
1976    }
1977
1978#if LIBXML_VERSION >= 20614
1979    if (flags & XML_SCHEMA_VAL_VC_I_CREATE) {
1980        valid_opts |= XML_SCHEMA_VAL_VC_I_CREATE;
1981    }
1982#endif
1983
1984    xmlSchemaSetValidOptions(vptr, valid_opts);
1985    xmlSchemaSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr);
1986    is_valid = xmlSchemaValidateDoc(vptr, docp);
1987    xmlSchemaFree(sptr);
1988    xmlSchemaFreeValidCtxt(vptr);
1989
1990    if (is_valid == 0) {
1991        RETURN_TRUE;
1992    } else {
1993        RETURN_FALSE;
1994    }
1995}
1996/* }}} */
1997
1998/* {{{ proto boolean dom_document_schema_validate_file(string filename, int flags); */
1999PHP_FUNCTION(dom_document_schema_validate_file)
2000{
2001    _dom_document_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
2002}
2003/* }}} end dom_document_schema_validate_file */
2004
2005/* {{{ proto boolean dom_document_schema_validate(string source, int flags); */
2006PHP_FUNCTION(dom_document_schema_validate_xml)
2007{
2008    _dom_document_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
2009}
2010/* }}} end dom_document_schema_validate */
2011
2012static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
2013{
2014    zval *id;
2015    xmlDoc *docp;
2016    dom_object *intern;
2017    char *source = NULL, *valid_file = NULL;
2018    int source_len = 0;
2019    xmlRelaxNGParserCtxtPtr parser;
2020    xmlRelaxNGPtr           sptr;
2021    xmlRelaxNGValidCtxtPtr  vptr;
2022    int                     is_valid;
2023    char resolved_path[MAXPATHLEN + 1];
2024
2025    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Op", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
2026        return;
2027    }
2028
2029    if (source_len == 0) {
2030        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema source");
2031        RETURN_FALSE;
2032    }
2033
2034    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2035
2036    switch (type) {
2037    case DOM_LOAD_FILE:
2038        valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN  TSRMLS_CC);
2039        if (!valid_file) {
2040            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid RelaxNG file source");
2041            RETURN_FALSE;
2042        }
2043        parser = xmlRelaxNGNewParserCtxt(valid_file);
2044        break;
2045    case DOM_LOAD_STRING:
2046        parser = xmlRelaxNGNewMemParserCtxt(source, source_len);
2047        /* If loading from memory, we need to set the base directory for the document
2048           but it is not apparent how to do that for schema's */
2049        break;
2050    default:
2051        return;
2052    }
2053
2054    xmlRelaxNGSetParserErrors(parser,
2055        (xmlRelaxNGValidityErrorFunc) php_libxml_error_handler,
2056        (xmlRelaxNGValidityWarningFunc) php_libxml_error_handler,
2057        parser);
2058    sptr = xmlRelaxNGParse(parser);
2059    xmlRelaxNGFreeParserCtxt(parser);
2060    if (!sptr) {
2061        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid RelaxNG");
2062        RETURN_FALSE;
2063    }
2064
2065    docp = (xmlDocPtr) dom_object_get_node(intern);
2066
2067    vptr = xmlRelaxNGNewValidCtxt(sptr);
2068    if (!vptr) {
2069        xmlRelaxNGFree(sptr);
2070        php_error(E_ERROR, "Invalid RelaxNG Validation Context");
2071        RETURN_FALSE;
2072    }
2073
2074    xmlRelaxNGSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr);
2075    is_valid = xmlRelaxNGValidateDoc(vptr, docp);
2076    xmlRelaxNGFree(sptr);
2077    xmlRelaxNGFreeValidCtxt(vptr);
2078
2079    if (is_valid == 0) {
2080        RETURN_TRUE;
2081    } else {
2082        RETURN_FALSE;
2083    }
2084}
2085/* }}} */
2086
2087/* {{{ proto boolean dom_document_relaxNG_validate_file(string filename); */
2088PHP_FUNCTION(dom_document_relaxNG_validate_file)
2089{
2090    _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
2091}
2092/* }}} end dom_document_relaxNG_validate_file */
2093
2094/* {{{ proto boolean dom_document_relaxNG_validate_xml(string source); */
2095PHP_FUNCTION(dom_document_relaxNG_validate_xml)
2096{
2097    _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
2098}
2099/* }}} end dom_document_relaxNG_validate_xml */
2100
2101#endif
2102
2103#if defined(LIBXML_HTML_ENABLED)
2104
2105static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
2106{
2107    zval *id;
2108    xmlDoc *docp = NULL, *newdoc;
2109    dom_object *intern;
2110    dom_doc_propsptr doc_prop;
2111    char *source;
2112    int source_len, refcount, ret;
2113    long options = 0;
2114    htmlParserCtxtPtr ctxt;
2115
2116    id = getThis();
2117
2118    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &options) == FAILURE) {
2119        return;
2120    }
2121
2122    if (!source_len) {
2123        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string supplied as input");
2124        RETURN_FALSE;
2125    }
2126
2127    if (mode == DOM_LOAD_FILE) {
2128        ctxt = htmlCreateFileParserCtxt(source, NULL);
2129    } else {
2130        source_len = xmlStrlen(source);
2131        ctxt = htmlCreateMemoryParserCtxt(source, source_len);
2132    }
2133
2134    if (!ctxt) {
2135        RETURN_FALSE;
2136    }
2137
2138    if (options) {
2139        htmlCtxtUseOptions(ctxt, options);
2140    }
2141
2142    ctxt->vctxt.error = php_libxml_ctx_error;
2143    ctxt->vctxt.warning = php_libxml_ctx_warning;
2144    if (ctxt->sax != NULL) {
2145        ctxt->sax->error = php_libxml_ctx_error;
2146        ctxt->sax->warning = php_libxml_ctx_warning;
2147    }
2148    htmlParseDocument(ctxt);
2149    newdoc = ctxt->myDoc;
2150    htmlFreeParserCtxt(ctxt);
2151
2152    if (!newdoc)
2153        RETURN_FALSE;
2154
2155    if (id != NULL && instanceof_function(Z_OBJCE_P(id), dom_document_class_entry TSRMLS_CC)) {
2156        intern = (dom_object *)zend_object_store_get_object(id TSRMLS_CC);
2157        if (intern != NULL) {
2158            docp = (xmlDocPtr) dom_object_get_node(intern);
2159            doc_prop = NULL;
2160            if (docp != NULL) {
2161                php_libxml_decrement_node_ptr((php_libxml_node_object *) intern TSRMLS_CC);
2162                doc_prop = intern->document->doc_props;
2163                intern->document->doc_props = NULL;
2164                refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern TSRMLS_CC);
2165                if (refcount != 0) {
2166                    docp->_private = NULL;
2167                }
2168            }
2169            intern->document = NULL;
2170            if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc TSRMLS_CC) == -1) {
2171                RETURN_FALSE;
2172            }
2173            intern->document->doc_props = doc_prop;
2174        }
2175
2176        php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern TSRMLS_CC);
2177
2178        RETURN_TRUE;
2179    } else {
2180        DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
2181    }
2182}
2183/* }}} */
2184
2185/* {{{ proto DOMNode dom_document_load_html_file(string source);
2186Since: DOM extended
2187*/
2188PHP_METHOD(domdocument, loadHTMLFile)
2189{
2190    dom_load_html(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
2191}
2192/* }}} end dom_document_load_html_file */
2193
2194/* {{{ proto DOMNode dom_document_load_html(string source);
2195Since: DOM extended
2196*/
2197PHP_METHOD(domdocument, loadHTML)
2198{
2199    dom_load_html(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
2200}
2201/* }}} end dom_document_load_html */
2202
2203/* {{{ proto int dom_document_save_html_file(string file);
2204Convenience method to save to file as html
2205*/
2206PHP_FUNCTION(dom_document_save_html_file)
2207{
2208    zval *id;
2209    xmlDoc *docp;
2210    int file_len, bytes, format;
2211    dom_object *intern;
2212    dom_doc_propsptr doc_props;
2213    char *file;
2214    const char *encoding;
2215
2216    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &file, &file_len) == FAILURE) {
2217        return;
2218    }
2219
2220    if (file_len == 0) {
2221        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Filename");
2222        RETURN_FALSE;
2223    }
2224
2225    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2226
2227
2228    encoding = (const char *) htmlGetMetaEncoding(docp);
2229
2230    doc_props = dom_get_doc_props(intern->document);
2231    format = doc_props->formatoutput;
2232    bytes = htmlSaveFileFormat(file, docp, encoding, format);
2233
2234    if (bytes == -1) {
2235        RETURN_FALSE;
2236    }
2237    RETURN_LONG(bytes);
2238}
2239/* }}} end dom_document_save_html_file */
2240
2241/* {{{ proto string dom_document_save_html();
2242Convenience method to output as html
2243*/
2244PHP_FUNCTION(dom_document_save_html)
2245{
2246    zval *id, *nodep = NULL;
2247    xmlDoc *docp;
2248    xmlNode *node;
2249    xmlBufferPtr buf;
2250    dom_object *intern, *nodeobj;
2251    xmlChar *mem = NULL;
2252    int size = 0, format;
2253    dom_doc_propsptr doc_props;
2254
2255    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
2256        "O|O!", &id, dom_document_class_entry, &nodep, dom_node_class_entry)
2257        == FAILURE) {
2258        return;
2259    }
2260
2261    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2262
2263    doc_props = dom_get_doc_props(intern->document);
2264    format = doc_props->formatoutput;
2265
2266    if (nodep != NULL) {
2267        /* Dump contents of Node */
2268        DOM_GET_OBJ(node, nodep, xmlNodePtr, nodeobj);
2269        if (node->doc != docp) {
2270            php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
2271            RETURN_FALSE;
2272        }
2273
2274        buf = xmlBufferCreate();
2275        if (!buf) {
2276            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch buffer");
2277            RETURN_FALSE;
2278        }
2279
2280        if (node->type == XML_DOCUMENT_FRAG_NODE) {
2281            int one_size;
2282
2283            for (node = node->children; node; node = node->next) {
2284                one_size = htmlNodeDump(buf, docp, node);
2285
2286                if (one_size >= 0) {
2287                    size += one_size;
2288                } else {
2289                    size = -1;
2290                    break;
2291                }
2292            }
2293        } else {
2294            size = htmlNodeDump(buf, docp, node);
2295        }
2296        if (size >= 0) {
2297            mem = (xmlChar*) xmlBufferContent(buf);
2298            if (!mem) {
2299                RETVAL_FALSE;
2300            } else {
2301                RETVAL_STRINGL((const char*) mem, size, 1);
2302            }
2303        } else {
2304            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error dumping HTML node");
2305            RETVAL_FALSE;
2306        }
2307        xmlBufferFree(buf);
2308    } else {
2309#if LIBXML_VERSION >= 20623
2310        htmlDocDumpMemoryFormat(docp, &mem, &size, format);
2311#else
2312        htmlDocDumpMemory(docp, &mem, &size);
2313#endif
2314        if (!size) {
2315            RETVAL_FALSE;
2316        } else {
2317            RETVAL_STRINGL((const char*) mem, size, 1);
2318        }
2319        if (mem)
2320            xmlFree(mem);
2321    }
2322
2323}
2324/* }}} end dom_document_save_html */
2325
2326#endif  /* defined(LIBXML_HTML_ENABLED) */
2327
2328/* {{{ proto boolean DOMDocument::registerNodeClass(string baseclass, string extendedclass);
2329   Register extended class used to create base node type */
2330PHP_METHOD(domdocument, registerNodeClass)
2331{
2332    zval *id;
2333    xmlDoc *docp;
2334    char *baseclass = NULL, *extendedclass = NULL;
2335    int baseclass_len = 0, extendedclass_len = 0;
2336    zend_class_entry *basece = NULL, *ce = NULL;
2337    dom_object *intern;
2338
2339    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oss!", &id, dom_document_class_entry, &baseclass, &baseclass_len, &extendedclass, &extendedclass_len) == FAILURE) {
2340        return;
2341    }
2342
2343    if (baseclass_len) {
2344        zend_class_entry **pce;
2345        if (zend_lookup_class(baseclass, baseclass_len, &pce TSRMLS_CC) == FAILURE) {
2346            php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s does not exist", baseclass);
2347            return;
2348        }
2349        basece = *pce;
2350    }
2351
2352    if (basece == NULL || ! instanceof_function(basece, dom_node_class_entry TSRMLS_CC)) {
2353        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s is not derived from DOMNode.", baseclass);
2354        return;
2355    }
2356
2357    if (extendedclass_len) {
2358        zend_class_entry **pce;
2359        if (zend_lookup_class(extendedclass, extendedclass_len, &pce TSRMLS_CC) == FAILURE) {
2360            php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s does not exist", extendedclass);
2361        }
2362        ce = *pce;
2363    }
2364
2365    if (ce == NULL || instanceof_function(ce, basece TSRMLS_CC)) {
2366
2367        DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2368
2369        if (dom_set_doc_classmap(intern->document, basece, ce TSRMLS_CC) == FAILURE) {
2370            php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s could not be registered.", extendedclass);
2371        }
2372        RETURN_TRUE;
2373    } else {
2374        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s is not derived from %s.", extendedclass, baseclass);
2375    }
2376
2377    RETURN_FALSE;
2378}
2379/* }}} */
2380
2381#endif  /* HAVE_LIBXML && HAVE_DOM */
2382
2383/*
2384 * Local variables:
2385 * tab-width: 4
2386 * c-basic-offset: 4
2387 * End:
2388 * vim600: noet sw=4 ts=4 fdm=marker
2389 * vim<600: noet sw=4 ts=4
2390 */
2391