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