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