1/*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2015 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;
1523        if (CHECK_NULL_PATH(source, source_len)) {
1524            return NULL;
1525        }
1526        file_dest = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN  TSRMLS_CC);
1527        if (file_dest) {
1528            ctxt = xmlCreateFileParserCtxt(file_dest);
1529        }
1530
1531    } else {
1532        ctxt = xmlCreateMemoryParserCtxt(source, source_len);
1533    }
1534
1535    if (ctxt == NULL) {
1536        return(NULL);
1537    }
1538
1539    /* If loading from memory, we need to set the base directory for the document */
1540    if (mode != DOM_LOAD_FILE) {
1541#if HAVE_GETCWD
1542        directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
1543#elif HAVE_GETWD
1544        directory = VCWD_GETWD(resolved_path);
1545#endif
1546        if (directory) {
1547            if(ctxt->directory != NULL) {
1548                xmlFree((char *) ctxt->directory);
1549            }
1550            resolved_path_len = strlen(resolved_path);
1551            if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) {
1552                resolved_path[resolved_path_len] = DEFAULT_SLASH;
1553                resolved_path[++resolved_path_len] = '\0';
1554            }
1555            ctxt->directory = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
1556        }
1557    }
1558
1559    ctxt->vctxt.error = php_libxml_ctx_error;
1560    ctxt->vctxt.warning = php_libxml_ctx_warning;
1561
1562    if (ctxt->sax != NULL) {
1563        ctxt->sax->error = php_libxml_ctx_error;
1564        ctxt->sax->warning = php_libxml_ctx_warning;
1565    }
1566
1567    if (validate && ! (options & XML_PARSE_DTDVALID)) {
1568        options |= XML_PARSE_DTDVALID;
1569    }
1570    if (resolve_externals && ! (options & XML_PARSE_DTDATTR)) {
1571        options |= XML_PARSE_DTDATTR;
1572    }
1573    if (substitute_ent && ! (options & XML_PARSE_NOENT)) {
1574        options |= XML_PARSE_NOENT;
1575    }
1576    if (keep_blanks == 0 && ! (options & XML_PARSE_NOBLANKS)) {
1577        options |= XML_PARSE_NOBLANKS;
1578    }
1579
1580    xmlCtxtUseOptions(ctxt, options);
1581
1582    ctxt->recovery = recover;
1583    if (recover) {
1584        old_error_reporting = EG(error_reporting);
1585        EG(error_reporting) = old_error_reporting | E_WARNING;
1586    }
1587
1588    xmlParseDocument(ctxt);
1589
1590    if (ctxt->wellFormed || recover) {
1591        ret = ctxt->myDoc;
1592        if (ctxt->recovery) {
1593            EG(error_reporting) = old_error_reporting;
1594        }
1595        /* If loading from memory, set the base reference uri for the document */
1596        if (ret && ret->URL == NULL && ctxt->directory != NULL) {
1597            ret->URL = xmlStrdup(ctxt->directory);
1598        }
1599    } else {
1600        ret = NULL;
1601        xmlFreeDoc(ctxt->myDoc);
1602        ctxt->myDoc = NULL;
1603    }
1604
1605    xmlFreeParserCtxt(ctxt);
1606
1607    return(ret);
1608}
1609/* }}} */
1610
1611/* {{{ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) */
1612static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) {
1613    zval *id;
1614    xmlDoc *docp = NULL, *newdoc;
1615    dom_doc_propsptr doc_prop;
1616    dom_object *intern;
1617    char *source;
1618    int source_len, refcount, ret;
1619    long options = 0;
1620
1621    id = getThis();
1622    if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), dom_document_class_entry TSRMLS_CC)) {
1623        id = NULL;
1624    }
1625
1626    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &options) == FAILURE) {
1627        return;
1628    }
1629
1630    if (!source_len) {
1631        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string supplied as input");
1632        RETURN_FALSE;
1633    }
1634
1635    newdoc = dom_document_parser(id, mode, source, source_len, options TSRMLS_CC);
1636
1637    if (!newdoc)
1638        RETURN_FALSE;
1639
1640    if (id != NULL) {
1641        intern = (dom_object *)zend_object_store_get_object(id TSRMLS_CC);
1642        if (intern != NULL) {
1643            docp = (xmlDocPtr) dom_object_get_node(intern);
1644            doc_prop = NULL;
1645            if (docp != NULL) {
1646                php_libxml_decrement_node_ptr((php_libxml_node_object *) intern TSRMLS_CC);
1647                doc_prop = intern->document->doc_props;
1648                intern->document->doc_props = NULL;
1649                refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern TSRMLS_CC);
1650                if (refcount != 0) {
1651                    docp->_private = NULL;
1652                }
1653            }
1654            intern->document = NULL;
1655            if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc TSRMLS_CC) == -1) {
1656                RETURN_FALSE;
1657            }
1658            intern->document->doc_props = doc_prop;
1659        }
1660
1661        php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern TSRMLS_CC);
1662
1663        RETURN_TRUE;
1664    } else {
1665        DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
1666    }
1667}
1668/* }}} end dom_parser_document */
1669
1670/* {{{ proto DOMNode dom_document_load(string source [, int options]);
1671URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-load
1672Since: DOM Level 3
1673*/
1674PHP_METHOD(domdocument, load)
1675{
1676    dom_parse_document(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
1677}
1678/* }}} end dom_document_load */
1679
1680/* {{{ proto DOMNode dom_document_loadxml(string source [, int options]);
1681URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-loadXML
1682Since: DOM Level 3
1683*/
1684PHP_METHOD(domdocument, loadXML)
1685{
1686    dom_parse_document(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
1687}
1688/* }}} end dom_document_loadxml */
1689
1690/* {{{ proto int dom_document_save(string file);
1691Convenience method to save to file
1692*/
1693PHP_FUNCTION(dom_document_save)
1694{
1695    zval *id;
1696    xmlDoc *docp;
1697    int file_len = 0, bytes, format, saveempty = 0;
1698    dom_object *intern;
1699    dom_doc_propsptr doc_props;
1700    char *file;
1701    long options = 0;
1702
1703    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Op|l", &id, dom_document_class_entry, &file, &file_len, &options) == FAILURE) {
1704        return;
1705    }
1706
1707    if (file_len == 0) {
1708        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Filename");
1709        RETURN_FALSE;
1710    }
1711
1712    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1713
1714    /* encoding handled by property on doc */
1715
1716    doc_props = dom_get_doc_props(intern->document);
1717    format = doc_props->formatoutput;
1718    if (options & LIBXML_SAVE_NOEMPTYTAG) {
1719        saveempty = xmlSaveNoEmptyTags;
1720        xmlSaveNoEmptyTags = 1;
1721    }
1722    bytes = xmlSaveFormatFileEnc(file, docp, NULL, format);
1723    if (options & LIBXML_SAVE_NOEMPTYTAG) {
1724        xmlSaveNoEmptyTags = saveempty;
1725    }
1726    if (bytes == -1) {
1727        RETURN_FALSE;
1728    }
1729    RETURN_LONG(bytes);
1730}
1731/* }}} end dom_document_save */
1732
1733/* {{{ proto string dom_document_savexml([node n]);
1734URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-saveXML
1735Since: DOM Level 3
1736*/
1737PHP_FUNCTION(dom_document_savexml)
1738{
1739    zval *id, *nodep = NULL;
1740    xmlDoc *docp;
1741    xmlNode *node;
1742    xmlBufferPtr buf;
1743    xmlChar *mem;
1744    dom_object *intern, *nodeobj;
1745    dom_doc_propsptr doc_props;
1746    int size, format, saveempty = 0;
1747    long options = 0;
1748
1749    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) {
1750        return;
1751    }
1752
1753    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1754
1755    doc_props = dom_get_doc_props(intern->document);
1756    format = doc_props->formatoutput;
1757
1758    if (nodep != NULL) {
1759        /* Dump contents of Node */
1760        DOM_GET_OBJ(node, nodep, xmlNodePtr, nodeobj);
1761        if (node->doc != docp) {
1762            php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
1763            RETURN_FALSE;
1764        }
1765        buf = xmlBufferCreate();
1766        if (!buf) {
1767            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch buffer");
1768            RETURN_FALSE;
1769        }
1770        if (options & LIBXML_SAVE_NOEMPTYTAG) {
1771            saveempty = xmlSaveNoEmptyTags;
1772            xmlSaveNoEmptyTags = 1;
1773        }
1774        xmlNodeDump(buf, docp, node, 0, format);
1775        if (options & LIBXML_SAVE_NOEMPTYTAG) {
1776            xmlSaveNoEmptyTags = saveempty;
1777        }
1778        mem = (xmlChar*) xmlBufferContent(buf);
1779        if (!mem) {
1780            xmlBufferFree(buf);
1781            RETURN_FALSE;
1782        }
1783        RETVAL_STRING(mem, 1);
1784        xmlBufferFree(buf);
1785    } else {
1786        if (options & LIBXML_SAVE_NOEMPTYTAG) {
1787            saveempty = xmlSaveNoEmptyTags;
1788            xmlSaveNoEmptyTags = 1;
1789        }
1790        /* Encoding is handled from the encoding property set on the document */
1791        xmlDocDumpFormatMemory(docp, &mem, &size, format);
1792        if (options & LIBXML_SAVE_NOEMPTYTAG) {
1793            xmlSaveNoEmptyTags = saveempty;
1794        }
1795        if (!size) {
1796            RETURN_FALSE;
1797        }
1798        RETVAL_STRINGL(mem, size, 1);
1799        xmlFree(mem);
1800    }
1801}
1802/* }}} end dom_document_savexml */
1803
1804static xmlNodePtr php_dom_free_xinclude_node(xmlNodePtr cur TSRMLS_DC) /* {{{ */
1805{
1806    xmlNodePtr xincnode;
1807
1808    xincnode = cur;
1809    cur = cur->next;
1810    xmlUnlinkNode(xincnode);
1811    php_libxml_node_free_resource(xincnode TSRMLS_CC);
1812
1813    return cur;
1814}
1815/* }}} */
1816
1817static void php_dom_remove_xinclude_nodes(xmlNodePtr cur TSRMLS_DC) /* {{{ */
1818{
1819    while(cur) {
1820        if (cur->type == XML_XINCLUDE_START) {
1821            cur = php_dom_free_xinclude_node(cur TSRMLS_CC);
1822
1823            /* XML_XINCLUDE_END node will be a sibling of XML_XINCLUDE_START */
1824            while(cur && cur->type != XML_XINCLUDE_END) {
1825                /* remove xinclude processing nodes from recursive xincludes */
1826                if (cur->type == XML_ELEMENT_NODE) {
1827                       php_dom_remove_xinclude_nodes(cur->children TSRMLS_CC);
1828                }
1829                cur = cur->next;
1830            }
1831
1832            if (cur && cur->type == XML_XINCLUDE_END) {
1833                cur = php_dom_free_xinclude_node(cur TSRMLS_CC);
1834            }
1835        } else {
1836            if (cur->type == XML_ELEMENT_NODE) {
1837                php_dom_remove_xinclude_nodes(cur->children TSRMLS_CC);
1838            }
1839            cur = cur->next;
1840        }
1841    }
1842}
1843/* }}} */
1844
1845/* {{{ proto int dom_document_xinclude([int options])
1846   Substitutues xincludes in a DomDocument */
1847PHP_FUNCTION(dom_document_xinclude)
1848{
1849    zval *id;
1850    xmlDoc *docp;
1851    xmlNodePtr root;
1852    long flags = 0;
1853    int err;
1854    dom_object *intern;
1855
1856    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &id, dom_document_class_entry, &flags) == FAILURE) {
1857        return;
1858    }
1859
1860    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1861
1862    err = xmlXIncludeProcessFlags(docp, flags);
1863
1864    /* XML_XINCLUDE_START and XML_XINCLUDE_END nodes need to be removed as these
1865    are added via xmlXIncludeProcess to mark beginning and ending of xincluded document
1866    but are not wanted in resulting document - must be done even if err as it could fail after
1867    having processed some xincludes */
1868    root = (xmlNodePtr) docp->children;
1869    while(root && root->type != XML_ELEMENT_NODE && root->type != XML_XINCLUDE_START) {
1870        root = root->next;
1871    }
1872    if (root) {
1873        php_dom_remove_xinclude_nodes(root TSRMLS_CC);
1874    }
1875
1876    if (err) {
1877        RETVAL_LONG(err);
1878    } else {
1879        RETVAL_FALSE;
1880    }
1881
1882}
1883/* }}} */
1884
1885/* {{{ proto boolean dom_document_validate();
1886Since: DOM extended
1887*/
1888PHP_FUNCTION(dom_document_validate)
1889{
1890    zval *id;
1891    xmlDoc *docp;
1892    dom_object *intern;
1893    xmlValidCtxt *cvp;
1894
1895    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &id, dom_document_class_entry) == FAILURE) {
1896        return;
1897    }
1898
1899    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1900
1901    cvp = xmlNewValidCtxt();
1902
1903    cvp->userData = NULL;
1904    cvp->error    = (xmlValidityErrorFunc) php_libxml_error_handler;
1905    cvp->warning  = (xmlValidityErrorFunc) php_libxml_error_handler;
1906
1907    if (xmlValidateDocument(cvp, docp)) {
1908        RETVAL_TRUE;
1909    } else {
1910        RETVAL_FALSE;
1911    }
1912
1913    xmlFreeValidCtxt(cvp);
1914
1915}
1916/* }}} */
1917
1918#if defined(LIBXML_SCHEMAS_ENABLED)
1919static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
1920{
1921    zval *id;
1922    xmlDoc *docp;
1923    dom_object *intern;
1924    char *source = NULL, *valid_file = NULL;
1925    int source_len = 0, valid_opts = 0;
1926    long flags = 0;
1927    xmlSchemaParserCtxtPtr  parser;
1928    xmlSchemaPtr            sptr;
1929    xmlSchemaValidCtxtPtr   vptr;
1930    int                     is_valid;
1931    char resolved_path[MAXPATHLEN + 1];
1932
1933    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|l", &id, dom_document_class_entry, &source, &source_len, &flags) == FAILURE) {
1934        return;
1935    }
1936
1937    if (source_len == 0) {
1938        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema source");
1939        RETURN_FALSE;
1940    }
1941
1942    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1943
1944    switch (type) {
1945    case DOM_LOAD_FILE:
1946        if (CHECK_NULL_PATH(source, source_len)) {
1947            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema file source");
1948            RETURN_FALSE;
1949        }
1950        valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN  TSRMLS_CC);
1951        if (!valid_file) {
1952            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema file source");
1953            RETURN_FALSE;
1954        }
1955        parser = xmlSchemaNewParserCtxt(valid_file);
1956        break;
1957    case DOM_LOAD_STRING:
1958        parser = xmlSchemaNewMemParserCtxt(source, source_len);
1959        /* If loading from memory, we need to set the base directory for the document
1960           but it is not apparent how to do that for schema's */
1961        break;
1962    default:
1963        return;
1964    }
1965
1966    xmlSchemaSetParserErrors(parser,
1967        (xmlSchemaValidityErrorFunc) php_libxml_error_handler,
1968        (xmlSchemaValidityWarningFunc) php_libxml_error_handler,
1969        parser);
1970    sptr = xmlSchemaParse(parser);
1971    xmlSchemaFreeParserCtxt(parser);
1972    if (!sptr) {
1973        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema");
1974        RETURN_FALSE;
1975    }
1976
1977    docp = (xmlDocPtr) dom_object_get_node(intern);
1978
1979    vptr = xmlSchemaNewValidCtxt(sptr);
1980    if (!vptr) {
1981        xmlSchemaFree(sptr);
1982        php_error(E_ERROR, "Invalid Schema Validation Context");
1983        RETURN_FALSE;
1984    }
1985
1986#if LIBXML_VERSION >= 20614
1987    if (flags & XML_SCHEMA_VAL_VC_I_CREATE) {
1988        valid_opts |= XML_SCHEMA_VAL_VC_I_CREATE;
1989    }
1990#endif
1991
1992    xmlSchemaSetValidOptions(vptr, valid_opts);
1993    xmlSchemaSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr);
1994    is_valid = xmlSchemaValidateDoc(vptr, docp);
1995    xmlSchemaFree(sptr);
1996    xmlSchemaFreeValidCtxt(vptr);
1997
1998    if (is_valid == 0) {
1999        RETURN_TRUE;
2000    } else {
2001        RETURN_FALSE;
2002    }
2003}
2004/* }}} */
2005
2006/* {{{ proto boolean dom_document_schema_validate_file(string filename, int flags); */
2007PHP_FUNCTION(dom_document_schema_validate_file)
2008{
2009    _dom_document_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
2010}
2011/* }}} end dom_document_schema_validate_file */
2012
2013/* {{{ proto boolean dom_document_schema_validate(string source, int flags); */
2014PHP_FUNCTION(dom_document_schema_validate_xml)
2015{
2016    _dom_document_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
2017}
2018/* }}} end dom_document_schema_validate */
2019
2020static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
2021{
2022    zval *id;
2023    xmlDoc *docp;
2024    dom_object *intern;
2025    char *source = NULL, *valid_file = NULL;
2026    int source_len = 0;
2027    xmlRelaxNGParserCtxtPtr parser;
2028    xmlRelaxNGPtr           sptr;
2029    xmlRelaxNGValidCtxtPtr  vptr;
2030    int                     is_valid;
2031    char resolved_path[MAXPATHLEN + 1];
2032
2033    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
2034        return;
2035    }
2036
2037    if (source_len == 0) {
2038        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Schema source");
2039        RETURN_FALSE;
2040    }
2041
2042    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2043
2044    switch (type) {
2045    case DOM_LOAD_FILE:
2046        if (CHECK_NULL_PATH(source, source_len)) {
2047            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid RelaxNG file source");
2048            RETURN_FALSE;
2049        }
2050        valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN  TSRMLS_CC);
2051        if (!valid_file) {
2052            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid RelaxNG file source");
2053            RETURN_FALSE;
2054        }
2055        parser = xmlRelaxNGNewParserCtxt(valid_file);
2056        break;
2057    case DOM_LOAD_STRING:
2058        parser = xmlRelaxNGNewMemParserCtxt(source, source_len);
2059        /* If loading from memory, we need to set the base directory for the document
2060           but it is not apparent how to do that for schema's */
2061        break;
2062    default:
2063        return;
2064    }
2065
2066    xmlRelaxNGSetParserErrors(parser,
2067        (xmlRelaxNGValidityErrorFunc) php_libxml_error_handler,
2068        (xmlRelaxNGValidityWarningFunc) php_libxml_error_handler,
2069        parser);
2070    sptr = xmlRelaxNGParse(parser);
2071    xmlRelaxNGFreeParserCtxt(parser);
2072    if (!sptr) {
2073        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid RelaxNG");
2074        RETURN_FALSE;
2075    }
2076
2077    docp = (xmlDocPtr) dom_object_get_node(intern);
2078
2079    vptr = xmlRelaxNGNewValidCtxt(sptr);
2080    if (!vptr) {
2081        xmlRelaxNGFree(sptr);
2082        php_error(E_ERROR, "Invalid RelaxNG Validation Context");
2083        RETURN_FALSE;
2084    }
2085
2086    xmlRelaxNGSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr);
2087    is_valid = xmlRelaxNGValidateDoc(vptr, docp);
2088    xmlRelaxNGFree(sptr);
2089    xmlRelaxNGFreeValidCtxt(vptr);
2090
2091    if (is_valid == 0) {
2092        RETURN_TRUE;
2093    } else {
2094        RETURN_FALSE;
2095    }
2096}
2097/* }}} */
2098
2099/* {{{ proto boolean dom_document_relaxNG_validate_file(string filename); */
2100PHP_FUNCTION(dom_document_relaxNG_validate_file)
2101{
2102    _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
2103}
2104/* }}} end dom_document_relaxNG_validate_file */
2105
2106/* {{{ proto boolean dom_document_relaxNG_validate_xml(string source); */
2107PHP_FUNCTION(dom_document_relaxNG_validate_xml)
2108{
2109    _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
2110}
2111/* }}} end dom_document_relaxNG_validate_xml */
2112
2113#endif
2114
2115#if defined(LIBXML_HTML_ENABLED)
2116
2117static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
2118{
2119    zval *id;
2120    xmlDoc *docp = NULL, *newdoc;
2121    dom_object *intern;
2122    dom_doc_propsptr doc_prop;
2123    char *source;
2124    int source_len, refcount, ret;
2125    long options = 0;
2126    htmlParserCtxtPtr ctxt;
2127
2128    id = getThis();
2129
2130    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &options) == FAILURE) {
2131        return;
2132    }
2133
2134    if (!source_len) {
2135        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string supplied as input");
2136        RETURN_FALSE;
2137    }
2138
2139    if (mode == DOM_LOAD_FILE) {
2140        if (CHECK_NULL_PATH(source, source_len)) {
2141            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid file source");
2142            RETURN_FALSE;
2143        }
2144        ctxt = htmlCreateFileParserCtxt(source, NULL);
2145    } else {
2146        source_len = xmlStrlen(source);
2147        ctxt = htmlCreateMemoryParserCtxt(source, source_len);
2148    }
2149
2150    if (!ctxt) {
2151        RETURN_FALSE;
2152    }
2153
2154    if (options) {
2155        htmlCtxtUseOptions(ctxt, options);
2156    }
2157
2158    ctxt->vctxt.error = php_libxml_ctx_error;
2159    ctxt->vctxt.warning = php_libxml_ctx_warning;
2160    if (ctxt->sax != NULL) {
2161        ctxt->sax->error = php_libxml_ctx_error;
2162        ctxt->sax->warning = php_libxml_ctx_warning;
2163    }
2164    htmlParseDocument(ctxt);
2165    newdoc = ctxt->myDoc;
2166    htmlFreeParserCtxt(ctxt);
2167
2168    if (!newdoc)
2169        RETURN_FALSE;
2170
2171    if (id != NULL && instanceof_function(Z_OBJCE_P(id), dom_document_class_entry TSRMLS_CC)) {
2172        intern = (dom_object *)zend_object_store_get_object(id TSRMLS_CC);
2173        if (intern != NULL) {
2174            docp = (xmlDocPtr) dom_object_get_node(intern);
2175            doc_prop = NULL;
2176            if (docp != NULL) {
2177                php_libxml_decrement_node_ptr((php_libxml_node_object *) intern TSRMLS_CC);
2178                doc_prop = intern->document->doc_props;
2179                intern->document->doc_props = NULL;
2180                refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern TSRMLS_CC);
2181                if (refcount != 0) {
2182                    docp->_private = NULL;
2183                }
2184            }
2185            intern->document = NULL;
2186            if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc TSRMLS_CC) == -1) {
2187                RETURN_FALSE;
2188            }
2189            intern->document->doc_props = doc_prop;
2190        }
2191
2192        php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern TSRMLS_CC);
2193
2194        RETURN_TRUE;
2195    } else {
2196        DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
2197    }
2198}
2199/* }}} */
2200
2201/* {{{ proto DOMNode dom_document_load_html_file(string source);
2202Since: DOM extended
2203*/
2204PHP_METHOD(domdocument, loadHTMLFile)
2205{
2206    dom_load_html(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
2207}
2208/* }}} end dom_document_load_html_file */
2209
2210/* {{{ proto DOMNode dom_document_load_html(string source);
2211Since: DOM extended
2212*/
2213PHP_METHOD(domdocument, loadHTML)
2214{
2215    dom_load_html(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
2216}
2217/* }}} end dom_document_load_html */
2218
2219/* {{{ proto int dom_document_save_html_file(string file);
2220Convenience method to save to file as html
2221*/
2222PHP_FUNCTION(dom_document_save_html_file)
2223{
2224    zval *id;
2225    xmlDoc *docp;
2226    int file_len, bytes, format;
2227    dom_object *intern;
2228    dom_doc_propsptr doc_props;
2229    char *file;
2230    const char *encoding;
2231
2232    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Op", &id, dom_document_class_entry, &file, &file_len) == FAILURE) {
2233        return;
2234    }
2235
2236    if (file_len == 0) {
2237        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Filename");
2238        RETURN_FALSE;
2239    }
2240
2241    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2242
2243
2244    encoding = (const char *) htmlGetMetaEncoding(docp);
2245
2246    doc_props = dom_get_doc_props(intern->document);
2247    format = doc_props->formatoutput;
2248    bytes = htmlSaveFileFormat(file, docp, encoding, format);
2249
2250    if (bytes == -1) {
2251        RETURN_FALSE;
2252    }
2253    RETURN_LONG(bytes);
2254}
2255/* }}} end dom_document_save_html_file */
2256
2257/* {{{ proto string dom_document_save_html();
2258Convenience method to output as html
2259*/
2260PHP_FUNCTION(dom_document_save_html)
2261{
2262    zval *id, *nodep = NULL;
2263    xmlDoc *docp;
2264    xmlNode *node;
2265    xmlBufferPtr buf;
2266    dom_object *intern, *nodeobj;
2267    xmlChar *mem = NULL;
2268    int size = 0, format;
2269    dom_doc_propsptr doc_props;
2270
2271    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
2272        "O|O!", &id, dom_document_class_entry, &nodep, dom_node_class_entry)
2273        == FAILURE) {
2274        return;
2275    }
2276
2277    DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2278
2279    doc_props = dom_get_doc_props(intern->document);
2280    format = doc_props->formatoutput;
2281
2282    if (nodep != NULL) {
2283        /* Dump contents of Node */
2284        DOM_GET_OBJ(node, nodep, xmlNodePtr, nodeobj);
2285        if (node->doc != docp) {
2286            php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
2287            RETURN_FALSE;
2288        }
2289
2290        buf = xmlBufferCreate();
2291        if (!buf) {
2292            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch buffer");
2293            RETURN_FALSE;
2294        }
2295
2296        if (node->type == XML_DOCUMENT_FRAG_NODE) {
2297            int one_size;
2298
2299            for (node = node->children; node; node = node->next) {
2300                one_size = htmlNodeDump(buf, docp, node);
2301
2302                if (one_size >= 0) {
2303                    size += one_size;
2304                } else {
2305                    size = -1;
2306                    break;
2307                }
2308            }
2309        } else {
2310            size = htmlNodeDump(buf, docp, node);
2311        }
2312        if (size >= 0) {
2313            mem = (xmlChar*) xmlBufferContent(buf);
2314            if (!mem) {
2315                RETVAL_FALSE;
2316            } else {
2317                RETVAL_STRINGL((const char*) mem, size, 1);
2318            }
2319        } else {
2320            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error dumping HTML node");
2321            RETVAL_FALSE;
2322        }
2323        xmlBufferFree(buf);
2324    } else {
2325#if LIBXML_VERSION >= 20623
2326        htmlDocDumpMemoryFormat(docp, &mem, &size, format);
2327#else
2328        htmlDocDumpMemory(docp, &mem, &size);
2329#endif
2330        if (!size) {
2331            RETVAL_FALSE;
2332        } else {
2333            RETVAL_STRINGL((const char*) mem, size, 1);
2334        }
2335        if (mem)
2336            xmlFree(mem);
2337    }
2338
2339}
2340/* }}} end dom_document_save_html */
2341
2342#endif  /* defined(LIBXML_HTML_ENABLED) */
2343
2344/* {{{ proto boolean DOMDocument::registerNodeClass(string baseclass, string extendedclass);
2345   Register extended class used to create base node type */
2346PHP_METHOD(domdocument, registerNodeClass)
2347{
2348    zval *id;
2349    xmlDoc *docp;
2350    char *baseclass = NULL, *extendedclass = NULL;
2351    int baseclass_len = 0, extendedclass_len = 0;
2352    zend_class_entry *basece = NULL, *ce = NULL;
2353    dom_object *intern;
2354
2355    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oss!", &id, dom_document_class_entry, &baseclass, &baseclass_len, &extendedclass, &extendedclass_len) == FAILURE) {
2356        return;
2357    }
2358
2359    if (baseclass_len) {
2360        zend_class_entry **pce;
2361        if (zend_lookup_class(baseclass, baseclass_len, &pce TSRMLS_CC) == FAILURE) {
2362            php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s does not exist", baseclass);
2363            return;
2364        }
2365        basece = *pce;
2366    }
2367
2368    if (basece == NULL || ! instanceof_function(basece, dom_node_class_entry TSRMLS_CC)) {
2369        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s is not derived from DOMNode.", baseclass);
2370        return;
2371    }
2372
2373    if (extendedclass_len) {
2374        zend_class_entry **pce;
2375        if (zend_lookup_class(extendedclass, extendedclass_len, &pce TSRMLS_CC) == FAILURE) {
2376            php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s does not exist", extendedclass);
2377        }
2378        ce = *pce;
2379    }
2380
2381    if (ce == NULL || instanceof_function(ce, basece TSRMLS_CC)) {
2382
2383        DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2384
2385        if (dom_set_doc_classmap(intern->document, basece, ce TSRMLS_CC) == FAILURE) {
2386            php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s could not be registered.", extendedclass);
2387        }
2388        RETURN_TRUE;
2389    } else {
2390        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Class %s is not derived from %s.", extendedclass, baseclass);
2391    }
2392
2393    RETURN_FALSE;
2394}
2395/* }}} */
2396
2397#endif  /* HAVE_LIBXML && HAVE_DOM */
2398
2399/*
2400 * Local variables:
2401 * tab-width: 4
2402 * c-basic-offset: 4
2403 * End:
2404 * vim600: noet sw=4 ts=4 fdm=marker
2405 * vim<600: noet sw=4 ts=4
2406 */
2407