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