php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
php_dom.c
Go to the documentation of this file.
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 | Marcus Borger <helly@php.net> |
16 +----------------------------------------------------------------------+
17*/
18
19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
23#include "php.h"
24#if defined(HAVE_LIBXML) && defined(HAVE_DOM)
25#include "zend_enum.h"
26#include "php_dom.h"
27#include "nodelist.h"
28#include "html_collection.h"
29#include "namespace_compat.h"
30#include "private_data.h"
31#include "internal_helpers.h"
32#include "php_dom_arginfo.h"
33#include "dom_properties.h"
34#include "token_list.h"
35#include "zend_interfaces.h"
38
39#include "ext/standard/info.h"
40
41/* {{{ class entries */
87#ifdef LIBXML_XPATH_ENABLED
88PHP_DOM_EXPORT zend_class_entry *dom_xpath_class_entry;
89PHP_DOM_EXPORT zend_class_entry *dom_modern_xpath_class_entry;
90#endif
94/* }}} */
95
96static zend_object_handlers dom_object_handlers;
97static zend_object_handlers dom_nnodemap_object_handlers;
98static zend_object_handlers dom_nodelist_object_handlers;
99static zend_object_handlers dom_modern_nnodemap_object_handlers;
100static zend_object_handlers dom_modern_nodelist_object_handlers;
101static zend_object_handlers dom_html_collection_object_handlers;
102static zend_object_handlers dom_object_namespace_node_handlers;
103static zend_object_handlers dom_modern_domimplementation_object_handlers;
104static zend_object_handlers dom_token_list_object_handlers;
105#ifdef LIBXML_XPATH_ENABLED
106zend_object_handlers dom_xpath_object_handlers;
107#endif
108
109static HashTable classes;
110/* {{{ prop handler tables */
111static HashTable dom_document_prop_handlers;
112static HashTable dom_xml_document_prop_handlers;
113static HashTable dom_abstract_base_document_prop_handlers;
114static HashTable dom_documentfragment_prop_handlers;
115static HashTable dom_modern_documentfragment_prop_handlers;
116static HashTable dom_node_prop_handlers;
117static HashTable dom_modern_node_prop_handlers;
118static HashTable dom_entity_reference_prop_handlers;
119static HashTable dom_modern_entity_reference_prop_handlers;
120static HashTable dom_nodelist_prop_handlers;
121static HashTable dom_namednodemap_prop_handlers;
122static HashTable dom_characterdata_prop_handlers;
123static HashTable dom_modern_characterdata_prop_handlers;
124static HashTable dom_attr_prop_handlers;
125static HashTable dom_modern_attr_prop_handlers;
126static HashTable dom_element_prop_handlers;
127static HashTable dom_modern_element_prop_handlers;
128static HashTable dom_modern_element_prop_handlers;
129static HashTable dom_text_prop_handlers;
130static HashTable dom_modern_text_prop_handlers;
131static HashTable dom_documenttype_prop_handlers;
132static HashTable dom_modern_documenttype_prop_handlers;
133static HashTable dom_notation_prop_handlers;
134static HashTable dom_modern_notation_prop_handlers;
135static HashTable dom_entity_prop_handlers;
136static HashTable dom_modern_entity_prop_handlers;
137static HashTable dom_processinginstruction_prop_handlers;
138static HashTable dom_modern_processinginstruction_prop_handlers;
139static HashTable dom_namespace_node_prop_handlers;
140static HashTable dom_token_list_prop_handlers;
141#ifdef LIBXML_XPATH_ENABLED
142static HashTable dom_xpath_prop_handlers;
143#endif
144/* }}} */
145
146static zend_object *dom_objects_namespace_node_new(zend_class_entry *class_type);
147static void dom_object_namespace_node_free_storage(zend_object *object);
148static xmlNodePtr php_dom_create_fake_namespace_decl_node_ptr(xmlNodePtr nodep, xmlNsPtr original);
149
150typedef zend_result (*dom_read_t)(dom_object *obj, zval *retval);
151typedef zend_result (*dom_write_t)(dom_object *obj, zval *newval);
152
153typedef struct dom_prop_handler {
154 dom_read_t read_func;
155 dom_write_t write_func;
156} dom_prop_handler;
157
158int dom_node_is_read_only(const xmlNode *node) {
159 switch (node->type) {
161 case XML_ENTITY_NODE:
164 case XML_DTD_NODE:
165 case XML_ELEMENT_DECL:
166 case XML_ATTRIBUTE_DECL:
167 case XML_ENTITY_DECL:
168 case XML_NAMESPACE_DECL:
169 return SUCCESS;
170 break;
171 default:
172 if (node->doc == NULL) {
173 return SUCCESS;
174 } else {
175 return FAILURE;
176 }
177 }
178}
179
180bool dom_node_children_valid(const xmlNode *node) {
181 switch (node->type) {
183 case XML_DTD_NODE:
184 case XML_PI_NODE:
185 case XML_COMMENT_NODE:
186 case XML_TEXT_NODE:
189 return false;
190 default:
191 return true;
192 }
193}
194
195static const libxml_doc_props default_doc_props = {
196 .formatoutput = false,
197 .validateonparse = false,
198 .resolveexternals = false,
199 .preservewhitespace = true,
200 .substituteentities = false,
201 .stricterror = true,
202 .recover = false,
203 .classmap = NULL,
204};
205
207
208static PHP_GINIT_FUNCTION(dom)
209{
210#if defined(COMPILE_DL_DOM) && defined(ZTS)
212#endif
213 dom_globals->suppress_warnings = false;
214}
215
216/* {{{ dom_get_doc_props() */
217dom_doc_propsptr dom_get_doc_props(php_libxml_ref_obj *document)
218{
219 dom_doc_propsptr doc_props;
220
221 if (document && document->doc_props) {
222 return document->doc_props;
223 } else {
224 doc_props = emalloc(sizeof(libxml_doc_props));
225 memcpy(doc_props, &default_doc_props, sizeof(libxml_doc_props));
226 if (document) {
227 document->doc_props = doc_props;
228 }
229 return doc_props;
230 }
231}
232/* }}} */
233
234libxml_doc_props const* dom_get_doc_props_read_only(const php_libxml_ref_obj *document)
235{
236 if (document && document->doc_props) {
237 return document->doc_props;
238 } else {
239 return &default_doc_props;
240 }
241}
242
243static void dom_copy_document_ref(php_libxml_ref_obj *source_doc, php_libxml_ref_obj *dest_doc)
244{
245 dom_doc_propsptr dest;
246
247 if (source_doc && dest_doc) {
248
249 libxml_doc_props const* source = dom_get_doc_props_read_only(source_doc);
250 dest = dom_get_doc_props(dest_doc);
251
252 dest->formatoutput = source->formatoutput;
253 dest->validateonparse = source->validateonparse;
254 dest->resolveexternals = source->resolveexternals;
255 dest->preservewhitespace = source->preservewhitespace;
256 dest->substituteentities = source->substituteentities;
257 dest->stricterror = source->stricterror;
258 dest->recover = source->recover;
259 if (source->classmap) {
260 ALLOC_HASHTABLE(dest->classmap);
261 zend_hash_init(dest->classmap, 0, NULL, NULL, false);
262 zend_hash_copy(dest->classmap, source->classmap, NULL);
263 }
264
265 dest_doc->class_type = source_doc->class_type;
266 dest_doc->handlers = source_doc->handlers;
267 }
268}
269
270void dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce)
271{
272 dom_doc_propsptr doc_props;
273
274 if (document) {
275 doc_props = dom_get_doc_props(document);
276 if (doc_props->classmap == NULL) {
277 if (ce == NULL) {
278 return;
279 }
280 ALLOC_HASHTABLE(doc_props->classmap);
281 zend_hash_init(doc_props->classmap, 0, NULL, NULL, false);
282 }
283 if (ce) {
284 zend_hash_update_ptr(doc_props->classmap, basece->name, ce);
285 } else {
286 zend_hash_del(doc_props->classmap, basece->name);
287 }
288 }
289}
290
291zend_class_entry *dom_get_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece)
292{
293 if (document) {
294 libxml_doc_props const* doc_props = dom_get_doc_props_read_only(document);
295 if (doc_props->classmap) {
296 zend_class_entry *ce = zend_hash_find_ptr(doc_props->classmap, basece->name);
297 if (ce) {
298 return ce;
299 }
300 }
301 }
302
303 return basece;
304}
305/* }}} */
306
307/* {{{ dom_get_strict_error() */
308bool dom_get_strict_error(php_libxml_ref_obj *document) {
309 return dom_get_doc_props_read_only(document)->stricterror;
310}
311/* }}} */
312
313/* {{{ xmlNodePtr dom_object_get_node(dom_object *obj) */
315{
316 if (obj && obj->ptr != NULL) {
317 return ((php_libxml_node_ptr *)obj->ptr)->node;
318 } else {
319 return NULL;
320 }
321}
322/* }}} end dom_object_get_node */
323
324/* {{{ dom_object *php_dom_object_get_data(xmlNodePtr obj) */
326{
327 if (obj && obj->_private != NULL) {
328 return (dom_object *) ((php_libxml_node_ptr *) obj->_private)->_private;
329 } else {
330 return NULL;
331 }
332}
333/* }}} end php_dom_object_get_data */
334
335static void dom_register_prop_handler(HashTable *prop_handler, const char *name, size_t name_len, const dom_prop_handler *hnd)
336{
337 zend_string *str = zend_string_init_interned(name, name_len, true);
338 zend_hash_add_new_ptr(prop_handler, str, (void *) hnd);
339 zend_string_release_ex(str, true);
340}
341
342static void dom_overwrite_prop_handler(HashTable *prop_handler, const char *name, size_t name_len, const dom_prop_handler *hnd)
343{
344 zend_hash_str_update_ptr(prop_handler, name, name_len, (void *) hnd);
345}
346
347#define DOM_REGISTER_PROP_HANDLER(prop_handler, name, prop_read_func, prop_write_func) do { \
348 static const dom_prop_handler hnd = {.read_func = prop_read_func, .write_func = prop_write_func}; \
349 dom_register_prop_handler(prop_handler, "" name, sizeof("" name) - 1, &hnd); \
350 } while (0)
351
352#define DOM_OVERWRITE_PROP_HANDLER(prop_handler, name, prop_read_func, prop_write_func) do { \
353 static const dom_prop_handler hnd = {.read_func = prop_read_func, .write_func = prop_write_func}; \
354 dom_overwrite_prop_handler(prop_handler, "" name, sizeof("" name) - 1, &hnd); \
355 } while (0)
356
357static zval *dom_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot)
358{
359 dom_object *obj = php_dom_obj_from_obj(object);
360
361 if (!obj->prop_handler || !zend_hash_exists(obj->prop_handler, name)) {
362 return zend_std_get_property_ptr_ptr(object, name, type, cache_slot);
363 }
364
365 if (cache_slot) {
366 cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
367 }
368 return NULL;
369}
370
371static zend_always_inline const dom_prop_handler *dom_get_prop_handler(const dom_object *obj, zend_string *name, void **cache_slot)
372{
373 const dom_prop_handler *hnd = NULL;
374
375 if (obj->prop_handler != NULL) {
376 if (cache_slot && *cache_slot == obj->prop_handler) {
377 hnd = cache_slot[1];
378 }
379 if (!hnd) {
380 hnd = zend_hash_find_ptr(obj->prop_handler, name);
381 if (cache_slot) {
382 cache_slot[0] = obj->prop_handler;
383 cache_slot[1] = (void *) hnd;
384 cache_slot[2] = NULL;
385 }
386 }
387 }
388
389 return hnd;
390}
391
392/* {{{ dom_read_property */
393zval *dom_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
394{
395 dom_object *obj = php_dom_obj_from_obj(object);
396 zval *retval;
397 const dom_prop_handler *hnd = dom_get_prop_handler(obj, name, cache_slot);
398
399 if (hnd) {
400 int ret = hnd->read_func(obj, rv);
401 if (ret == SUCCESS) {
402 retval = rv;
403 } else {
404 retval = &EG(uninitialized_zval);
405 }
406 } else {
407 retval = zend_std_read_property(object, name, type, cache_slot, rv);
408 }
409
410 return retval;
411}
412/* }}} */
413
414zval *dom_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
415{
416 dom_object *obj = php_dom_obj_from_obj(object);
417 const dom_prop_handler *hnd = dom_get_prop_handler(obj, name, cache_slot);
418
419 if (hnd) {
420 if (UNEXPECTED(!hnd->write_func)) {
422 return &EG(error_zval);
423 }
424
425 zend_property_info *prop = NULL;
426 if (cache_slot) {
427 ZEND_ASSERT(*cache_slot == obj->prop_handler);
428 prop = *(cache_slot + 2);
429 }
430 if (!prop) {
431 prop = zend_get_property_info(object->ce, name, /* silent */ true);
432 if (cache_slot) {
433 *(cache_slot + 2) = prop;
434 }
435 }
436
437 ZEND_ASSERT(prop && ZEND_TYPE_IS_SET(prop->type));
438 zval tmp;
439 ZVAL_COPY(&tmp, value);
440 if (!zend_verify_property_type(prop, &tmp, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)))) {
441 zval_ptr_dtor(&tmp);
442 return &EG(error_zval);
443 }
444 hnd->write_func(obj, &tmp);
445 zval_ptr_dtor(&tmp);
446
447 return value;
448 }
449
450 return zend_std_write_property(object, name, value, cache_slot);
451}
452
453// todo: make dom_property_exists return bool as well
454/* {{{ dom_property_exists */
455static int dom_property_exists(zend_object *object, zend_string *name, int check_empty, void **cache_slot)
456{
457 dom_object *obj = php_dom_obj_from_obj(object);
458 bool retval = false;
459 const dom_prop_handler *hnd = dom_get_prop_handler(obj, name, cache_slot);
460
461 if (hnd) {
462 zval tmp;
463
464 if (check_empty == 2) {
465 retval = true;
466 } else if (hnd->read_func(obj, &tmp) == SUCCESS) {
467 if (check_empty == 1) {
468 retval = zend_is_true(&tmp);
469 } else if (check_empty == 0) {
470 retval = (Z_TYPE(tmp) != IS_NULL);
471 }
472 zval_ptr_dtor(&tmp);
473 }
474 } else {
475 retval = zend_std_has_property(object, name, check_empty, cache_slot);
476 }
477
478 return retval;
479}
480/* }}} */
481
482static void dom_unset_property(zend_object *object, zend_string *member, void **cache_slot)
483{
484 dom_object *obj = php_dom_obj_from_obj(object);
485
486 if (obj->prop_handler != NULL && zend_hash_exists(obj->prop_handler, member)) {
487 zend_throw_error(NULL, "Cannot unset %s::$%s", ZSTR_VAL(object->ce->name), ZSTR_VAL(member));
488 return;
489 }
490
491 zend_std_unset_property(object, member, cache_slot);
492}
493
494static HashTable* dom_get_debug_info_helper(zend_object *object, int *is_temp) /* {{{ */
495{
496 dom_object *obj = php_dom_obj_from_obj(object);
497 HashTable *debug_info,
498 *prop_handlers = obj->prop_handler,
499 *std_props;
500 zend_string *string_key;
501 dom_prop_handler *entry;
502 zend_string *object_str;
503
504 *is_temp = 1;
505
506 std_props = zend_std_get_properties(object);
507 debug_info = zend_array_dup(std_props);
508
509 if (!prop_handlers) {
510 return debug_info;
511 }
512
513 DOM_G(suppress_warnings) = true;
514
515 object_str = ZSTR_INIT_LITERAL("(object value omitted)", false);
516
517 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(prop_handlers, string_key, entry) {
518 zval value;
519
520 ZEND_ASSERT(string_key != NULL);
521
522 if (entry->read_func(obj, &value) == FAILURE) {
523 continue;
524 }
525
526 if (Z_TYPE(value) == IS_OBJECT) {
528 ZVAL_NEW_STR(&value, object_str);
529 zend_string_addref(object_str);
530 }
531
532 zend_hash_update(debug_info, string_key, &value);
534
535 zend_string_release_ex(object_str, false);
536
537 DOM_G(suppress_warnings) = false;
538
539 return debug_info;
540}
541/* }}} */
542
543static HashTable* dom_get_debug_info(zend_object *object, int *is_temp) /* {{{ */
544{
545 return dom_get_debug_info_helper(object, is_temp);
546}
547/* }}} */
548
549void *php_dom_export_node(zval *object) /* {{{ */
550{
551 php_libxml_node_object *intern;
552 xmlNodePtr nodep = NULL;
553
554 intern = (php_libxml_node_object *) Z_DOMOBJ_P(object);
555 if (intern->node) {
556 nodep = intern->node->node;
557 }
558
559 return nodep;
560}
561/* }}} */
562
563/* {{{ Get a simplexml_element object from dom to allow for processing */
564static void dom_import_simplexml_common(INTERNAL_FUNCTION_PARAMETERS, php_libxml_class_type new_class)
565{
566 zval *node;
567 xmlNodePtr nodep = NULL;
568 php_libxml_node_object *nodeobj;
569
570 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &node) == FAILURE) {
572 }
573
574 nodeobj = (php_libxml_node_object *) ((char *) Z_OBJ_P(node) - Z_OBJ_HT_P(node)->offset);
575 nodep = php_libxml_import_node(node);
576
577 if (nodep && nodeobj && nodeobj->document && (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE)) {
578 php_libxml_class_type old_class_type = nodeobj->document->class_type;
579 if (old_class_type != PHP_LIBXML_CLASS_UNSET && old_class_type != new_class) {
580 if (new_class == PHP_LIBXML_CLASS_MODERN) {
581 zend_argument_type_error(1, "must not be already imported as a DOMNode");
582 } else {
583 zend_argument_type_error(1, "must not be already imported as a Dom\\Node");
584 }
586 }
587
588 /* Lock the node class type to prevent creating multiple representations of the same node. */
589 nodeobj->document->class_type = new_class;
590
591 if (old_class_type != PHP_LIBXML_CLASS_MODERN && new_class == PHP_LIBXML_CLASS_MODERN && nodep->doc != NULL) {
592 dom_document_convert_to_modern(nodeobj->document, nodep->doc);
593 }
594
595 DOM_RET_OBJ((xmlNodePtr) nodep, (dom_object *)nodeobj);
596 } else {
597 zend_argument_type_error(1, "is not a valid node type");
599 }
600}
601
603{
604 dom_import_simplexml_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LIBXML_CLASS_LEGACY);
605}
606
607PHP_FUNCTION(Dom_import_simplexml)
608{
609 dom_import_simplexml_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LIBXML_CLASS_MODERN);
610}
611/* }}} */
612
613static dom_object* dom_objects_set_class(zend_class_entry *class_type);
614
615void php_dom_update_document_after_clone(dom_object *original, xmlNodePtr original_node, dom_object *clone, xmlNodePtr cloned_node)
616{
617 dom_copy_document_ref(original->document, clone->document);
618 /* Workaround libxml2 bug, see https://gitlab.gnome.org/GNOME/libxml2/-/commit/07920b4381873187c02df53fa9b5d44aff3a7041 */
619#if LIBXML_VERSION < 20911
620 if (original_node->type == XML_HTML_DOCUMENT_NODE) {
621 cloned_node->type = XML_HTML_DOCUMENT_NODE;
622 }
623#endif
624}
625
626static void dom_update_refcount_after_clone(dom_object *original, xmlNodePtr original_node, dom_object *clone, xmlNodePtr cloned_node)
627{
628 /* If we cloned a document then we must create new doc proxy */
629 if (cloned_node->doc == original_node->doc) {
630 clone->document = original->document;
631 }
632 php_libxml_increment_doc_ref((php_libxml_node_object *)clone, cloned_node->doc);
633 php_libxml_increment_node_ptr((php_libxml_node_object *)clone, cloned_node, (void *)clone);
634 if (original->document != clone->document) {
635 php_dom_update_document_after_clone(original, original_node, clone, cloned_node);
636 }
637}
638
639static zend_object *dom_objects_store_clone_obj(zend_object *zobject) /* {{{ */
640{
641 dom_object *intern = php_dom_obj_from_obj(zobject);
642 dom_object *clone = dom_objects_set_class(intern->std.ce);
643
644 if (instanceof_function(intern->std.ce, dom_node_class_entry) || instanceof_function(intern->std.ce, dom_modern_node_class_entry)) {
645 xmlNodePtr node = (xmlNodePtr)dom_object_get_node(intern);
646 if (node != NULL) {
647 php_dom_private_data *private_data = NULL;
648 if (php_dom_follow_spec_intern(intern)) {
649 if (node->type == XML_DOCUMENT_NODE || node->type == XML_HTML_DOCUMENT_NODE) {
650 private_data = php_dom_private_data_create();
651 } else {
652 private_data = php_dom_get_private_data(intern);
653 }
654 }
655
656 xmlNodePtr cloned_node = dom_clone_node(php_dom_ns_mapper_from_private(private_data), node, node->doc, true);
657 if (cloned_node != NULL) {
658 dom_update_refcount_after_clone(intern, node, clone, cloned_node);
659 }
660 if (private_data != NULL) {
661 clone->document->private_data = php_dom_libxml_private_data_header(private_data);
662 }
663 }
664 }
665
666 zend_objects_clone_members(&clone->std, &intern->std);
667
668 return &clone->std;
669}
670/* }}} */
671
672static zend_object *dom_object_namespace_node_clone_obj(zend_object *zobject)
673{
674 dom_object_namespace_node *intern = php_dom_namespace_node_obj_from_obj(zobject);
675 zend_object *clone = dom_objects_namespace_node_new(intern->dom.std.ce);
676 dom_object_namespace_node *clone_intern = php_dom_namespace_node_obj_from_obj(clone);
677
678 xmlNodePtr original_node = dom_object_get_node(&intern->dom);
679 ZEND_ASSERT(original_node->type == XML_NAMESPACE_DECL);
680 xmlNodePtr cloned_node = php_dom_create_fake_namespace_decl_node_ptr(original_node->parent, original_node->ns);
681
682 if (intern->parent_intern) {
683 clone_intern->parent_intern = intern->parent_intern;
684 GC_ADDREF(&clone_intern->parent_intern->std);
685 }
686 dom_update_refcount_after_clone(&intern->dom, original_node, &clone_intern->dom, cloned_node);
687
688 zend_objects_clone_members(clone, &intern->dom.std);
689 return clone;
690}
691
692static zend_object *dom_token_list_new(zend_class_entry *class_type)
693{
694 dom_token_list_object *intern = zend_object_alloc(sizeof(*intern), class_type);
695
696 intern->dom.prop_handler = &dom_token_list_prop_handlers;
697
698 zend_object_std_init(&intern->dom.std, class_type);
699 object_properties_init(&intern->dom.std, class_type);
700
701 return &intern->dom.std;
702}
703
704static const zend_module_dep dom_deps[] = {
705 ZEND_MOD_REQUIRED("libxml")
706 ZEND_MOD_CONFLICTS("domxml")
708};
709
712 dom_deps,
713 "dom",
714 ext_functions,
715 PHP_MINIT(dom),
716 PHP_MSHUTDOWN(dom),
717 NULL,
718 NULL,
719 PHP_MINFO(dom),
720 DOM_API_VERSION, /* Extension versionnumber */
722 PHP_GINIT(dom),
723 NULL,
724 NULL,
726};
727/* }}} */
728
729#ifdef COMPILE_DL_DOM
731#endif
732
733void dom_nnodemap_objects_free_storage(zend_object *object);
734static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int type, zval *rv);
735static int dom_nodelist_has_dimension(zend_object *object, zval *member, int check_empty);
736static zval *dom_nodemap_read_dimension(zend_object *object, zval *offset, int type, zval *rv);
737static int dom_nodemap_has_dimension(zend_object *object, zval *member, int check_empty);
738static zval *dom_modern_nodemap_read_dimension(zend_object *object, zval *offset, int type, zval *rv);
739static int dom_modern_nodemap_has_dimension(zend_object *object, zval *member, int check_empty);
740
741#ifdef LIBXML_XPATH_ENABLED
742void dom_xpath_objects_free_storage(zend_object *object);
743HashTable *dom_xpath_get_gc(zend_object *object, zval **table, int *n);
744#endif
745
746static void *dom_malloc(size_t size) {
747 return emalloc(size);
748}
749
750static void *dom_realloc(void *dst, size_t size) {
751 return erealloc(dst, size);
752}
753
754static void *dom_calloc(size_t num, size_t size) {
755 return ecalloc(num, size);
756}
757
758static void dom_free(void *ptr) {
759 efree(ptr);
760}
761
762/* {{{ PHP_MINIT_FUNCTION(dom) */
764{
765 memcpy(&dom_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
766 dom_object_handlers.offset = XtOffsetOf(dom_object, std);
767 dom_object_handlers.free_obj = dom_objects_free_storage;
768 dom_object_handlers.read_property = dom_read_property;
769 dom_object_handlers.write_property = dom_write_property;
770 dom_object_handlers.get_property_ptr_ptr = dom_get_property_ptr_ptr;
771 dom_object_handlers.unset_property = dom_unset_property;
772 dom_object_handlers.clone_obj = dom_objects_store_clone_obj;
773 dom_object_handlers.has_property = dom_property_exists;
774 dom_object_handlers.get_debug_info = dom_get_debug_info;
775
776 memcpy(&dom_modern_domimplementation_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
777 /* The IDL has the [SameObject] constraint, which is incompatible with cloning because it imposes that there is only
778 * one instance per parent object. */
779 dom_modern_domimplementation_object_handlers.clone_obj = NULL;
780
781 memcpy(&dom_nnodemap_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
782 dom_nnodemap_object_handlers.free_obj = dom_nnodemap_objects_free_storage;
783 dom_nnodemap_object_handlers.read_dimension = dom_nodemap_read_dimension;
784 dom_nnodemap_object_handlers.has_dimension = dom_nodemap_has_dimension;
785
786 memcpy(&dom_nodelist_object_handlers, &dom_nnodemap_object_handlers, sizeof(zend_object_handlers));
787 dom_nodelist_object_handlers.read_dimension = dom_nodelist_read_dimension;
788 dom_nodelist_object_handlers.has_dimension = dom_nodelist_has_dimension;
789
790 memcpy(&dom_modern_nnodemap_object_handlers, &dom_nnodemap_object_handlers, sizeof(zend_object_handlers));
791 dom_modern_nnodemap_object_handlers.read_dimension = dom_modern_nodemap_read_dimension;
792 dom_modern_nnodemap_object_handlers.has_dimension = dom_modern_nodemap_has_dimension;
793
794 memcpy(&dom_modern_nodelist_object_handlers, &dom_nodelist_object_handlers, sizeof(zend_object_handlers));
795 dom_modern_nodelist_object_handlers.read_dimension = dom_modern_nodelist_read_dimension;
796 dom_modern_nodelist_object_handlers.has_dimension = dom_modern_nodelist_has_dimension;
797
798 memcpy(&dom_html_collection_object_handlers, &dom_modern_nodelist_object_handlers, sizeof(zend_object_handlers));
799 dom_html_collection_object_handlers.read_dimension = dom_html_collection_read_dimension;
800 dom_html_collection_object_handlers.has_dimension = dom_html_collection_has_dimension;
801
802 memcpy(&dom_object_namespace_node_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
803 dom_object_namespace_node_handlers.offset = XtOffsetOf(dom_object_namespace_node, dom.std);
804 dom_object_namespace_node_handlers.free_obj = dom_object_namespace_node_free_storage;
805 dom_object_namespace_node_handlers.clone_obj = dom_object_namespace_node_clone_obj;
806
807 memcpy(&dom_token_list_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
808 dom_token_list_object_handlers.offset = XtOffsetOf(dom_token_list_object, dom.std);
809 dom_token_list_object_handlers.free_obj = dom_token_list_free_obj;
810 /* The Web IDL (Web Interface Description Language - https://webidl.spec.whatwg.org) has the [SameObject] constraint
811 * for this object, which is incompatible with cloning because it imposes that there is only one instance
812 * per parent object. */
813 dom_token_list_object_handlers.clone_obj = NULL;
814 dom_token_list_object_handlers.read_dimension = dom_token_list_read_dimension;
815 dom_token_list_object_handlers.has_dimension = dom_token_list_has_dimension;
816
817 zend_hash_init(&classes, 0, NULL, NULL, true);
818
819 dom_adjacent_position_class_entry = register_class_Dom_AdjacentPosition();
820
821 dom_domexception_class_entry = register_class_DOMException(zend_ce_exception);
822
823 dom_parentnode_class_entry = register_class_DOMParentNode();
824 dom_modern_parentnode_class_entry = register_class_Dom_ParentNode();
825 dom_childnode_class_entry = register_class_DOMChildNode();
826 dom_modern_childnode_class_entry = register_class_Dom_ChildNode();
827
828 dom_domimplementation_class_entry = register_class_DOMImplementation();
830 dom_domimplementation_class_entry->default_object_handlers = &dom_object_handlers;
831
832 dom_modern_domimplementation_class_entry = register_class_Dom_Implementation();
834 dom_modern_domimplementation_class_entry->default_object_handlers = &dom_modern_domimplementation_object_handlers;
835
836 dom_node_class_entry = register_class_DOMNode();
837 dom_node_class_entry->create_object = dom_objects_new;
838 dom_node_class_entry->default_object_handlers = &dom_object_handlers;
839
840 zend_hash_init(&dom_node_prop_handlers, 0, NULL, NULL, true);
841 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "nodeName", dom_node_node_name_read, NULL);
842 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "nodeValue", dom_node_node_value_read, dom_node_node_value_write);
843 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "nodeType", dom_node_node_type_read, NULL);
844 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "parentNode", dom_node_parent_node_read, NULL);
845 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "parentElement", dom_node_parent_element_read, NULL);
846 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "childNodes", dom_node_child_nodes_read, NULL);
847 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "firstChild", dom_node_first_child_read, NULL);
848 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "lastChild", dom_node_last_child_read, NULL);
849 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "previousSibling", dom_node_previous_sibling_read, NULL);
850 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "nextSibling", dom_node_next_sibling_read, NULL);
851 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "attributes", dom_node_attributes_read, NULL);
852 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "isConnected", dom_node_is_connected_read, NULL);
853 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "ownerDocument", dom_node_owner_document_read, NULL);
854 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "namespaceURI", dom_node_namespace_uri_read, NULL);
855 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "prefix", dom_node_prefix_read, dom_node_prefix_write);
856 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "localName", dom_node_local_name_read, NULL);
857 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "baseURI", dom_node_base_uri_read, NULL);
858 DOM_REGISTER_PROP_HANDLER(&dom_node_prop_handlers, "textContent", dom_node_text_content_read, dom_node_text_content_write);
859 zend_hash_add_new_ptr(&classes, dom_node_class_entry->name, &dom_node_prop_handlers);
860
861 dom_modern_node_class_entry = register_class_Dom_Node();
863 dom_modern_node_class_entry->default_object_handlers = &dom_object_handlers;
864
865 zend_hash_init(&dom_modern_node_prop_handlers, 0, NULL, NULL, true);
866 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "nodeType", dom_node_node_type_read, NULL);
867 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "nodeName", dom_node_node_name_read, NULL);
868 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "baseURI", dom_node_base_uri_read, NULL);
869 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "isConnected", dom_node_is_connected_read, NULL);
870 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "ownerDocument", dom_node_owner_document_read, NULL);
871 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "parentNode", dom_node_parent_node_read, NULL);
872 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "parentElement", dom_node_parent_element_read, NULL);
873 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "childNodes", dom_node_child_nodes_read, NULL);
874 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "firstChild", dom_node_first_child_read, NULL);
875 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "lastChild", dom_node_last_child_read, NULL);
876 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "previousSibling", dom_node_previous_sibling_read, NULL);
877 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "nextSibling", dom_node_next_sibling_read, NULL);
878 /* We will set-up the setter for the derived classes afterwards on a class-by-class basis. */
879 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "nodeValue", dom_node_node_value_read, NULL);
880 DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "textContent", dom_node_text_content_read, NULL);
881 zend_hash_add_new_ptr(&classes, dom_modern_node_class_entry->name, &dom_modern_node_prop_handlers);
882
883 dom_namespace_node_class_entry = register_class_DOMNameSpaceNode();
884 dom_namespace_node_class_entry->create_object = dom_objects_namespace_node_new;
885 dom_namespace_node_class_entry->default_object_handlers = &dom_object_namespace_node_handlers;
886
887 zend_hash_init(&dom_namespace_node_prop_handlers, 0, NULL, NULL, true);
888 DOM_REGISTER_PROP_HANDLER(&dom_namespace_node_prop_handlers, "nodeName", dom_node_node_name_read, NULL);
889 DOM_REGISTER_PROP_HANDLER(&dom_namespace_node_prop_handlers, "nodeValue", dom_node_node_value_read, NULL);
890 DOM_REGISTER_PROP_HANDLER(&dom_namespace_node_prop_handlers, "nodeType", dom_node_node_type_read, NULL);
891 DOM_REGISTER_PROP_HANDLER(&dom_namespace_node_prop_handlers, "prefix", dom_node_prefix_read, NULL);
892 DOM_REGISTER_PROP_HANDLER(&dom_namespace_node_prop_handlers, "localName", dom_node_local_name_read, NULL);
893 DOM_REGISTER_PROP_HANDLER(&dom_namespace_node_prop_handlers, "namespaceURI", dom_node_namespace_uri_read, NULL);
894 DOM_REGISTER_PROP_HANDLER(&dom_namespace_node_prop_handlers, "isConnected", dom_node_is_connected_read, NULL);
895 DOM_REGISTER_PROP_HANDLER(&dom_namespace_node_prop_handlers, "ownerDocument", dom_node_owner_document_read, NULL);
896 DOM_REGISTER_PROP_HANDLER(&dom_namespace_node_prop_handlers, "parentNode", dom_node_parent_node_read, NULL);
897 DOM_REGISTER_PROP_HANDLER(&dom_namespace_node_prop_handlers, "parentElement", dom_node_parent_element_read, NULL);
898 zend_hash_add_new_ptr(&classes, dom_namespace_node_class_entry->name, &dom_namespace_node_prop_handlers);
899
900 dom_namespace_info_class_entry = register_class_Dom_NamespaceInfo();
901
904 dom_documentfragment_class_entry->default_object_handlers = &dom_object_handlers;
905 zend_hash_init(&dom_documentfragment_prop_handlers, 0, NULL, NULL, true);
906
907 DOM_REGISTER_PROP_HANDLER(&dom_documentfragment_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL);
908 DOM_REGISTER_PROP_HANDLER(&dom_documentfragment_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL);
909 DOM_REGISTER_PROP_HANDLER(&dom_documentfragment_prop_handlers, "childElementCount", dom_parent_node_child_element_count, NULL);
910 zend_hash_merge(&dom_documentfragment_prop_handlers, &dom_node_prop_handlers, NULL, false);
911 zend_hash_add_new_ptr(&classes, dom_documentfragment_class_entry->name, &dom_documentfragment_prop_handlers);
912
915 dom_modern_documentfragment_class_entry->default_object_handlers = &dom_object_handlers;
916 zend_hash_init(&dom_modern_documentfragment_prop_handlers, 0, NULL, NULL, true);
917
918 DOM_REGISTER_PROP_HANDLER(&dom_modern_documentfragment_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL);
919 DOM_REGISTER_PROP_HANDLER(&dom_modern_documentfragment_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL);
920 DOM_REGISTER_PROP_HANDLER(&dom_modern_documentfragment_prop_handlers, "childElementCount", dom_parent_node_child_element_count, NULL);
921 zend_hash_merge(&dom_modern_documentfragment_prop_handlers, &dom_modern_node_prop_handlers, NULL, false);
922 DOM_OVERWRITE_PROP_HANDLER(&dom_modern_documentfragment_prop_handlers, "textContent", dom_node_text_content_read, dom_node_text_content_write);
923 zend_hash_add_new_ptr(&classes, dom_modern_documentfragment_class_entry->name, &dom_modern_documentfragment_prop_handlers);
924
926 dom_abstract_base_document_class_entry->default_object_handlers = &dom_object_handlers;
927 zend_hash_init(&dom_abstract_base_document_prop_handlers, 0, NULL, NULL, true);
928 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "implementation", dom_modern_document_implementation_read, NULL);
929 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "URL", dom_document_document_uri_read, dom_document_document_uri_write);
930 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "documentURI", dom_document_document_uri_read, dom_document_document_uri_write);
931 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "characterSet", dom_document_encoding_read, dom_html_document_encoding_write);
932 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "charset", dom_document_encoding_read, dom_html_document_encoding_write);
933 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "inputEncoding", dom_document_encoding_read, dom_html_document_encoding_write);
934 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "doctype", dom_document_doctype_read, NULL);
935 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "documentElement", dom_document_document_element_read, NULL);
936 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL);
937 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL);
938 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "childElementCount", dom_parent_node_child_element_count, NULL);
939 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "body", dom_html_document_body_read, dom_html_document_body_write);
940 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "head", dom_html_document_head_read, NULL);
941 DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "title", dom_html_document_title_read, dom_html_document_title_write);
942 zend_hash_merge(&dom_abstract_base_document_prop_handlers, &dom_modern_node_prop_handlers, NULL, false);
943 /* No need to register in &classes because this is an abstract class handler. */
944
947 dom_document_class_entry->default_object_handlers = &dom_object_handlers;
948 zend_hash_init(&dom_document_prop_handlers, 0, NULL, NULL, true);
949 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "doctype", dom_document_doctype_read, NULL);
950 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "implementation", dom_document_implementation_read, NULL);
951 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "documentElement", dom_document_document_element_read, NULL);
952 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "actualEncoding", dom_document_actual_encoding_read, NULL);
953 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "encoding", dom_document_encoding_read, dom_document_encoding_write);
954 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "xmlEncoding", dom_document_encoding_read, NULL);
955 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "standalone", dom_document_standalone_read, dom_document_standalone_write);
956 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "xmlStandalone", dom_document_standalone_read, dom_document_standalone_write);
957 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "version", dom_document_version_read, dom_document_version_write);
958 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "xmlVersion", dom_document_version_read, dom_document_version_write);
959 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "strictErrorChecking", dom_document_strict_error_checking_read, dom_document_strict_error_checking_write);
960 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "documentURI", dom_document_document_uri_read, dom_document_document_uri_write);
961 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "config", dom_document_config_read, NULL);
962 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "formatOutput", dom_document_format_output_read, dom_document_format_output_write);
963 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "validateOnParse", dom_document_validate_on_parse_read, dom_document_validate_on_parse_write);
964 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "resolveExternals", dom_document_resolve_externals_read, dom_document_resolve_externals_write);
965 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "preserveWhiteSpace", dom_document_preserve_whitespace_read, dom_document_preserve_whitespace_write);
966 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "recover", dom_document_recover_read, dom_document_recover_write);
967 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "substituteEntities", dom_document_substitue_entities_read, dom_document_substitue_entities_write);
968 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL);
969 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL);
970 DOM_REGISTER_PROP_HANDLER(&dom_document_prop_handlers, "childElementCount", dom_parent_node_child_element_count, NULL);
971
972 zend_hash_merge(&dom_document_prop_handlers, &dom_node_prop_handlers, NULL, false);
973 zend_hash_add_new_ptr(&classes, dom_document_class_entry->name, &dom_document_prop_handlers);
974
976 dom_html_document_class_entry->default_object_handlers = &dom_object_handlers;
977 zend_hash_add_new_ptr(&classes, dom_html_document_class_entry->name, &dom_abstract_base_document_prop_handlers);
978
980 dom_xml_document_class_entry->default_object_handlers = &dom_object_handlers;
981 zend_hash_init(&dom_xml_document_prop_handlers, 0, NULL, NULL, true);
982 DOM_REGISTER_PROP_HANDLER(&dom_xml_document_prop_handlers, "xmlEncoding", dom_document_encoding_read, NULL);
983 DOM_REGISTER_PROP_HANDLER(&dom_xml_document_prop_handlers, "xmlStandalone", dom_document_standalone_read, dom_document_standalone_write);
984 DOM_REGISTER_PROP_HANDLER(&dom_xml_document_prop_handlers, "xmlVersion", dom_document_version_read, dom_document_version_write);
985 DOM_REGISTER_PROP_HANDLER(&dom_xml_document_prop_handlers, "formatOutput", dom_document_format_output_read, dom_document_format_output_write);
986
987 zend_hash_merge(&dom_xml_document_prop_handlers, &dom_abstract_base_document_prop_handlers, NULL, false);
988 zend_hash_add_new_ptr(&classes, dom_xml_document_class_entry->name, &dom_xml_document_prop_handlers);
989
990 dom_nodelist_class_entry = register_class_DOMNodeList(zend_ce_aggregate, zend_ce_countable);
992 dom_nodelist_class_entry->default_object_handlers = &dom_nodelist_object_handlers;
994
995 zend_hash_init(&dom_nodelist_prop_handlers, 0, NULL, NULL, true);
996 DOM_REGISTER_PROP_HANDLER(&dom_nodelist_prop_handlers, "length", dom_nodelist_length_read, NULL);
997 zend_hash_add_new_ptr(&classes, dom_nodelist_class_entry->name, &dom_nodelist_prop_handlers);
998
1001 dom_modern_nodelist_class_entry->default_object_handlers = &dom_modern_nodelist_object_handlers;
1003
1004 zend_hash_add_new_ptr(&classes, dom_modern_nodelist_class_entry->name, &dom_nodelist_prop_handlers);
1005
1006 dom_namednodemap_class_entry = register_class_DOMNamedNodeMap(zend_ce_aggregate, zend_ce_countable);
1008 dom_namednodemap_class_entry->default_object_handlers = &dom_nnodemap_object_handlers;
1010
1011 zend_hash_init(&dom_namednodemap_prop_handlers, 0, NULL, NULL, true);
1012 DOM_REGISTER_PROP_HANDLER(&dom_namednodemap_prop_handlers, "length", dom_namednodemap_length_read, NULL);
1013 zend_hash_add_new_ptr(&classes, dom_namednodemap_class_entry->name, &dom_namednodemap_prop_handlers);
1014
1017 dom_modern_namednodemap_class_entry->default_object_handlers = &dom_modern_nnodemap_object_handlers;
1019
1020 zend_hash_add_new_ptr(&classes, dom_modern_namednodemap_class_entry->name, &dom_namednodemap_prop_handlers);
1021
1024 dom_modern_dtd_namednodemap_class_entry->default_object_handlers = &dom_modern_nnodemap_object_handlers;
1026
1027 zend_hash_add_new_ptr(&classes, dom_modern_dtd_namednodemap_class_entry->name, &dom_namednodemap_prop_handlers);
1028
1029 dom_html_collection_class_entry = register_class_Dom_HTMLCollection(zend_ce_aggregate, zend_ce_countable);
1031 dom_html_collection_class_entry->default_object_handlers = &dom_html_collection_object_handlers;
1033
1034 zend_hash_add_new_ptr(&classes, dom_html_collection_class_entry->name, &dom_nodelist_prop_handlers);
1035
1038 dom_characterdata_class_entry->default_object_handlers = &dom_object_handlers;
1039
1040 zend_hash_init(&dom_characterdata_prop_handlers, 0, NULL, NULL, true);
1041 DOM_REGISTER_PROP_HANDLER(&dom_characterdata_prop_handlers, "data", dom_characterdata_data_read, dom_characterdata_data_write);
1042 DOM_REGISTER_PROP_HANDLER(&dom_characterdata_prop_handlers, "length", dom_characterdata_length_read, NULL);
1043 DOM_REGISTER_PROP_HANDLER(&dom_characterdata_prop_handlers, "previousElementSibling", dom_node_previous_element_sibling_read, NULL);
1044 DOM_REGISTER_PROP_HANDLER(&dom_characterdata_prop_handlers, "nextElementSibling", dom_node_next_element_sibling_read, NULL);
1045 zend_hash_merge(&dom_characterdata_prop_handlers, &dom_node_prop_handlers, NULL, false);
1046 zend_hash_add_new_ptr(&classes, dom_characterdata_class_entry->name, &dom_characterdata_prop_handlers);
1047
1050 dom_modern_characterdata_class_entry->default_object_handlers = &dom_object_handlers;
1051
1052 zend_hash_init(&dom_modern_characterdata_prop_handlers, 0, NULL, NULL, true);
1053 DOM_REGISTER_PROP_HANDLER(&dom_modern_characterdata_prop_handlers, "data", dom_characterdata_data_read, dom_characterdata_data_write);
1054 DOM_REGISTER_PROP_HANDLER(&dom_modern_characterdata_prop_handlers, "length", dom_characterdata_length_read, NULL);
1055 DOM_REGISTER_PROP_HANDLER(&dom_modern_characterdata_prop_handlers, "previousElementSibling", dom_node_previous_element_sibling_read, NULL);
1056 DOM_REGISTER_PROP_HANDLER(&dom_modern_characterdata_prop_handlers, "nextElementSibling", dom_node_next_element_sibling_read, NULL);
1057 zend_hash_merge(&dom_modern_characterdata_prop_handlers, &dom_modern_node_prop_handlers, NULL, false);
1058 DOM_OVERWRITE_PROP_HANDLER(&dom_modern_characterdata_prop_handlers, "nodeValue", dom_node_node_value_read, dom_node_node_value_write);
1059 DOM_OVERWRITE_PROP_HANDLER(&dom_modern_characterdata_prop_handlers, "textContent", dom_node_text_content_read, dom_node_text_content_write);
1060 zend_hash_add_new_ptr(&classes, dom_modern_characterdata_class_entry->name, &dom_modern_characterdata_prop_handlers);
1061
1062 dom_attr_class_entry = register_class_DOMAttr(dom_node_class_entry);
1063 dom_attr_class_entry->create_object = dom_objects_new;
1064 dom_attr_class_entry->default_object_handlers = &dom_object_handlers;
1065
1066 zend_hash_init(&dom_attr_prop_handlers, 0, NULL, NULL, true);
1067 DOM_REGISTER_PROP_HANDLER(&dom_attr_prop_handlers, "name", dom_attr_name_read, NULL);
1068 DOM_REGISTER_PROP_HANDLER(&dom_attr_prop_handlers, "specified", dom_attr_specified_read, NULL);
1069 DOM_REGISTER_PROP_HANDLER(&dom_attr_prop_handlers, "value", dom_attr_value_read, dom_attr_value_write);
1070 DOM_REGISTER_PROP_HANDLER(&dom_attr_prop_handlers, "ownerElement", dom_attr_owner_element_read, NULL);
1071 DOM_REGISTER_PROP_HANDLER(&dom_attr_prop_handlers, "schemaTypeInfo", dom_attr_schema_type_info_read, NULL);
1072 zend_hash_merge(&dom_attr_prop_handlers, &dom_node_prop_handlers, NULL, false);
1073 zend_hash_add_new_ptr(&classes, dom_attr_class_entry->name, &dom_attr_prop_handlers);
1074
1077 dom_modern_attr_class_entry->default_object_handlers = &dom_object_handlers;
1078
1079 zend_hash_init(&dom_modern_attr_prop_handlers, 0, NULL, NULL, true);
1080 DOM_REGISTER_PROP_HANDLER(&dom_modern_attr_prop_handlers, "namespaceURI", dom_node_namespace_uri_read, NULL);
1081 DOM_REGISTER_PROP_HANDLER(&dom_modern_attr_prop_handlers, "prefix", dom_modern_node_prefix_read, NULL);
1082 DOM_REGISTER_PROP_HANDLER(&dom_modern_attr_prop_handlers, "localName", dom_node_local_name_read, NULL);
1083 DOM_REGISTER_PROP_HANDLER(&dom_modern_attr_prop_handlers, "name", dom_attr_name_read, NULL);
1084 DOM_REGISTER_PROP_HANDLER(&dom_modern_attr_prop_handlers, "value", dom_attr_value_read, dom_attr_value_write);
1085 DOM_REGISTER_PROP_HANDLER(&dom_modern_attr_prop_handlers, "ownerElement", dom_attr_owner_element_read, NULL);
1086 DOM_REGISTER_PROP_HANDLER(&dom_modern_attr_prop_handlers, "specified", dom_attr_specified_read, NULL);
1087 zend_hash_merge(&dom_modern_attr_prop_handlers, &dom_modern_node_prop_handlers, NULL, false);
1088 DOM_OVERWRITE_PROP_HANDLER(&dom_modern_attr_prop_handlers, "nodeValue", dom_node_node_value_read, dom_node_node_value_write);
1089 DOM_OVERWRITE_PROP_HANDLER(&dom_modern_attr_prop_handlers, "textContent", dom_node_text_content_read, dom_node_text_content_write);
1090 zend_hash_add_new_ptr(&classes, dom_modern_attr_class_entry->name, &dom_modern_attr_prop_handlers);
1091
1094 dom_element_class_entry->default_object_handlers = &dom_object_handlers;
1095
1096 zend_hash_init(&dom_element_prop_handlers, 0, NULL, NULL, true);
1097 DOM_REGISTER_PROP_HANDLER(&dom_element_prop_handlers, "tagName", dom_element_tag_name_read, NULL);
1098 DOM_REGISTER_PROP_HANDLER(&dom_element_prop_handlers, "className", dom_element_class_name_read, dom_element_class_name_write);
1099 DOM_REGISTER_PROP_HANDLER(&dom_element_prop_handlers, "id", dom_element_id_read, dom_element_id_write);
1100 DOM_REGISTER_PROP_HANDLER(&dom_element_prop_handlers, "schemaTypeInfo", dom_element_schema_type_info_read, NULL);
1101 DOM_REGISTER_PROP_HANDLER(&dom_element_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL);
1102 DOM_REGISTER_PROP_HANDLER(&dom_element_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL);
1103 DOM_REGISTER_PROP_HANDLER(&dom_element_prop_handlers, "childElementCount", dom_parent_node_child_element_count, NULL);
1104 DOM_REGISTER_PROP_HANDLER(&dom_element_prop_handlers, "previousElementSibling", dom_node_previous_element_sibling_read, NULL);
1105 DOM_REGISTER_PROP_HANDLER(&dom_element_prop_handlers, "nextElementSibling", dom_node_next_element_sibling_read, NULL);
1106 zend_hash_merge(&dom_element_prop_handlers, &dom_node_prop_handlers, NULL, false);
1107 zend_hash_add_new_ptr(&classes, dom_element_class_entry->name, &dom_element_prop_handlers);
1108
1111 dom_modern_element_class_entry->default_object_handlers = &dom_object_handlers;
1112
1113 zend_hash_init(&dom_modern_element_prop_handlers, 0, NULL, NULL, true);
1114 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "namespaceURI", dom_node_namespace_uri_read, NULL);
1115 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "prefix", dom_modern_node_prefix_read, NULL);
1116 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "localName", dom_node_local_name_read, NULL);
1117 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "tagName", dom_element_tag_name_read, NULL);
1118 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "id", dom_element_id_read, dom_element_id_write);
1119 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "className", dom_element_class_name_read, dom_element_class_name_write);
1120 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "classList", dom_element_class_list_read, NULL);
1121 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "attributes", dom_node_attributes_read, NULL);
1122 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL);
1123 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL);
1124 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "childElementCount", dom_parent_node_child_element_count, NULL);
1125 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "previousElementSibling", dom_node_previous_element_sibling_read, NULL);
1126 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "nextElementSibling", dom_node_next_element_sibling_read, NULL);
1127 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "innerHTML", dom_element_inner_html_read, dom_element_inner_html_write);
1128 DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "substitutedNodeValue", dom_modern_element_substituted_node_value_read, dom_modern_element_substituted_node_value_write);
1129 zend_hash_merge(&dom_modern_element_prop_handlers, &dom_modern_node_prop_handlers, NULL, false);
1130 DOM_OVERWRITE_PROP_HANDLER(&dom_modern_element_prop_handlers, "textContent", dom_node_text_content_read, dom_node_text_content_write);
1131 zend_hash_add_new_ptr(&classes, dom_modern_element_class_entry->name, &dom_modern_element_prop_handlers);
1132
1133 dom_html_element_class_entry = register_class_Dom_HTMLElement(dom_modern_element_class_entry);
1135 dom_html_element_class_entry->default_object_handlers = &dom_object_handlers;
1136 zend_hash_add_new_ptr(&classes, dom_html_element_class_entry->name, &dom_modern_element_prop_handlers);
1137
1138 dom_text_class_entry = register_class_DOMText(dom_characterdata_class_entry);
1139 dom_text_class_entry->create_object = dom_objects_new;
1140 dom_text_class_entry->default_object_handlers = &dom_object_handlers;
1141
1142 zend_hash_init(&dom_text_prop_handlers, 0, NULL, NULL, true);
1143 DOM_REGISTER_PROP_HANDLER(&dom_text_prop_handlers, "wholeText", dom_text_whole_text_read, NULL);
1144 zend_hash_merge(&dom_text_prop_handlers, &dom_characterdata_prop_handlers, NULL, false);
1145 zend_hash_add_new_ptr(&classes, dom_text_class_entry->name, &dom_text_prop_handlers);
1146
1149 dom_modern_text_class_entry->default_object_handlers = &dom_object_handlers;
1150
1151 zend_hash_init(&dom_modern_text_prop_handlers, 0, NULL, NULL, true);
1152 DOM_REGISTER_PROP_HANDLER(&dom_modern_text_prop_handlers, "wholeText", dom_text_whole_text_read, NULL);
1153 zend_hash_merge(&dom_modern_text_prop_handlers, &dom_modern_characterdata_prop_handlers, NULL, false);
1154 zend_hash_add_new_ptr(&classes, dom_modern_text_class_entry->name, &dom_modern_text_prop_handlers);
1155
1156 dom_comment_class_entry = register_class_DOMComment(dom_characterdata_class_entry);
1158 dom_comment_class_entry->default_object_handlers = &dom_object_handlers;
1159 zend_hash_add_new_ptr(&classes, dom_comment_class_entry->name, &dom_characterdata_prop_handlers);
1160
1163 dom_modern_comment_class_entry->default_object_handlers = &dom_object_handlers;
1164 zend_hash_add_new_ptr(&classes, dom_modern_comment_class_entry->name, &dom_modern_characterdata_prop_handlers);
1165
1166 dom_cdatasection_class_entry = register_class_DOMCdataSection(dom_text_class_entry);
1168 dom_cdatasection_class_entry->default_object_handlers = &dom_object_handlers;
1169 zend_hash_add_new_ptr(&classes, dom_cdatasection_class_entry->name, &dom_text_prop_handlers);
1170
1171 dom_modern_cdatasection_class_entry = register_class_Dom_CDATASection(dom_modern_text_class_entry);
1173 dom_modern_cdatasection_class_entry->default_object_handlers = &dom_object_handlers;
1174 zend_hash_add_new_ptr(&classes, dom_modern_cdatasection_class_entry->name, &dom_modern_text_prop_handlers);
1175
1176 dom_documenttype_class_entry = register_class_DOMDocumentType(dom_node_class_entry);
1178 dom_documenttype_class_entry->default_object_handlers = &dom_object_handlers;
1179
1180 zend_hash_init(&dom_documenttype_prop_handlers, 0, NULL, NULL, true);
1181 DOM_REGISTER_PROP_HANDLER(&dom_documenttype_prop_handlers, "name", dom_documenttype_name_read, NULL);
1182 DOM_REGISTER_PROP_HANDLER(&dom_documenttype_prop_handlers, "entities", dom_documenttype_entities_read, NULL);
1183 DOM_REGISTER_PROP_HANDLER(&dom_documenttype_prop_handlers, "notations", dom_documenttype_notations_read, NULL);
1184 DOM_REGISTER_PROP_HANDLER(&dom_documenttype_prop_handlers, "publicId", dom_documenttype_public_id_read, NULL);
1185 DOM_REGISTER_PROP_HANDLER(&dom_documenttype_prop_handlers, "systemId", dom_documenttype_system_id_read, NULL);
1186 DOM_REGISTER_PROP_HANDLER(&dom_documenttype_prop_handlers, "internalSubset", dom_documenttype_internal_subset_read, NULL);
1187 zend_hash_merge(&dom_documenttype_prop_handlers, &dom_node_prop_handlers, NULL, false);
1188 zend_hash_add_new_ptr(&classes, dom_documenttype_class_entry->name, &dom_documenttype_prop_handlers);
1189
1192 dom_modern_documenttype_class_entry->default_object_handlers = &dom_object_handlers;
1193
1194 zend_hash_init(&dom_modern_documenttype_prop_handlers, 0, NULL, NULL, true);
1195 DOM_REGISTER_PROP_HANDLER(&dom_modern_documenttype_prop_handlers, "name", dom_documenttype_name_read, NULL);
1196 DOM_REGISTER_PROP_HANDLER(&dom_modern_documenttype_prop_handlers, "entities", dom_documenttype_entities_read, NULL);
1197 DOM_REGISTER_PROP_HANDLER(&dom_modern_documenttype_prop_handlers, "notations", dom_documenttype_notations_read, NULL);
1198 DOM_REGISTER_PROP_HANDLER(&dom_modern_documenttype_prop_handlers, "publicId", dom_documenttype_public_id_read, NULL);
1199 DOM_REGISTER_PROP_HANDLER(&dom_modern_documenttype_prop_handlers, "systemId", dom_documenttype_system_id_read, NULL);
1200 DOM_REGISTER_PROP_HANDLER(&dom_modern_documenttype_prop_handlers, "internalSubset", dom_documenttype_internal_subset_read, NULL);
1201 zend_hash_merge(&dom_modern_documenttype_prop_handlers, &dom_modern_node_prop_handlers, NULL, false);
1202 zend_hash_add_new_ptr(&classes, dom_modern_documenttype_class_entry->name, &dom_modern_documenttype_prop_handlers);
1203
1204 dom_notation_class_entry = register_class_DOMNotation(dom_node_class_entry);
1206 dom_notation_class_entry->default_object_handlers = &dom_object_handlers;
1207
1208 zend_hash_init(&dom_notation_prop_handlers, 0, NULL, NULL, true);
1209 DOM_REGISTER_PROP_HANDLER(&dom_notation_prop_handlers, "publicId", dom_notation_public_id_read, NULL);
1210 DOM_REGISTER_PROP_HANDLER(&dom_notation_prop_handlers, "systemId", dom_notation_system_id_read, NULL);
1211 zend_hash_merge(&dom_notation_prop_handlers, &dom_node_prop_handlers, NULL, false);
1212 zend_hash_add_new_ptr(&classes, dom_notation_class_entry->name, &dom_notation_prop_handlers);
1213
1214 dom_modern_notation_class_entry = register_class_Dom_Notation(dom_modern_node_class_entry);
1216 dom_modern_notation_class_entry->default_object_handlers = &dom_object_handlers;
1217
1218 zend_hash_init(&dom_modern_notation_prop_handlers, 0, NULL, NULL, true);
1219 DOM_REGISTER_PROP_HANDLER(&dom_modern_notation_prop_handlers, "publicId", dom_notation_public_id_read, NULL);
1220 DOM_REGISTER_PROP_HANDLER(&dom_modern_notation_prop_handlers, "systemId", dom_notation_system_id_read, NULL);
1221 zend_hash_merge(&dom_modern_notation_prop_handlers, &dom_modern_node_prop_handlers, NULL, false);
1222 zend_hash_add_new_ptr(&classes, dom_modern_notation_class_entry->name, &dom_modern_node_prop_handlers);
1223
1224 dom_entity_class_entry = register_class_DOMEntity(dom_node_class_entry);
1225 dom_entity_class_entry->create_object = dom_objects_new;
1226 dom_entity_class_entry->default_object_handlers = &dom_object_handlers;
1227
1228 zend_hash_init(&dom_entity_prop_handlers, 0, NULL, NULL, true);
1229 DOM_REGISTER_PROP_HANDLER(&dom_entity_prop_handlers, "publicId", dom_entity_public_id_read, NULL);
1230 DOM_REGISTER_PROP_HANDLER(&dom_entity_prop_handlers, "systemId", dom_entity_system_id_read, NULL);
1231 DOM_REGISTER_PROP_HANDLER(&dom_entity_prop_handlers, "notationName", dom_entity_notation_name_read, NULL);
1232 DOM_REGISTER_PROP_HANDLER(&dom_entity_prop_handlers, "actualEncoding", dom_entity_actual_encoding_read, NULL);
1233 DOM_REGISTER_PROP_HANDLER(&dom_entity_prop_handlers, "encoding", dom_entity_encoding_read, NULL);
1234 DOM_REGISTER_PROP_HANDLER(&dom_entity_prop_handlers, "version", dom_entity_version_read, NULL);
1235 zend_hash_merge(&dom_entity_prop_handlers, &dom_node_prop_handlers, NULL, false);
1236 zend_hash_add_new_ptr(&classes, dom_entity_class_entry->name, &dom_entity_prop_handlers);
1237
1240 dom_modern_entity_class_entry->default_object_handlers = &dom_object_handlers;
1241
1242 zend_hash_init(&dom_modern_entity_prop_handlers, 0, NULL, NULL, true);
1243 DOM_REGISTER_PROP_HANDLER(&dom_modern_entity_prop_handlers, "publicId", dom_entity_public_id_read, NULL);
1244 DOM_REGISTER_PROP_HANDLER(&dom_modern_entity_prop_handlers, "systemId", dom_entity_system_id_read, NULL);
1245 DOM_REGISTER_PROP_HANDLER(&dom_modern_entity_prop_handlers, "notationName", dom_entity_notation_name_read, NULL);
1246 zend_hash_merge(&dom_modern_entity_prop_handlers, &dom_modern_node_prop_handlers, NULL, false);
1247 zend_hash_add_new_ptr(&classes, dom_modern_entity_class_entry->name, &dom_modern_entity_prop_handlers);
1248
1249 dom_entityreference_class_entry = register_class_DOMEntityReference(dom_node_class_entry);
1251 dom_entityreference_class_entry->default_object_handlers = &dom_object_handlers;
1252
1253 zend_hash_init(&dom_entity_reference_prop_handlers, 0, NULL, NULL, true);
1254 zend_hash_merge(&dom_entity_reference_prop_handlers, &dom_node_prop_handlers, NULL, false);
1255 DOM_OVERWRITE_PROP_HANDLER(&dom_entity_reference_prop_handlers, "firstChild", dom_entity_reference_child_read, NULL);
1256 DOM_OVERWRITE_PROP_HANDLER(&dom_entity_reference_prop_handlers, "lastChild", dom_entity_reference_child_read, NULL);
1257 DOM_OVERWRITE_PROP_HANDLER(&dom_entity_reference_prop_handlers, "textContent", dom_entity_reference_text_content_read, NULL);
1258 DOM_OVERWRITE_PROP_HANDLER(&dom_entity_reference_prop_handlers, "childNodes", dom_entity_reference_child_nodes_read, NULL);
1259 zend_hash_add_new_ptr(&classes, dom_entityreference_class_entry->name, &dom_entity_reference_prop_handlers);
1260
1261 dom_modern_entityreference_class_entry = register_class_Dom_EntityReference(dom_modern_node_class_entry);
1263 dom_modern_entityreference_class_entry->default_object_handlers = &dom_object_handlers;
1264
1265 zend_hash_init(&dom_modern_entity_reference_prop_handlers, 0, NULL, NULL, true);
1266 zend_hash_merge(&dom_modern_entity_reference_prop_handlers, &dom_modern_node_prop_handlers, NULL, false);
1267 DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "firstChild", dom_entity_reference_child_read, NULL);
1268 DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "lastChild", dom_entity_reference_child_read, NULL);
1269 DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "textContent", dom_entity_reference_text_content_read, NULL);
1270 DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "childNodes", dom_entity_reference_child_nodes_read, NULL);
1271 zend_hash_add_new_ptr(&classes, dom_modern_entityreference_class_entry->name, &dom_modern_entity_reference_prop_handlers);
1272
1273 dom_processinginstruction_class_entry = register_class_DOMProcessingInstruction(dom_node_class_entry);
1275 dom_processinginstruction_class_entry->default_object_handlers = &dom_object_handlers;
1276
1277 zend_hash_init(&dom_processinginstruction_prop_handlers, 0, NULL, NULL, true);
1278 DOM_REGISTER_PROP_HANDLER(&dom_processinginstruction_prop_handlers, "target", dom_processinginstruction_target_read, NULL);
1279 DOM_REGISTER_PROP_HANDLER(&dom_processinginstruction_prop_handlers, "data", dom_processinginstruction_data_read, dom_processinginstruction_data_write);
1280 zend_hash_merge(&dom_processinginstruction_prop_handlers, &dom_node_prop_handlers, NULL, false);
1281 zend_hash_add_new_ptr(&classes, dom_processinginstruction_class_entry->name, &dom_processinginstruction_prop_handlers);
1282
1285 dom_modern_processinginstruction_class_entry->default_object_handlers = &dom_object_handlers;
1286
1287 zend_hash_init(&dom_modern_processinginstruction_prop_handlers, 0, NULL, NULL, true);
1288 DOM_REGISTER_PROP_HANDLER(&dom_modern_processinginstruction_prop_handlers, "target", dom_processinginstruction_target_read, NULL);
1289 DOM_REGISTER_PROP_HANDLER(&dom_modern_processinginstruction_prop_handlers, "data", dom_processinginstruction_data_read, dom_processinginstruction_data_write);
1290 zend_hash_merge(&dom_modern_processinginstruction_prop_handlers, &dom_modern_characterdata_prop_handlers, NULL, false);
1291 zend_hash_add_new_ptr(&classes, dom_modern_processinginstruction_class_entry->name, &dom_modern_processinginstruction_prop_handlers);
1292
1293#ifdef LIBXML_XPATH_ENABLED
1294 memcpy(&dom_xpath_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
1295 dom_xpath_object_handlers.offset = XtOffsetOf(dom_xpath_object, dom) + XtOffsetOf(dom_object, std);
1296 dom_xpath_object_handlers.free_obj = dom_xpath_objects_free_storage;
1297 dom_xpath_object_handlers.get_gc = dom_xpath_get_gc;
1298 dom_xpath_object_handlers.clone_obj = NULL;
1299
1300 dom_xpath_class_entry = register_class_DOMXPath();
1301 dom_xpath_class_entry->create_object = dom_xpath_objects_new;
1302 dom_xpath_class_entry->default_object_handlers = &dom_xpath_object_handlers;
1303
1304 zend_hash_init(&dom_xpath_prop_handlers, 0, NULL, NULL, true);
1305 DOM_REGISTER_PROP_HANDLER(&dom_xpath_prop_handlers, "document", dom_xpath_document_read, NULL);
1306 DOM_REGISTER_PROP_HANDLER(&dom_xpath_prop_handlers, "registerNodeNamespaces", dom_xpath_register_node_ns_read, dom_xpath_register_node_ns_write);
1307 zend_hash_add_new_ptr(&classes, dom_xpath_class_entry->name, &dom_xpath_prop_handlers);
1308
1309 dom_modern_xpath_class_entry = register_class_Dom_XPath();
1310 dom_modern_xpath_class_entry->create_object = dom_xpath_objects_new;
1311 dom_modern_xpath_class_entry->default_object_handlers = &dom_xpath_object_handlers;
1312
1313 zend_hash_add_new_ptr(&classes, dom_modern_xpath_class_entry->name, &dom_xpath_prop_handlers);
1314#endif
1315
1316 dom_token_list_class_entry = register_class_Dom_TokenList(zend_ce_aggregate, zend_ce_countable);
1317 dom_token_list_class_entry->create_object = dom_token_list_new;
1318 dom_token_list_class_entry->default_object_handlers = &dom_token_list_object_handlers;
1320
1321 zend_hash_init(&dom_token_list_prop_handlers, 0, NULL, NULL, true);
1322 DOM_REGISTER_PROP_HANDLER(&dom_token_list_prop_handlers, "length", dom_token_list_length_read, NULL);
1323 DOM_REGISTER_PROP_HANDLER(&dom_token_list_prop_handlers, "value", dom_token_list_value_read, dom_token_list_value_write);
1324 zend_hash_add_new_ptr(&classes, dom_token_list_class_entry->name, &dom_token_list_prop_handlers);
1325
1326 register_php_dom_symbols(module_number);
1327
1328 php_libxml_register_export(dom_node_class_entry, php_dom_export_node);
1329 php_libxml_register_export(dom_modern_node_class_entry, php_dom_export_node);
1330
1331 lexbor_memory_setup(dom_malloc, dom_realloc, dom_calloc, dom_free);
1332
1333 return SUCCESS;
1334}
1335/* }}} */
1336
1337/* {{{ */
1339{
1341 php_info_print_table_row(2, "DOM/XML", "enabled");
1342 php_info_print_table_row(2, "DOM/XML API Version", DOM_API_VERSION);
1343 php_info_print_table_row(2, "libxml Version", LIBXML_DOTTED_VERSION);
1344#ifdef LIBXML_HTML_ENABLED
1345 php_info_print_table_row(2, "HTML Support", "enabled");
1346#endif
1347#ifdef LIBXML_XPATH_ENABLED
1348 php_info_print_table_row(2, "XPath Support", "enabled");
1349#endif
1350#ifdef LIBXML_XPTR_ENABLED
1351 php_info_print_table_row(2, "XPointer Support", "enabled");
1352#endif
1353#ifdef LIBXML_SCHEMAS_ENABLED
1354 php_info_print_table_row(2, "Schema Support", "enabled");
1355 php_info_print_table_row(2, "RelaxNG Support", "enabled");
1356#endif
1358}
1359/* }}} */
1360
1361PHP_MSHUTDOWN_FUNCTION(dom) /* {{{ */
1362{
1363 zend_hash_destroy(&dom_document_prop_handlers);
1364 zend_hash_destroy(&dom_abstract_base_document_prop_handlers);
1365 zend_hash_destroy(&dom_xml_document_prop_handlers);
1366 zend_hash_destroy(&dom_documentfragment_prop_handlers);
1367 zend_hash_destroy(&dom_modern_documentfragment_prop_handlers);
1368 zend_hash_destroy(&dom_node_prop_handlers);
1369 zend_hash_destroy(&dom_modern_node_prop_handlers);
1370 zend_hash_destroy(&dom_entity_reference_prop_handlers);
1371 zend_hash_destroy(&dom_modern_entity_reference_prop_handlers);
1372 zend_hash_destroy(&dom_namespace_node_prop_handlers);
1373 zend_hash_destroy(&dom_nodelist_prop_handlers);
1374 zend_hash_destroy(&dom_namednodemap_prop_handlers);
1375 zend_hash_destroy(&dom_characterdata_prop_handlers);
1376 zend_hash_destroy(&dom_modern_characterdata_prop_handlers);
1377 zend_hash_destroy(&dom_attr_prop_handlers);
1378 zend_hash_destroy(&dom_modern_attr_prop_handlers);
1379 zend_hash_destroy(&dom_element_prop_handlers);
1380 zend_hash_destroy(&dom_modern_element_prop_handlers);
1381 zend_hash_destroy(&dom_text_prop_handlers);
1382 zend_hash_destroy(&dom_modern_text_prop_handlers);
1383 zend_hash_destroy(&dom_documenttype_prop_handlers);
1384 zend_hash_destroy(&dom_modern_documenttype_prop_handlers);
1385 zend_hash_destroy(&dom_notation_prop_handlers);
1386 zend_hash_destroy(&dom_modern_notation_prop_handlers);
1387 zend_hash_destroy(&dom_entity_prop_handlers);
1388 zend_hash_destroy(&dom_modern_entity_prop_handlers);
1389 zend_hash_destroy(&dom_processinginstruction_prop_handlers);
1390 zend_hash_destroy(&dom_modern_processinginstruction_prop_handlers);
1391 zend_hash_destroy(&dom_token_list_prop_handlers);
1392#ifdef LIBXML_XPATH_ENABLED
1393 zend_hash_destroy(&dom_xpath_prop_handlers);
1394#endif
1395 zend_hash_destroy(&classes);
1396
1397/* If you want do find memleaks in this module, compile libxml2 with --with-mem-debug and
1398 uncomment the following line, this will tell you the amount of not freed memory
1399 and the total used memory into apaches error_log */
1400/* xmlMemoryDump();*/
1401
1402 return SUCCESS;
1403}
1404/* }}} */
1405
1406/* {{{ node_list_unlink */
1407void node_list_unlink(xmlNodePtr node)
1408{
1409 dom_object *wrapper;
1410
1411 while (node != NULL) {
1412
1413 wrapper = php_dom_object_get_data(node);
1414
1415 if (wrapper != NULL ) {
1416 xmlUnlinkNode(node);
1417 } else {
1418 if (node->type == XML_ENTITY_REF_NODE)
1419 break;
1420 node_list_unlink(node->children);
1421
1422 switch (node->type) {
1423 case XML_ATTRIBUTE_DECL:
1424 case XML_DTD_NODE:
1426 case XML_ENTITY_DECL:
1427 case XML_ATTRIBUTE_NODE:
1428 case XML_TEXT_NODE:
1429 break;
1430 default:
1431 node_list_unlink((xmlNodePtr) node->properties);
1432 }
1433
1434 }
1435
1436 node = node->next;
1437 }
1438}
1439/* }}} end node_list_unlink */
1440
1441/* {{{ dom_objects_free_storage */
1443{
1444 dom_object *intern = php_dom_obj_from_obj(object);
1445
1446 zend_object_std_dtor(&intern->std);
1447
1448 php_libxml_node_ptr *ptr = intern->ptr;
1449 if (ptr != NULL && ptr->node != NULL) {
1450 xmlNodePtr node = ptr->node;
1451
1452 if (node->type != XML_DOCUMENT_NODE && node->type != XML_HTML_DOCUMENT_NODE) {
1453 php_libxml_node_decrement_resource((php_libxml_node_object *) intern);
1454 } else {
1455 php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
1456 php_libxml_decrement_doc_ref((php_libxml_node_object *) intern);
1457 }
1458 intern->ptr = NULL;
1459 }
1460}
1461/* }}} */
1462
1463void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, const char *local, size_t local_len, const char *ns, size_t ns_len) /* {{{ */
1464{
1465 dom_nnodemap_object *mapptr = (dom_nnodemap_object *) intern->ptr;
1466
1467 ZEND_ASSERT(basenode != NULL);
1468
1469 ZVAL_OBJ_COPY(&mapptr->baseobj_zv, &basenode->std);
1470
1471 xmlDocPtr doc = basenode->document ? basenode->document->ptr : NULL;
1472
1473 mapptr->baseobj = basenode;
1474 mapptr->nodetype = ntype;
1475 mapptr->ht = ht;
1476 if (EXPECTED(doc != NULL)) {
1477 mapptr->dict = doc->dict;
1478 xmlDictReference(doc->dict);
1479 }
1480
1481 const xmlChar* tmp;
1482
1483 if (local) {
1484 int len = (int) local_len;
1485 if (doc != NULL && (tmp = xmlDictExists(doc->dict, (const xmlChar *)local, len)) != NULL) {
1486 mapptr->local = BAD_CAST tmp;
1487 } else {
1488 mapptr->local = xmlCharStrndup(local, len);
1489 mapptr->free_local = true;
1490 }
1491 mapptr->local_lower = BAD_CAST estrdup(local);
1492 zend_str_tolower((char *) mapptr->local_lower, len);
1493 }
1494
1495 if (ns) {
1496 int len = (int) ns_len;
1497 if (doc != NULL && (tmp = xmlDictExists(doc->dict, (const xmlChar *)ns, len)) != NULL) {
1498 mapptr->ns = BAD_CAST tmp;
1499 } else {
1500 mapptr->ns = xmlCharStrndup(ns, len);
1501 mapptr->free_ns = true;
1502 }
1503 }
1504}
1505/* }}} */
1506
1507static void dom_objects_set_class_ex(zend_class_entry *class_type, dom_object *intern)
1508{
1509 zend_class_entry *base_class = class_type;
1510 while ((base_class->type != ZEND_INTERNAL_CLASS || base_class->info.internal.module->module_number != dom_module_entry.module_number) && base_class->parent != NULL) {
1511 base_class = base_class->parent;
1512 }
1513
1514 intern->prop_handler = zend_hash_find_ptr(&classes, base_class->name);
1515
1516 zend_object_std_init(&intern->std, class_type);
1517 object_properties_init(&intern->std, class_type);
1518}
1519
1520static dom_object* dom_objects_set_class(zend_class_entry *class_type)
1521{
1522 dom_object *intern = zend_object_alloc(sizeof(dom_object), class_type);
1523 dom_objects_set_class_ex(class_type, intern);
1524 return intern;
1525}
1526
1527/* {{{ dom_objects_new */
1529{
1530 dom_object *intern = dom_objects_set_class(class_type);
1531 return &intern->std;
1532}
1533/* }}} */
1534
1535static zend_object *dom_objects_namespace_node_new(zend_class_entry *class_type)
1536{
1537 dom_object_namespace_node *intern = zend_object_alloc(sizeof(dom_object_namespace_node), class_type);
1538 dom_objects_set_class_ex(class_type, &intern->dom);
1539 return &intern->dom.std;
1540}
1541
1542static void dom_object_namespace_node_free_storage(zend_object *object)
1543{
1544 dom_object_namespace_node *intern = php_dom_namespace_node_obj_from_obj(object);
1545 if (intern->parent_intern != NULL) {
1546 OBJ_RELEASE(&intern->parent_intern->std);
1547 }
1549}
1550
1551#ifdef LIBXML_XPATH_ENABLED
1552
1553/* {{{ zend_object dom_xpath_objects_new(zend_class_entry *class_type) */
1554zend_object *dom_xpath_objects_new(zend_class_entry *class_type)
1555{
1556 dom_xpath_object *intern = zend_object_alloc(sizeof(dom_xpath_object), class_type);
1557
1559 intern->register_node_ns = true;
1560
1561 intern->dom.prop_handler = &dom_xpath_prop_handlers;
1562
1563 zend_object_std_init(&intern->dom.std, class_type);
1564 object_properties_init(&intern->dom.std, class_type);
1565
1566 return &intern->dom.std;
1567}
1568/* }}} */
1569
1570#endif
1571
1572void dom_nnodemap_objects_free_storage(zend_object *object) /* {{{ */
1573{
1574 dom_object *intern = php_dom_obj_from_obj(object);
1575 dom_nnodemap_object *objmap = (dom_nnodemap_object *)intern->ptr;
1576
1577 if (objmap) {
1578 if (objmap->cached_obj && GC_DELREF(&objmap->cached_obj->std) == 0) {
1579 zend_objects_store_del(&objmap->cached_obj->std);
1580 }
1581 if (objmap->free_local) {
1582 xmlFree(objmap->local);
1583 }
1584 if (objmap->free_ns) {
1585 xmlFree(objmap->ns);
1586 }
1587 if (objmap->local_lower) {
1588 efree(objmap->local_lower);
1589 }
1590 if (!Z_ISUNDEF(objmap->baseobj_zv)) {
1591 zval_ptr_dtor(&objmap->baseobj_zv);
1592 }
1593 xmlDictFree(objmap->dict);
1594 efree(objmap);
1595 intern->ptr = NULL;
1596 }
1597
1598 php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
1599
1600 zend_object_std_dtor(&intern->std);
1601}
1602/* }}} */
1603
1605{
1606 dom_object *intern;
1607 dom_nnodemap_object *objmap;
1608
1609 intern = dom_objects_set_class(class_type);
1610 intern->ptr = emalloc(sizeof(dom_nnodemap_object));
1611 objmap = (dom_nnodemap_object *)intern->ptr;
1612 ZVAL_UNDEF(&objmap->baseobj_zv);
1613 objmap->baseobj = NULL;
1614 objmap->nodetype = 0;
1615 objmap->ht = NULL;
1616 objmap->local = NULL;
1617 objmap->local_lower = NULL;
1618 objmap->free_local = false;
1619 objmap->ns = NULL;
1620 objmap->free_ns = false;
1621 objmap->cache_tag.modification_nr = 0;
1622 objmap->cached_length = -1;
1623 objmap->cached_obj = NULL;
1624 objmap->cached_obj_index = 0;
1625 objmap->dict = NULL;
1626
1627 return &intern->std;
1628}
1629
1630void php_dom_create_iterator(zval *return_value, dom_iterator_type iterator_type, bool modern) /* {{{ */
1631{
1632 zend_class_entry *ce;
1633
1634 if (iterator_type == DOM_NAMEDNODEMAP) {
1635 ce = dom_get_namednodemap_ce(modern);
1636 } else if (iterator_type == DOM_HTMLCOLLECTION) {
1637 /* This only exists in modern DOM. */
1638 ZEND_ASSERT(modern);
1640 } else if (iterator_type == DOM_DTD_NAMEDNODEMAP) {
1641 ce = dom_get_dtd_namednodemap_ce(modern);
1642 } else {
1643 ZEND_ASSERT(iterator_type == DOM_NODELIST);
1644 ce = dom_get_nodelist_ce(modern);
1645 }
1646
1648}
1649/* }}} */
1650
1651static zend_always_inline zend_class_entry *dom_get_element_ce(const xmlNode *node, bool modern)
1652{
1653 if (modern) {
1656 } else {
1658 }
1659 } else {
1661 }
1662}
1663
1664bool php_dom_create_nullable_object(xmlNodePtr obj, zval *return_value, dom_object *domobj)
1665{
1666 if (!obj) {
1668 return false;
1669 }
1670
1671 return php_dom_create_object(obj, return_value, domobj);
1672}
1673
1674/* {{{ php_dom_create_object */
1675PHP_DOM_EXPORT bool php_dom_create_object(xmlNodePtr obj, zval *return_value, dom_object *domobj)
1676{
1677 dom_object *intern = php_dom_object_get_data(obj);
1678 if (intern) {
1679 ZVAL_OBJ_COPY(return_value, &intern->std);
1680 return true;
1681 }
1682
1683 bool modern = domobj && php_dom_follow_spec_intern(domobj);
1684
1685 zend_class_entry *ce;
1686 switch (obj->type) {
1687 case XML_DOCUMENT_NODE:
1688 {
1689 ce = dom_get_xml_document_ce(modern);
1690 break;
1691 }
1693 {
1694 ce = dom_get_html_document_ce(modern);
1695 break;
1696 }
1697 case XML_DTD_NODE:
1699 {
1700 ce = dom_get_documenttype_ce(modern);
1701 break;
1702 }
1703 case XML_ELEMENT_NODE:
1704 {
1705 ce = dom_get_element_ce(obj, modern);
1706 break;
1707 }
1708 case XML_ATTRIBUTE_NODE:
1709 {
1710 ce = dom_get_attr_ce(modern);
1711 break;
1712 }
1713 case XML_TEXT_NODE:
1714 {
1715 ce = dom_get_text_ce(modern);
1716 break;
1717 }
1718 case XML_COMMENT_NODE:
1719 {
1720 ce = dom_get_comment_ce(modern);
1721 break;
1722 }
1723 case XML_PI_NODE:
1724 {
1725 ce = dom_get_processinginstruction_ce(modern);
1726 break;
1727 }
1729 {
1730 ce = dom_get_entityreference_ce(modern);
1731 break;
1732 }
1733 case XML_ENTITY_DECL:
1734 case XML_ELEMENT_DECL:
1735 {
1736 ce = dom_get_entity_ce(modern);
1737 break;
1738 }
1740 {
1741 ce = dom_get_cdatasection_ce(modern);
1742 break;
1743 }
1745 {
1746 ce = dom_get_documentfragment_ce(modern);
1747 break;
1748 }
1749 case XML_NOTATION_NODE:
1750 {
1751 ce = dom_get_notation_ce(modern);
1752 break;
1753 }
1754 case XML_NAMESPACE_DECL:
1755 {
1756 /* This has no modern equivalent */
1758 break;
1759 }
1760 default:
1761 /* TODO you can actually hit this with fixed attributes in the DTD for example... */
1762 zend_throw_error(NULL, "Unsupported node type: %d", obj->type);
1764 return false;
1765 }
1766
1767 if (domobj && domobj->document) {
1768 ce = dom_get_doc_classmap(domobj->document, ce);
1769 }
1771 return false;
1772}
1773/* }}} end php_domobject_new */
1774
1776{
1778
1780 if (obj->doc != NULL) {
1781 if (parent != NULL) {
1782 intern->document = parent->document;
1783 }
1784 php_libxml_increment_doc_ref((php_libxml_node_object *)intern, obj->doc);
1785 }
1786
1787 php_libxml_increment_node_ptr((php_libxml_node_object *)intern, obj, (void *)intern);
1788
1789 return intern;
1790}
1791
1792void php_dom_create_implementation(zval *retval, bool modern) {
1793 object_init_ex(retval, dom_get_domimplementation_ce(modern));
1794}
1795
1796/* {{{ int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child) */
1797int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child)
1798{
1799 xmlNodePtr nodep;
1800
1801 if (parent == NULL || child == NULL || child->doc != parent->doc) {
1802 return SUCCESS;
1803 }
1804
1805 if (child->type == XML_DOCUMENT_NODE) {
1806 return FAILURE;
1807 }
1808
1809 nodep = parent;
1810
1811 while (nodep) {
1812 if (nodep == child) {
1813 return FAILURE;
1814 }
1815 nodep = nodep->parent;
1816 }
1817
1818 return SUCCESS;
1819}
1820/* }}} end dom_hierarchy */
1821
1822/* {{{ */
1823bool dom_has_feature(zend_string *feature, zend_string *version)
1824{
1825 if (zend_string_equals_literal(version, "1.0")
1826 || zend_string_equals_literal(version, "2.0")
1827 || zend_string_equals_literal(version, "")
1828 ) {
1829 if (zend_string_equals_literal_ci(feature, "XML")
1830 || (zend_string_equals_literal_ci(feature, "Core") && zend_string_equals_literal(version, "1.0"))
1831 ) {
1832 return true;
1833 }
1834 }
1835
1836 return false;
1837}
1838/* }}} end dom_has_feature */
1839
1840bool dom_match_qualified_name_according_to_spec(const xmlChar *qname, const xmlNode *nodep)
1841{
1842 const xmlChar *node_local = nodep->name;
1843
1844 /* The qualified name must be matched, which means either:
1845 * - The local parts are equal and there is no ns prefix for this element (i.e. the fqn is in the local name).
1846 * - There is a prefix, the prefixes are equal and the local parts are equal. */
1847 if (nodep->ns != NULL && nodep->ns->prefix != NULL) {
1848 const char *prefix = (const char *) nodep->ns->prefix;
1849 /* 1. match prefix up to |prefix| characters.
1850 * This won't overflow as it'll stop at the '\0' if the lengths don't match. */
1851 size_t prefix_len = strlen(prefix);
1852 if (strncmp((const char *) qname, prefix, prefix_len) != 0) {
1853 return false;
1854 }
1855 /* 2. match ':' */
1856 if (qname[prefix_len] != ':') {
1857 return false;
1858 }
1859 /* 3. match local name */
1860 return xmlStrEqual(qname + prefix_len + 1, node_local);
1861 } else {
1862 return xmlStrEqual(node_local, qname);
1863 }
1864}
1865
1866static bool dom_match_qualified_name_for_tag_name_equality(const xmlChar *local, const xmlChar *local_lower, const xmlNode *nodep, bool match_qname)
1867{
1868 if (!match_qname) {
1869 return xmlStrEqual(nodep->name, local);
1870 }
1871
1872 const xmlChar *local_to_use = nodep->doc->type == XML_HTML_DOCUMENT_NODE && php_dom_ns_is_fast(nodep, php_dom_ns_is_html_magic_token) ? local_lower : local;
1873 return dom_match_qualified_name_according_to_spec(local_to_use, nodep);
1874}
1875
1876xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, xmlChar *ns, xmlChar *local, xmlChar *local_lower, zend_long *cur, zend_long index) /* {{{ */
1877{
1878 /* Can happen with detached document */
1879 if (UNEXPECTED(nodep == NULL)) {
1880 return NULL;
1881 }
1882
1883 xmlNodePtr ret = NULL;
1884 bool local_match_any = local[0] == '*' && local[1] == '\0';
1885
1886 /* Note: The spec says that ns == '' must be transformed to ns == NULL. In other words, they are equivalent.
1887 * PHP however does not do this and internally uses the empty string everywhere when the user provides ns == NULL.
1888 * This is because for PHP ns == NULL has another meaning: "match every namespace" instead of "match the empty namespace". */
1889 bool ns_match_any = ns == NULL || (ns[0] == '*' && ns[1] == '\0');
1890
1891 bool match_qname = ns == NULL && php_dom_follow_spec_node(basep);
1892
1893 while (*cur <= index) {
1894 if (nodep->type == XML_ELEMENT_NODE) {
1895 if (local_match_any || dom_match_qualified_name_for_tag_name_equality(local, local_lower, nodep, match_qname)) {
1896 if (ns_match_any || (ns[0] == '\0' && nodep->ns == NULL) || (nodep->ns != NULL && xmlStrEqual(nodep->ns->href, ns))) {
1897 if (*cur == index) {
1898 ret = nodep;
1899 break;
1900 }
1901 (*cur)++;
1902 }
1903 }
1904 }
1905
1906 nodep = php_dom_next_in_tree_order(nodep, basep);
1907 if (!nodep) {
1908 return NULL;
1909 }
1910 }
1911 return ret;
1912}
1913/* }}} end dom_element_get_elements_by_tag_name_ns_raw */
1914
1915static inline bool is_empty_node(xmlNodePtr nodep)
1916{
1917 return nodep->content == NULL || *nodep->content == '\0';
1918}
1919
1920static inline void free_node(xmlNodePtr node)
1921{
1922 if (node->_private == NULL) {
1923 xmlFreeNode(node);
1924 }
1925}
1926
1927static void dom_merge_adjacent_exclusive_text_nodes(xmlNodePtr node)
1928{
1929 xmlNodePtr nextp = node->next;
1930 while (nextp != NULL && nextp->type == XML_TEXT_NODE) {
1931 xmlNodePtr newnextp = nextp->next;
1932 xmlChar *strContent = nextp->content;
1933 if (strContent != NULL) {
1934 xmlNodeAddContent(node, strContent);
1935 }
1936 xmlUnlinkNode(nextp);
1937 free_node(nextp);
1938 nextp = newnextp;
1939 }
1940}
1941
1942/* {{{ void php_dom_normalize_legacy(xmlNodePtr nodep) */
1943void php_dom_normalize_legacy(xmlNodePtr nodep)
1944{
1945 xmlNodePtr child = nodep->children;
1946 while(child != NULL) {
1947 switch (child->type) {
1948 case XML_TEXT_NODE:
1949 dom_merge_adjacent_exclusive_text_nodes(child);
1950 if (is_empty_node(child)) {
1951 xmlNodePtr nextp = child->next;
1952 xmlUnlinkNode(child);
1953 free_node(child);
1954 child = nextp;
1955 continue;
1956 }
1957 break;
1958 case XML_ELEMENT_NODE:
1960 xmlAttrPtr attr = child->properties;
1961 while (attr != NULL) {
1962 php_dom_normalize_legacy((xmlNodePtr) attr);
1963 attr = attr->next;
1964 }
1965 break;
1966 default:
1967 break;
1968 }
1969 child = child->next;
1970 }
1971}
1972/* }}} end php_dom_normalize_legacy */
1973
1974/* https://dom.spec.whatwg.org/#dom-node-normalize */
1975void php_dom_normalize_modern(xmlNodePtr this)
1976{
1977 /* for each descendant exclusive Text node node of this: */
1978 xmlNodePtr node = this->children;
1979 while (node != NULL) {
1980 if (node->type == XML_TEXT_NODE) {
1981 /* 1. Let length be node’s length.
1982 * We'll deviate a bit here: we'll just check if it's empty or not as we don't want to compute the length. */
1983 bool is_empty = is_empty_node(node);
1984
1985 /* 2. If length is zero, then remove node and continue with the next exclusive Text node, if any. */
1986 if (is_empty) {
1987 xmlNodePtr next = node->next;
1988 xmlUnlinkNode(node);
1989 free_node(node);
1990 node = next;
1991 continue;
1992 }
1993
1994 /* 3. Let data be the concatenation of the data of node’s contiguous exclusive Text nodes (excluding itself), in tree order.
1995 * 4. Replace data with node node, offset length, count 0, and data data.
1996 * 7. Remove node’s contiguous exclusive Text nodes (excluding itself), in tree order.
1997 * => In other words: Concat every contiguous text node into node and delete the merged nodes. */
1998 dom_merge_adjacent_exclusive_text_nodes(node);
1999
2000 /* Steps 5-6 deal with mutation records, we don't do that here. */
2001 } else if (node->type == XML_ELEMENT_NODE) {
2003 }
2004 node = node->next;
2005 }
2006}
2007
2008static void dom_reconcile_ns_internal(xmlDocPtr doc, xmlNodePtr nodep, xmlNodePtr search_parent)
2009{
2010 xmlNsPtr nsptr, nsdftptr, curns, prevns = NULL;
2011
2012 /* Following if block primarily used for inserting nodes created via createElementNS */
2013 if (nodep->nsDef != NULL) {
2014 curns = nodep->nsDef;
2015 while (curns) {
2016 nsdftptr = curns->next;
2017 if (curns->href != NULL) {
2018 if((nsptr = xmlSearchNsByHref(doc, search_parent, curns->href)) &&
2019 (curns->prefix == NULL || xmlStrEqual(nsptr->prefix, curns->prefix))) {
2020 curns->next = NULL;
2021 if (prevns == NULL) {
2022 nodep->nsDef = nsdftptr;
2023 } else {
2024 prevns->next = nsdftptr;
2025 }
2026 /* Note: we can't get here if the ns is already on the oldNs list.
2027 * This is because in that case the definition won't be on the node, and
2028 * therefore won't be in the nodep->nsDef list. */
2029 php_libxml_set_old_ns(doc, curns);
2030 curns = prevns;
2031 }
2032 }
2033 prevns = curns;
2034 curns = nsdftptr;
2035 }
2036 }
2037}
2038
2039void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep) /* {{{ */
2040{
2041 ZEND_ASSERT(nodep->type != XML_ATTRIBUTE_NODE);
2042
2043 /* Although the node type will be checked by the libxml2 API,
2044 * we still want to do the internal reconciliation conditionally. */
2045 if (nodep->type == XML_ELEMENT_NODE) {
2046 dom_reconcile_ns_internal(doc, nodep, nodep->parent);
2047 xmlReconciliateNs(doc, nodep);
2048 }
2049}
2050/* }}} */
2051
2052static void dom_reconcile_ns_list_internal(xmlDocPtr doc, xmlNodePtr nodep, xmlNodePtr last, xmlNodePtr search_parent)
2053{
2054 ZEND_ASSERT(nodep != NULL);
2055 while (true) {
2056 if (nodep->type == XML_ELEMENT_NODE) {
2057 dom_reconcile_ns_internal(doc, nodep, search_parent);
2058 if (nodep->children) {
2059 dom_reconcile_ns_list_internal(doc, nodep->children, nodep->last /* process the whole children list */, search_parent);
2060 }
2061 }
2062 if (nodep == last) {
2063 break;
2064 }
2065 nodep = nodep->next;
2066 }
2067}
2068
2069void dom_reconcile_ns_list(xmlDocPtr doc, xmlNodePtr nodep, xmlNodePtr last)
2070{
2071 dom_reconcile_ns_list_internal(doc, nodep, last, nodep->parent);
2072 /* The loop is outside of the recursion in the above call because
2073 * dom_libxml_reconcile_ensure_namespaces_are_declared() performs its own recursion. */
2074 while (true) {
2075 /* The internal libxml2 call will already check the node type, no need for us to do it here. */
2076 xmlReconciliateNs(doc, nodep);
2077 if (nodep == last) {
2078 break;
2079 }
2080 nodep = nodep->next;
2081 }
2082}
2083
2084/* https://dom.spec.whatwg.org/#validate-and-extract */
2085int dom_validate_and_extract(const zend_string *namespace, const zend_string *qname, xmlChar **localName, xmlChar **prefix)
2086{
2087 /* 1. If namespace is the empty string, then set it to null.
2088 * However, we're going to cheat and do the opposite to make
2089 * implementation of the below steps with existing zend_ helpers easier. */
2090 if (namespace == NULL) {
2091 namespace = zend_empty_string;
2092 }
2093
2094 /* 2. Validate qualifiedName. */
2095 if (xmlValidateQName(BAD_CAST ZSTR_VAL(qname), /* allow spaces */ 0) != 0) {
2096 return INVALID_CHARACTER_ERR;
2097 }
2098
2099 /* Steps 3-5 */
2100 *localName = xmlSplitQName2(BAD_CAST ZSTR_VAL(qname), prefix);
2101
2102 /* 6. If prefix is non-null and namespace is null, then throw a "NamespaceError" DOMException.
2103 * Note that null namespace means empty string here becaue of step 1. */
2104 if (*prefix != NULL && ZSTR_VAL(namespace)[0] == '\0') {
2105 return NAMESPACE_ERR;
2106 }
2107
2108 /* 7. If prefix is "xml" and namespace is not the XML namespace, then throw a "NamespaceError" DOMException. */
2109 if (UNEXPECTED(!zend_string_equals_literal(namespace, "http://www.w3.org/XML/1998/namespace") && xmlStrEqual(*prefix, BAD_CAST "xml"))) {
2110 return NAMESPACE_ERR;
2111 }
2112
2113 /* 8. If either qualifiedName or prefix is "xmlns" and namespace is not the XMLNS namespace, then throw a "NamespaceError" DOMException. */
2114 if (UNEXPECTED((zend_string_equals_literal(qname, "xmlns") || xmlStrEqual(*prefix, BAD_CAST "xmlns")) && !zend_string_equals_literal(namespace, "http://www.w3.org/2000/xmlns/"))) {
2115 return NAMESPACE_ERR;
2116 }
2117
2118 /* 9. If namespace is the XMLNS namespace and neither qualifiedName nor prefix is "xmlns", then throw a "NamespaceError" DOMException. */
2119 if (UNEXPECTED(zend_string_equals_literal(namespace, "http://www.w3.org/2000/xmlns/") && !zend_string_equals_literal(qname, "xmlns") && !xmlStrEqual(*prefix, BAD_CAST "xmlns"))) {
2120 return NAMESPACE_ERR;
2121 }
2122
2123 if (*localName == NULL) {
2124 *localName = xmlStrdup(BAD_CAST ZSTR_VAL(qname));
2125 }
2126
2127 return 0;
2128}
2129
2130/*
2131http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
2132
2133NAMESPACE_ERR: Raised if
2134
21351. the qualifiedName is a malformed qualified name
21362. the qualifiedName has a prefix and the namespaceURI is null
2137*/
2138
2139/* {{{ int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len) */
2140int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len) {
2141 if (name_len == 0) {
2142 return NAMESPACE_ERR;
2143 }
2144
2145 *localname = (char *)xmlSplitQName2(BAD_CAST qname, (xmlChar **) prefix);
2146 if (*localname == NULL) {
2147 *localname = (char *)xmlStrdup(BAD_CAST qname);
2148 if (*prefix == NULL && uri_len == 0) {
2149 return 0;
2150 }
2151 }
2152
2153 /* 1 */
2154 if (xmlValidateQName(BAD_CAST qname, 0) != 0) {
2155 return NAMESPACE_ERR;
2156 }
2157
2158 /* 2 */
2159 if (*prefix != NULL && uri_len == 0) {
2160 return NAMESPACE_ERR;
2161 }
2162
2163 return 0;
2164}
2165/* }}} */
2166
2167/* Creates a new namespace declaration with a random prefix with the given uri on the tree.
2168 * This is used to resolve a namespace prefix conflict in cases where spec does not want a
2169 * namespace error in case of conflicts, but demands a resolution. */
2170xmlNsPtr dom_get_ns_resolve_prefix_conflict(xmlNodePtr tree, const char *uri)
2171{
2172 ZEND_ASSERT(tree != NULL);
2173 xmlDocPtr doc = tree->doc;
2174
2175 if (UNEXPECTED(doc == NULL)) {
2176 return NULL;
2177 }
2178
2179 /* Code adapted from libxml2 (2.10.4) */
2180 char prefix[50];
2181 int counter = 1;
2182 snprintf(prefix, sizeof(prefix), "default");
2183 xmlNsPtr nsptr = xmlSearchNs(doc, tree, (const xmlChar *) prefix);
2184 while (nsptr != NULL) {
2185 if (counter > 1000) {
2186 return NULL;
2187 }
2188 snprintf(prefix, sizeof(prefix), "default%d", counter++);
2189 nsptr = xmlSearchNs(doc, tree, (const xmlChar *) prefix);
2190 }
2191
2192 /* Search yielded no conflict */
2193 return xmlNewNs(tree, (const xmlChar *) uri, (const xmlChar *) prefix);
2194}
2195
2196/*
2197http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
2198
2199NAMESPACE_ERR: Raised if
2200
22013. the qualifiedName has a prefix that is "xml" and the namespaceURI is different from "http://www.w3.org/XML/1998/namespace" [XML Namespaces]
22024. the qualifiedName or its prefix is "xmlns" and the namespaceURI is different from "http://www.w3.org/2000/xmlns/"
22035. the namespaceURI is "http://www.w3.org/2000/xmlns/" and neither the qualifiedName nor its prefix is "xmlns".
2204*/
2205
2206xmlNsPtr dom_get_ns_unchecked(xmlNodePtr nodep, char *uri, char *prefix)
2207{
2208 xmlNsPtr nsptr = xmlNewNs(nodep, BAD_CAST uri, BAD_CAST prefix);
2209 if (UNEXPECTED(nsptr == NULL)) {
2210 /* Either memory allocation failure, or it's because of a prefix conflict.
2211 * We'll assume a conflict and try again. If it was a memory allocation failure we'll just fail again, whatever.
2212 * This isn't needed for every caller (such as createElementNS & DOMElement::__construct), but isn't harmful and simplifies the mental model "when do I use which function?".
2213 * This branch will also be taken unlikely anyway as in those cases it'll be for allocation failure. */
2214 return dom_get_ns_resolve_prefix_conflict(nodep, uri);
2215 }
2216
2217 return nsptr;
2218}
2219
2220/* {{{ xmlNsPtr dom_get_ns(xmlNodePtr nodep, char *uri, int *errorcode, char *prefix) */
2221xmlNsPtr dom_get_ns(xmlNodePtr nodep, char *uri, int *errorcode, char *prefix) {
2222 xmlNsPtr nsptr;
2223
2224 if (! ((prefix && !strcmp (prefix, "xml") && strcmp(uri, (char *)XML_XML_NAMESPACE)) ||
2225 (prefix && !strcmp (prefix, "xmlns") && strcmp(uri, DOM_XMLNS_NS_URI)) ||
2226 (prefix && !strcmp(uri, DOM_XMLNS_NS_URI) && strcmp (prefix, "xmlns")))) {
2227 nsptr = dom_get_ns_unchecked(nodep, uri, prefix);
2228 if (UNEXPECTED(nsptr == NULL)) {
2229 goto err;
2230 }
2231 } else {
2232 goto err;
2233 }
2234
2235 *errorcode = 0;
2236 return nsptr;
2237err:
2238 *errorcode = NAMESPACE_ERR;
2239 return NULL;
2240}
2241/* }}} end dom_get_ns */
2242
2243/* {{{ xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName) */
2244xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName) {
2245 xmlNsPtr cur;
2246 xmlNs *ret = NULL;
2247 if (node == NULL)
2248 return NULL;
2249
2250 if (localName == NULL || localName[0] == '\0') {
2251 cur = node->nsDef;
2252 while (cur != NULL) {
2253 if (cur->prefix == NULL && cur->href != NULL) {
2254 ret = cur;
2255 break;
2256 }
2257 cur = cur->next;
2258 }
2259 } else {
2260 cur = node->nsDef;
2261 while (cur != NULL) {
2262 if (cur->prefix != NULL && xmlStrEqual(localName, cur->prefix)) {
2263 ret = cur;
2264 break;
2265 }
2266 cur = cur->next;
2267 }
2268 }
2269 return ret;
2270}
2271/* }}} end dom_get_nsdecl */
2272
2273static xmlNodePtr php_dom_create_fake_namespace_decl_node_ptr(xmlNodePtr nodep, xmlNsPtr original)
2274{
2275 xmlNodePtr attrp;
2276 xmlNsPtr curns = xmlNewNs(NULL, original->href, NULL);
2277 if (original->prefix) {
2278 curns->prefix = xmlStrdup(original->prefix);
2279 attrp = xmlNewDocNode(nodep->doc, NULL, BAD_CAST original->prefix, original->href);
2280 } else {
2281 attrp = xmlNewDocNode(nodep->doc, NULL, BAD_CAST "xmlns", original->href);
2282 }
2283 attrp->type = XML_NAMESPACE_DECL;
2284 attrp->parent = nodep;
2285 attrp->ns = curns;
2286 return attrp;
2287}
2288
2289/* Note: Assumes the additional lifetime was already added in the caller. */
2290xmlNodePtr php_dom_create_fake_namespace_decl(xmlNodePtr nodep, xmlNsPtr original, zval *return_value, dom_object *parent_intern)
2291{
2292 xmlNodePtr attrp = php_dom_create_fake_namespace_decl_node_ptr(nodep, original);
2293 php_dom_create_object(attrp, return_value, parent_intern);
2294 /* This object must exist, because we just created an object for it via php_dom_create_object(). */
2295 php_dom_namespace_node_obj_from_obj(Z_OBJ_P(return_value))->parent_intern = parent_intern;
2296 return attrp;
2297}
2298
2299static bool dom_nodemap_or_nodelist_process_offset_as_named(zval *offset, zend_long *lval)
2300{
2301 if (Z_TYPE_P(offset) == IS_STRING) {
2302 /* See zval_get_long_func() */
2303 double dval;
2304 zend_uchar is_numeric_string_type;
2305 if (0 == (is_numeric_string_type = is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), lval, &dval, true))) {
2306 return true;
2307 } else if (is_numeric_string_type == IS_DOUBLE) {
2308 *lval = zend_dval_to_lval_cap(dval);
2309 }
2310 } else {
2311 *lval = zval_get_long(offset);
2312 }
2313 return false;
2314}
2315
2316static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int type, zval *rv)
2317{
2318 if (UNEXPECTED(!offset)) {
2319 zend_throw_error(NULL, "Cannot access %s without offset", ZSTR_VAL(object->ce->name));
2320 return NULL;
2321 }
2322
2324
2325 zend_long lval;
2326 if (dom_nodemap_or_nodelist_process_offset_as_named(offset, &lval)) {
2327 /* does not support named lookup */
2328 ZVAL_NULL(rv);
2329 return rv;
2330 }
2331
2332 php_dom_nodelist_get_item_into_zval(php_dom_obj_from_obj(object)->ptr, lval, rv);
2333 return rv;
2334}
2335
2336static int dom_nodelist_has_dimension(zend_object *object, zval *member, int check_empty)
2337{
2338 ZVAL_DEREF(member);
2339
2340 /* If it exists, it cannot be empty because nodes aren't empty. */
2341 ZEND_IGNORE_VALUE(check_empty);
2342
2344 if (dom_nodemap_or_nodelist_process_offset_as_named(member, &offset)) {
2345 /* does not support named lookup */
2346 return 0;
2347 }
2348
2349 return offset >= 0 && offset < php_dom_get_nodelist_length(php_dom_obj_from_obj(object));
2350}
2351
2352void dom_remove_all_children(xmlNodePtr nodep)
2353{
2354 if (nodep->children) {
2355 node_list_unlink(nodep->children);
2356 php_libxml_node_free_list((xmlNodePtr) nodep->children);
2357 nodep->children = NULL;
2358 nodep->last = NULL;
2359 }
2360}
2361
2362void php_dom_get_content_into_zval(const xmlNode *nodep, zval *return_value, bool null_on_failure)
2363{
2364 ZEND_ASSERT(nodep != NULL);
2365
2366 switch (nodep->type) {
2367 case XML_TEXT_NODE:
2369 case XML_PI_NODE:
2370 case XML_COMMENT_NODE: {
2371 char *str = (char * ) nodep->content;
2372 if (str != NULL) {
2373 RETURN_STRING(str);
2374 }
2375
2376 break;
2377 }
2378
2379 case XML_ATTRIBUTE_NODE: {
2380 bool free;
2381 xmlChar *value = php_libxml_attr_value((const xmlAttr *) nodep, &free);
2382 RETVAL_STRING_FAST((const char *) value);
2383 if (free) {
2384 xmlFree(value);
2385 }
2386 return;
2387 }
2388
2389 default: {
2390 char *str = (char *) xmlNodeGetContent(nodep);
2391 if (str != NULL) {
2392 RETVAL_STRING(str);
2393 xmlFree(str);
2394 return;
2395 }
2396
2397 break;
2398 }
2399 }
2400
2401 if (null_on_failure) {
2402 RETURN_NULL();
2403 } else {
2405 }
2406}
2407
2408static zval *dom_nodemap_read_dimension(zend_object *object, zval *offset, int type, zval *rv)
2409{
2410 if (UNEXPECTED(!offset)) {
2411 zend_throw_error(NULL, "Cannot access %s without offset", ZSTR_VAL(object->ce->name));
2412 return NULL;
2413 }
2414
2416
2417 zend_long lval;
2418 if (dom_nodemap_or_nodelist_process_offset_as_named(offset, &lval)) {
2419 /* exceptional case, switch to named lookup */
2420 php_dom_named_node_map_get_named_item_into_zval(php_dom_obj_from_obj(object)->ptr, Z_STR_P(offset), rv);
2421 return rv;
2422 }
2423
2424 /* see PHP_METHOD(DOMNamedNodeMap, item) */
2425 if (UNEXPECTED(lval < 0 || ZEND_LONG_INT_OVFL(lval))) {
2426 zend_value_error("must be between 0 and %d", INT_MAX);
2427 return NULL;
2428 }
2429
2430 php_dom_named_node_map_get_item_into_zval(php_dom_obj_from_obj(object)->ptr, lval, rv);
2431 return rv;
2432}
2433
2434static int dom_nodemap_has_dimension(zend_object *object, zval *member, int check_empty)
2435{
2436 ZVAL_DEREF(member);
2437
2438 /* If it exists, it cannot be empty because nodes aren't empty. */
2439 ZEND_IGNORE_VALUE(check_empty);
2440
2442 if (dom_nodemap_or_nodelist_process_offset_as_named(member, &offset)) {
2443 /* exceptional case, switch to named lookup */
2444 return php_dom_named_node_map_get_named_item(php_dom_obj_from_obj(object)->ptr, Z_STR_P(member), false) != NULL;
2445 }
2446
2447 return offset >= 0 && offset < php_dom_get_namednodemap_length(php_dom_obj_from_obj(object));
2448}
2449
2450static zval *dom_modern_nodemap_read_dimension(zend_object *object, zval *offset, int type, zval *rv)
2451{
2452 if (UNEXPECTED(!offset)) {
2453 zend_throw_error(NULL, "Cannot append to %s", ZSTR_VAL(object->ce->name));
2454 return NULL;
2455 }
2456
2457 dom_nnodemap_object *map = php_dom_obj_from_obj(object)->ptr;
2458
2460 if (Z_TYPE_P(offset) == IS_STRING) {
2461 zend_ulong lval;
2462 if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), lval)) {
2464 } else {
2466 }
2467 } else if (Z_TYPE_P(offset) == IS_LONG) {
2469 } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
2470 php_dom_named_node_map_get_item_into_zval(map, zend_dval_to_lval_safe(Z_DVAL_P(offset)), rv);
2471 } else {
2473 return NULL;
2474 }
2475
2476 return rv;
2477}
2478
2479static int dom_modern_nodemap_has_dimension(zend_object *object, zval *member, int check_empty)
2480{
2481 /* If it exists, it cannot be empty because nodes aren't empty. */
2482 ZEND_IGNORE_VALUE(check_empty);
2483
2484 dom_object *obj = php_dom_obj_from_obj(object);
2485 dom_nnodemap_object *map = obj->ptr;
2486
2487 ZVAL_DEREF(member);
2488 if (Z_TYPE_P(member) == IS_STRING) {
2489 zend_ulong lval;
2490 if (ZEND_HANDLE_NUMERIC(Z_STR_P(member), lval)) {
2491 return (zend_long) lval >= 0 && (zend_long) lval < php_dom_get_namednodemap_length(obj);
2492 } else {
2493 return php_dom_named_node_map_get_named_item(map, Z_STR_P(member), false) != NULL;
2494 }
2495 } else if (Z_TYPE_P(member) == IS_LONG) {
2496 zend_long offset = Z_LVAL_P(member);
2497 return offset >= 0 && offset < php_dom_get_namednodemap_length(obj);
2498 } else if (Z_TYPE_P(member) == IS_DOUBLE) {
2499 zend_long offset = zend_dval_to_lval_safe(Z_DVAL_P(member));
2500 return offset >= 0 && offset < php_dom_get_namednodemap_length(obj);
2501 } else {
2503 return 0;
2504 }
2505}
2506
2507static xmlNodePtr dom_clone_container_helper(php_dom_libxml_ns_mapper *ns_mapper, xmlNodePtr src_node, xmlDocPtr dst_doc)
2508{
2509 xmlNodePtr clone = xmlDocCopyNode(src_node, dst_doc, 0);
2510 if (EXPECTED(clone != NULL)) {
2511 /* Set namespace to the original, reconciliation will fix this up. */
2512 clone->ns = src_node->ns;
2513
2514 if (src_node->type == XML_ELEMENT_NODE) {
2515 xmlAttrPtr last_added_attr = NULL;
2516
2517 if (src_node->nsDef != NULL) {
2518 xmlNsPtr current_ns = src_node->nsDef;
2519 do {
2520 php_dom_ns_compat_mark_attribute(ns_mapper, clone, current_ns);
2521 } while ((current_ns = current_ns->next) != NULL);
2522
2523 last_added_attr = clone->properties;
2524 while (last_added_attr->next != NULL) {
2525 last_added_attr = last_added_attr->next;
2526 }
2527 }
2528
2529 /* Attribute cloning logic. */
2530 for (xmlAttrPtr attr = src_node->properties; attr != NULL; attr = attr->next) {
2531 xmlAttrPtr new_attr = (xmlAttrPtr) xmlDocCopyNode((xmlNodePtr) attr, dst_doc, 0);
2532 if (UNEXPECTED(new_attr == NULL)) {
2533 xmlFreeNode(clone);
2534 return NULL;
2535 }
2536 if (last_added_attr == NULL) {
2537 clone->properties = new_attr;
2538 } else {
2539 new_attr->prev = last_added_attr;
2540 last_added_attr->next = new_attr;
2541 }
2542 new_attr->parent = clone;
2543 last_added_attr = new_attr;
2544
2545 /* Set namespace to the original, reconciliation will fix this up. */
2546 new_attr->ns = attr->ns;
2547 }
2548 }
2549 }
2550 return clone;
2551}
2552
2553static xmlNodePtr dom_clone_helper(php_dom_libxml_ns_mapper *ns_mapper, xmlNodePtr src_node, xmlDocPtr dst_doc, bool recursive)
2554{
2555 xmlNodePtr outer_clone = dom_clone_container_helper(ns_mapper, src_node, dst_doc);
2556
2557 if (!recursive || (src_node->type != XML_ELEMENT_NODE && src_node->type != XML_DOCUMENT_FRAG_NODE && src_node->type != XML_DOCUMENT_NODE && src_node->type != XML_HTML_DOCUMENT_NODE)) {
2558 return outer_clone;
2559 }
2560
2561 /* Handle dtd separately, because it is linked twice and requires a special copy function. */
2562 if (src_node->type == XML_DOCUMENT_NODE || src_node->type == XML_HTML_DOCUMENT_NODE) {
2563 dst_doc = (xmlDocPtr) outer_clone;
2564
2565 xmlDtdPtr original_subset = ((xmlDocPtr) src_node)->intSubset;
2566 if (original_subset != NULL) {
2567 dst_doc->intSubset = xmlCopyDtd(((xmlDocPtr) src_node)->intSubset);
2568 if (UNEXPECTED(dst_doc->intSubset == NULL)) {
2569 xmlFreeNode(outer_clone);
2570 return NULL;
2571 }
2572 dst_doc->intSubset->parent = dst_doc;
2573 xmlSetTreeDoc((xmlNodePtr) dst_doc->intSubset, dst_doc);
2574 dst_doc->children = dst_doc->last = (xmlNodePtr) dst_doc->intSubset;
2575 }
2576 }
2577
2578 xmlNodePtr cloned_parent = outer_clone;
2579 xmlNodePtr base = src_node;
2580 src_node = src_node->children;
2581 while (src_node != NULL) {
2582 ZEND_ASSERT(src_node != base);
2583
2584 xmlNodePtr cloned;
2585 if (src_node->type == XML_ELEMENT_NODE) {
2586 cloned = dom_clone_container_helper(ns_mapper, src_node, dst_doc);
2587 } else if (src_node->type == XML_DTD_NODE) {
2588 /* Already handled. */
2589 cloned = NULL;
2590 } else {
2591 cloned = xmlDocCopyNode(src_node, dst_doc, 1);
2592 }
2593
2594 if (EXPECTED(cloned != NULL)) {
2595 if (cloned_parent->children == NULL) {
2596 cloned_parent->children = cloned;
2597 } else {
2598 cloned->prev = cloned_parent->last;
2599 cloned_parent->last->next = cloned;
2600 }
2601 cloned->parent = cloned_parent;
2602 cloned_parent->last = cloned;
2603 }
2604
2605 if (src_node->type == XML_ELEMENT_NODE && src_node->children) {
2606 cloned_parent = cloned;
2607 src_node = src_node->children;
2608 } else if (src_node->next) {
2609 src_node = src_node->next;
2610 } else {
2611 /* Go upwards, until we find a parent node with a next sibling, or until we hit the base. */
2612 do {
2613 src_node = src_node->parent;
2614 if (src_node == base) {
2615 return outer_clone;
2616 }
2617 cloned_parent = cloned_parent->parent;
2618 } while (src_node->next == NULL);
2619 src_node = src_node->next;
2620 }
2621 }
2622
2623 return outer_clone;
2624}
2625
2626xmlNodePtr dom_clone_node(php_dom_libxml_ns_mapper *ns_mapper, xmlNodePtr node, xmlDocPtr doc, bool recursive)
2627{
2628 if (node->type == XML_DTD_NODE) {
2629 /* The behaviour w.r.t. the internal subset is implementation-defined according to DOM 3.
2630 * This follows what e.g. Java and C# do: copy it regardless of the recursiveness.
2631 * Makes sense as the subset is not exactly a child in the normal sense. */
2632 xmlDtdPtr dtd = xmlCopyDtd((xmlDtdPtr) node);
2633 xmlSetTreeDoc((xmlNodePtr) dtd, doc);
2634 return (xmlNodePtr) dtd;
2635 }
2636
2637 if (ns_mapper != NULL) {
2638 xmlNodePtr clone = dom_clone_helper(ns_mapper, node, doc, recursive);
2639 /* Defensively set doc to NULL because we should not be using it after this point.
2640 * When cloning a document the new document will be clone->doc, not doc. */
2641 doc = NULL;
2642 if (EXPECTED(clone != NULL) && clone->doc != node->doc) {
2643 /* We only need to reconcile the namespace when the document changes because the namespaces have to be
2644 * put into their respective namespace mapper. */
2645 if (clone->type == XML_DOCUMENT_NODE || clone->type == XML_HTML_DOCUMENT_NODE || clone->type == XML_DOCUMENT_FRAG_NODE) {
2646 for (xmlNodePtr child = clone->children; child != NULL; child = child->next) {
2647 php_dom_libxml_reconcile_modern(ns_mapper, child);
2648 }
2649 } else {
2650 php_dom_libxml_reconcile_modern(ns_mapper, clone);
2651 }
2652 }
2653 return clone;
2654 } else {
2655 /* See http://www.xmlsoft.org/html/libxml-tree.html#xmlDocCopyNode for meaning of values */
2656 int extended_recursive = recursive;
2657 if (!recursive && node->type == XML_ELEMENT_NODE) {
2658 extended_recursive = 2;
2659 }
2660 return xmlDocCopyNode(node, doc, extended_recursive);
2661 }
2662}
2663
2664bool php_dom_has_child_of_type(xmlNodePtr node, xmlElementType type)
2665{
2666 xmlNodePtr child = node->children;
2667
2668 while (child != NULL) {
2669 if (child->type == type) {
2670 return true;
2671 }
2672
2673 child = child->next;
2674 }
2675
2676 return false;
2677}
2678
2679bool php_dom_has_sibling_following_node(xmlNodePtr node, xmlElementType type)
2680{
2681 xmlNodePtr next = node->next;
2682
2683 while (next != NULL) {
2684 if (next->type == type) {
2685 return true;
2686 }
2687
2688 next = next->next;
2689 }
2690
2691 return false;
2692}
2693
2694bool php_dom_has_sibling_preceding_node(xmlNodePtr node, xmlElementType type)
2695{
2696 xmlNodePtr prev = node->prev;
2697
2698 while (prev != NULL) {
2699 if (prev->type == type) {
2700 return true;
2701 }
2702
2703 prev = prev->prev;
2704 }
2705
2706 return false;
2707}
2708
2709xmlAttrPtr php_dom_get_attribute_node(xmlNodePtr elem, const xmlChar *name, size_t name_len)
2710{
2711 xmlChar *name_processed = BAD_CAST name;
2713 char *lowercase_copy = zend_str_tolower_dup_ex((char *) name, name_len);
2714 if (lowercase_copy != NULL) {
2715 name_processed = BAD_CAST lowercase_copy;
2716 }
2717 }
2718
2719 xmlAttrPtr ret = NULL;
2720 for (xmlAttrPtr attr = elem->properties; attr != NULL; attr = attr->next) {
2721 if (dom_match_qualified_name_according_to_spec(name_processed, (xmlNodePtr) attr)) {
2722 ret = attr;
2723 break;
2724 }
2725 }
2726
2727 if (name_processed != name) {
2728 efree(name_processed);
2729 }
2730
2731 return ret;
2732}
2733
2734/* Workaround for a libxml2 bug on Windows: https://gitlab.gnome.org/GNOME/libxml2/-/issues/611. */
2735xmlChar *php_dom_libxml_fix_file_path(xmlChar *path)
2736{
2737 if (strncmp((char *) path, "file:/", sizeof("file:/") - 1) == 0) {
2738 if (path[6] != '/' && path[6] != '\0' && path[7] != '/' && path[7] != '\0') {
2739 /* The path is file:/xx... where xx != "//", which is broken */
2740 xmlChar *new_path = xmlStrdup(BAD_CAST "file:///");
2741 if (UNEXPECTED(new_path == NULL)) {
2742 return path;
2743 }
2744 new_path = xmlStrcat(new_path, path + 6);
2745 xmlFree(path);
2746 return new_path;
2747 }
2748 }
2749 return path;
2750}
2751
2752xmlDocPtr php_dom_create_html_doc(void)
2753{
2754#ifdef LIBXML_HTML_ENABLED
2755 xmlDocPtr lxml_doc = htmlNewDocNoDtD(NULL, NULL);
2756 if (EXPECTED(lxml_doc)) {
2757 lxml_doc->dict = xmlDictCreate();
2758 }
2759#else
2760 /* If HTML support is not enabled, then htmlNewDocNoDtD() is not available.
2761 * This code mimics the behaviour. */
2762 xmlDocPtr lxml_doc = xmlNewDoc((const xmlChar *) "1.0");
2763 if (EXPECTED(lxml_doc)) {
2764 lxml_doc->type = XML_HTML_DOCUMENT_NODE;
2765 lxml_doc->dict = xmlDictCreate();
2766 }
2767#endif
2768 return lxml_doc;
2769}
2770
2771#endif /* HAVE_DOM */
size_t len
Definition apprentice.c:174
prev(array|object &$array)
PHP_DOM_EXPORT zend_class_entry * dom_text_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_domimplementation_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_parentnode_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_namespace_info_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_node_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_attr_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_childnode_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_html_document_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_cdatasection_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_entity_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_html_element_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_documenttype_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_element_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_dtd_namednodemap_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_node_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_nodelist_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_namespace_node_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_entityreference_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_notation_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_attr_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_element_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_xml_document_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_abstract_base_document_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_comment_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_parentnode_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_notation_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_childnode_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_processinginstruction_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_documentfragment_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_processinginstruction_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_entity_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_namednodemap_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_entityreference_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_nodelist_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_characterdata_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_namednodemap_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_adjacent_position_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_token_list_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_characterdata_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_document_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_documentfragment_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_html_collection_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_domimplementation_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_cdatasection_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_domexception_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_comment_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_text_class_entry
PHP_DOM_EXPORT zend_class_entry * dom_modern_documenttype_class_entry
zend_result dom_token_list_value_write(dom_object *obj, zval *newval)
zend_result dom_nodelist_length_read(dom_object *obj, zval *retval)
zend_result dom_token_list_value_read(dom_object *obj, zval *retval)
zend_result dom_html_document_encoding_write(dom_object *obj, zval *retval)
zend_result dom_documenttype_entities_read(dom_object *obj, zval *retval)
zend_result dom_element_tag_name_read(dom_object *obj, zval *retval)
zend_result dom_modern_document_implementation_read(dom_object *obj, zval *retval)
zend_result dom_element_id_read(dom_object *obj, zval *retval)
zend_result dom_document_strict_error_checking_write(dom_object *obj, zval *newval)
zend_result dom_entity_reference_text_content_read(dom_object *obj, zval *retval)
zend_result dom_node_first_child_read(dom_object *obj, zval *retval)
zend_result dom_text_whole_text_read(dom_object *obj, zval *retval)
zend_result dom_node_last_child_read(dom_object *obj, zval *retval)
zend_result dom_node_owner_document_read(dom_object *obj, zval *retval)
zend_result dom_element_inner_html_read(dom_object *obj, zval *retval)
zend_result dom_html_document_body_write(dom_object *obj, zval *newval)
zend_result dom_node_local_name_read(dom_object *obj, zval *retval)
zend_result dom_document_format_output_read(dom_object *obj, zval *retval)
zend_result dom_document_standalone_write(dom_object *obj, zval *newval)
zend_result dom_characterdata_length_read(dom_object *obj, zval *retval)
zend_result dom_parent_node_last_element_child_read(dom_object *obj, zval *retval)
zend_result dom_documenttype_internal_subset_read(dom_object *obj, zval *retval)
zend_result dom_document_standalone_read(dom_object *obj, zval *retval)
zend_result dom_node_text_content_write(dom_object *obj, zval *newval)
zend_result dom_document_strict_error_checking_read(dom_object *obj, zval *retval)
zend_result dom_attr_schema_type_info_read(dom_object *obj, zval *retval)
zend_result dom_document_substitue_entities_write(dom_object *obj, zval *newval)
zend_result dom_document_recover_read(dom_object *obj, zval *retval)
zend_result dom_node_attributes_read(dom_object *obj, zval *retval)
zend_result dom_processinginstruction_data_write(dom_object *obj, zval *newval)
zend_result dom_token_list_length_read(dom_object *obj, zval *retval)
zend_result dom_document_resolve_externals_read(dom_object *obj, zval *retval)
zend_result dom_document_document_element_read(dom_object *obj, zval *retval)
zend_result dom_documenttype_name_read(dom_object *obj, zval *retval)
zend_result dom_node_next_element_sibling_read(dom_object *obj, zval *retval)
zend_result dom_attr_value_read(dom_object *obj, zval *retval)
zend_result dom_node_previous_sibling_read(dom_object *obj, zval *retval)
zend_result dom_document_format_output_write(dom_object *obj, zval *newval)
zend_result dom_html_document_title_write(dom_object *obj, zval *newval)
zend_result dom_characterdata_data_read(dom_object *obj, zval *retval)
zend_result dom_document_substitue_entities_read(dom_object *obj, zval *retval)
zend_result dom_node_previous_element_sibling_read(dom_object *obj, zval *retval)
zend_result dom_attr_name_read(dom_object *obj, zval *retval)
zend_result dom_modern_element_substituted_node_value_write(dom_object *obj, zval *newval)
zend_result dom_element_class_name_read(dom_object *obj, zval *retval)
zend_result dom_document_document_uri_write(dom_object *obj, zval *newval)
zend_result dom_entity_public_id_read(dom_object *obj, zval *retval)
zend_result dom_element_schema_type_info_read(dom_object *obj, zval *retval)
zend_result dom_notation_system_id_read(dom_object *obj, zval *retval)
zend_result dom_node_parent_node_read(dom_object *obj, zval *retval)
zend_result dom_node_child_nodes_read(dom_object *obj, zval *retval)
zend_result dom_element_class_name_write(dom_object *obj, zval *newval)
zend_result dom_html_document_head_read(dom_object *obj, zval *retval)
zend_result dom_documenttype_notations_read(dom_object *obj, zval *retval)
zend_result dom_document_config_read(dom_object *obj, zval *retval)
zend_result dom_namednodemap_length_read(dom_object *obj, zval *retval)
zend_result dom_document_actual_encoding_read(dom_object *obj, zval *retval)
zend_result dom_node_parent_element_read(dom_object *obj, zval *retval)
zend_result dom_element_inner_html_write(dom_object *obj, zval *newval)
zend_result dom_modern_element_substituted_node_value_read(dom_object *obj, zval *retval)
zend_result dom_entity_version_read(dom_object *obj, zval *retval)
zend_result dom_html_document_body_read(dom_object *obj, zval *retval)
zend_result dom_node_node_value_read(dom_object *obj, zval *retval)
zend_result dom_document_document_uri_read(dom_object *obj, zval *retval)
zend_result dom_entity_reference_child_read(dom_object *obj, zval *retval)
zend_result dom_node_node_value_write(dom_object *obj, zval *newval)
zend_result dom_document_resolve_externals_write(dom_object *obj, zval *newval)
zend_result dom_attr_value_write(dom_object *obj, zval *newval)
zend_result dom_html_document_title_read(dom_object *obj, zval *retval)
zend_result dom_element_class_list_read(dom_object *obj, zval *retval)
zend_result dom_processinginstruction_data_read(dom_object *obj, zval *retval)
zend_result dom_documenttype_public_id_read(dom_object *obj, zval *retval)
zend_result dom_node_prefix_read(dom_object *obj, zval *retval)
zend_result dom_characterdata_data_write(dom_object *obj, zval *newval)
zend_result dom_document_recover_write(dom_object *obj, zval *newval)
zend_result dom_node_prefix_write(dom_object *obj, zval *newval)
zend_result dom_documenttype_system_id_read(dom_object *obj, zval *retval)
zend_result dom_node_next_sibling_read(dom_object *obj, zval *retval)
zend_result dom_entity_reference_child_nodes_read(dom_object *obj, zval *retval)
zend_result dom_document_preserve_whitespace_write(dom_object *obj, zval *newval)
zend_result dom_entity_notation_name_read(dom_object *obj, zval *retval)
zend_result dom_document_validate_on_parse_read(dom_object *obj, zval *retval)
zend_result dom_node_namespace_uri_read(dom_object *obj, zval *retval)
zend_result dom_element_id_write(dom_object *obj, zval *newval)
zend_result dom_parent_node_child_element_count(dom_object *obj, zval *retval)
zend_result dom_processinginstruction_target_read(dom_object *obj, zval *retval)
zend_result dom_node_base_uri_read(dom_object *obj, zval *retval)
zend_result dom_entity_actual_encoding_read(dom_object *obj, zval *retval)
zend_result dom_attr_owner_element_read(dom_object *obj, zval *retval)
zend_result dom_document_implementation_read(dom_object *obj, zval *retval)
zend_result dom_notation_public_id_read(dom_object *obj, zval *retval)
zend_result dom_parent_node_first_element_child_read(dom_object *obj, zval *retval)
zend_result dom_document_validate_on_parse_write(dom_object *obj, zval *newval)
zend_result dom_document_encoding_write(dom_object *obj, zval *newval)
zend_result dom_entity_encoding_read(dom_object *obj, zval *retval)
zend_result dom_node_is_connected_read(dom_object *obj, zval *retval)
zend_result dom_attr_specified_read(dom_object *obj, zval *retval)
zend_result dom_modern_node_prefix_read(dom_object *obj, zval *retval)
zend_result dom_node_text_content_read(dom_object *obj, zval *retval)
zend_result dom_document_version_write(dom_object *obj, zval *newval)
zend_result dom_node_node_type_read(dom_object *obj, zval *retval)
zend_result dom_node_node_name_read(dom_object *obj, zval *retval)
zend_result dom_document_encoding_read(dom_object *obj, zval *retval)
zend_result dom_document_doctype_read(dom_object *obj, zval *retval)
zend_result dom_document_version_read(dom_object *obj, zval *retval)
zend_result dom_document_preserve_whitespace_read(dom_object *obj, zval *retval)
zend_result dom_entity_system_id_read(dom_object *obj, zval *retval)
@ NAMESPACE_ERR
@ INVALID_CHARACTER_ERR
zend_ffi_type * type
Definition ffi.c:3812
zend_long n
Definition ffi.c:4979
new_type size
Definition ffi.c:4365
void * ptr
Definition ffi.c:3814
memcpy(ptr1, ptr2, size)
char * err
Definition ffi.c:3029
new_type attr
Definition ffi.c:4364
HashTable * ht
Definition ffi.c:4838
zend_long offset
#define NULL
Definition gdcache.h:45
#define prefix
#define SUCCESS
Definition hash_sha3.c:261
zval * dom_html_collection_read_dimension(zend_object *object, zval *offset, int type, zval *rv)
int dom_html_collection_has_dimension(zend_object *object, zval *member, int check_empty)
LXB_API lxb_status_t lexbor_memory_setup(lexbor_memory_malloc_f new_malloc, lexbor_memory_realloc_f new_realloc, lexbor_memory_calloc_f new_calloc, lexbor_memory_free_f new_free)
Definition memory.c:40
const LIBXML_DOTTED_VERSION
#define next(ls)
Definition minilua.c:2661
PHP_DOM_EXPORT const php_dom_ns_magic_token * php_dom_ns_is_html_magic_token
PHP_DOM_EXPORT bool php_dom_ns_is_fast(const xmlNode *nodep, const php_dom_ns_magic_token *magic_token)
PHP_DOM_EXPORT bool php_dom_ns_is_html_and_document_is_html(const xmlNode *nodep)
PHP_DOM_EXPORT void php_dom_libxml_reconcile_modern(php_dom_libxml_ns_mapper *ns_mapper, xmlNodePtr node)
PHP_DOM_EXPORT xmlAttrPtr php_dom_ns_compat_mark_attribute(php_dom_libxml_ns_mapper *mapper, xmlNodePtr node, xmlNsPtr ns)
#define DOM_XMLNS_NS_URI
zval * dom_modern_nodelist_read_dimension(zend_object *object, zval *offset, int type, zval *rv)
zend_long php_dom_get_nodelist_length(dom_object *obj)
void php_dom_nodelist_get_item_into_zval(dom_nnodemap_object *objmap, zend_long index, zval *return_value)
int dom_modern_nodelist_has_dimension(zend_object *object, zval *member, int check_empty)
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
#define PHP_GINIT
Definition php.h:397
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MSHUTDOWN_FUNCTION
Definition php.h:401
#define PHP_MINFO
Definition php.h:396
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_MSHUTDOWN
Definition php.h:393
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHP_GINIT_FUNCTION
Definition php.h:405
#define INT_MAX
Definition php.h:237
#define PHP_MINIT
Definition php.h:392
#define PHP_MODULE_GLOBALS
Definition php.h:408
xmlNodePtr php_dom_named_node_map_get_named_item(dom_nnodemap_object *objmap, const zend_string *named, bool may_transform)
void php_dom_normalize_modern(xmlNodePtr nodep)
dom_object * php_dom_instantiate_object_helper(zval *return_value, zend_class_entry *ce, xmlNodePtr obj, dom_object *parent)
#define DOM_G(v)
Definition php_dom.h:324
xmlAttrPtr php_dom_get_attribute_node(xmlNodePtr elem, const xmlChar *name, size_t name_len)
zend_object_iterator * php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
void php_dom_create_implementation(zval *retval, bool modern)
xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName)
bool dom_node_children_valid(const xmlNode *node)
xmlNsPtr dom_get_ns(xmlNodePtr node, char *uri, int *errorcode, char *prefix)
xmlDocPtr php_dom_create_html_doc(void)
int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child)
void php_dom_named_node_map_get_named_item_into_zval(dom_nnodemap_object *objmap, const zend_string *named, zval *return_value)
bool dom_has_feature(zend_string *feature, zend_string *version)
zend_object * dom_objects_new(zend_class_entry *class_type)
void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep)
int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len)
bool suppress_warnings
Definition php_dom.h:319
void dom_document_convert_to_modern(php_libxml_ref_obj *document, xmlDocPtr lxml_doc)
xmlNodePtr dom_clone_node(php_dom_libxml_ns_mapper *ns_mapper, xmlNodePtr node, xmlDocPtr doc, bool recursive)
void node_list_unlink(xmlNodePtr node)
bool dom_match_qualified_name_according_to_spec(const xmlChar *qname, const xmlNode *nodep)
int php_dom_get_namednodemap_length(dom_object *obj)
xmlNsPtr dom_get_ns_resolve_prefix_conflict(xmlNodePtr tree, const char *uri)
bool dom_get_strict_error(php_libxml_ref_obj *document)
xmlNsPtr dom_get_ns_unchecked(xmlNodePtr nodep, char *uri, char *prefix)
xmlNodePtr php_dom_create_fake_namespace_decl(xmlNodePtr nodep, xmlNsPtr original, zval *return_value, dom_object *parent_intern)
xmlNode * dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, xmlChar *ns, xmlChar *local, xmlChar *local_lower, zend_long *cur, zend_long index)
#define DOM_API_VERSION
Definition php_dom.h:63
void php_dom_update_document_after_clone(dom_object *original, xmlNodePtr original_node, dom_object *clone, xmlNodePtr cloned_node)
void dom_objects_free_storage(zend_object *object)
bool php_dom_create_nullable_object(xmlNodePtr obj, zval *return_value, dom_object *domobj)
void php_dom_normalize_legacy(xmlNodePtr nodep)
bool php_dom_has_sibling_following_node(xmlNodePtr node, xmlElementType type)
void php_dom_get_content_into_zval(const xmlNode *nodep, zval *target, bool default_is_null)
int dom_validate_and_extract(const zend_string *namespace, const zend_string *qname, xmlChar **localName, xmlChar **prefix)
dom_doc_propsptr dom_get_doc_props(php_libxml_ref_obj *document)
bool php_dom_has_sibling_preceding_node(xmlNodePtr node, xmlElementType type)
void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, const char *local, size_t local_len, const char *ns, size_t ns_len)
void php_dom_named_node_map_get_item_into_zval(dom_nnodemap_object *objmap, zend_long index, zval *return_value)
bool php_dom_has_child_of_type(xmlNodePtr node, xmlElementType type)
void dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce)
void php_dom_create_iterator(zval *return_value, dom_iterator_type iterator_type, bool modern)
libxml_doc_props const * dom_get_doc_props_read_only(const php_libxml_ref_obj *document)
int dom_node_is_read_only(const xmlNode *node)
void dom_reconcile_ns_list(xmlDocPtr doc, xmlNodePtr nodep, xmlNodePtr last)
zend_object * dom_nnodemap_objects_new(zend_class_entry *class_type)
zend_module_entry dom_module_entry
xmlChar * php_dom_libxml_fix_file_path(xmlChar *path)
dom_iterator_type
Definition php_dom.h:114
@ DOM_DTD_NAMEDNODEMAP
Definition php_dom.h:117
@ DOM_NODELIST
Definition php_dom.h:115
@ DOM_NAMEDNODEMAP
Definition php_dom.h:116
@ DOM_HTMLCOLLECTION
Definition php_dom.h:118
void dom_remove_all_children(xmlNodePtr nodep)
const XML_DOCUMENT_TYPE_NODE
dom_import_simplexml(object $node)
const XML_DTD_NODE
const XML_HTML_DOCUMENT_NODE
const XML_PI_NODE
const XML_TEXT_NODE
const XML_ELEMENT_NODE
const XML_ATTRIBUTE_NODE
const XML_DOCUMENT_NODE
const XML_COMMENT_NODE
const XML_CDATA_SECTION_NODE
const XML_DOCUMENT_FRAG_NODE
const XML_ENTITY_NODE
const XML_NOTATION_NODE
const XML_ENTITY_REF_NODE
php_dom_private_data * php_dom_private_data_create(void)
php_dom_libxml_ns_mapper * php_dom_ns_mapper_from_private(php_dom_private_data *private_data)
php_libxml_private_data_header * php_dom_libxml_private_data_header(php_dom_private_data *private_data)
zval rv
Definition session.c:1024
HashTable * prop_handler
Definition xml_common.h:28
void * ptr
Definition xml_common.h:26
zend_object std
Definition xml_common.h:29
php_libxml_ref_obj * document
Definition xml_common.h:27
struct _zend_module_entry * module
Definition zend.h:234
zend_string * name
Definition zend.h:149
union _zend_class_entry::@126215362204241324314155352336150042254204116267 info
struct _zend_class_entry::@126215362204241324314155352336150042254204116267::@031207115026352130035014265255253014334154061307 internal
char type
Definition zend.h:148
zend_class_entry * parent
Definition zend.h:152
int module_number
zend_object_write_property_t write_property
zend_object_unset_property_t unset_property
zend_object_get_property_ptr_ptr_t get_property_ptr_ptr
zend_object_free_obj_t free_obj
zend_object_get_debug_info_t get_debug_info
zend_object_get_gc_t get_gc
zend_object_has_dimension_t has_dimension
zend_object_read_property_t read_property
zend_object_has_property_t has_property
zend_object_read_dimension_t read_dimension
zend_object_clone_obj_t clone_obj
zend_class_entry * ce
Definition zend_types.h:560
zend_long cached_obj_index
Definition php_dom.h:90
dom_object * baseobj
Definition php_dom.h:81
xmlHashTable * ht
Definition php_dom.h:85
dom_object * cached_obj
Definition php_dom.h:89
php_libxml_cache_tag cache_tag
Definition php_dom.h:88
xmlChar * local_lower
Definition php_dom.h:86
xmlDictPtr dict
Definition php_dom.h:91
xmlChar * local
Definition php_dom.h:86
dom_object * parent_intern
Definition php_dom.h:110
bool register_node_ns
Definition php_dom.h:69
dom_object dom
Definition php_dom.h:70
php_dom_xpath_callbacks xpath_callbacks
Definition php_dom.h:68
zend_object_iterator * dom_token_list_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
void dom_token_list_free_obj(zend_object *object)
int dom_token_list_has_dimension(zend_object *object, zval *offset, int check_empty)
zval * dom_token_list_read_dimension(zend_object *object, zval *offset, int type, zval *rv)
#define PHP_DOM_EXPORT
Definition xml_common.h:51
PHP_DOM_EXPORT xmlNodePtr dom_object_get_node(dom_object *obj)
struct _dom_object dom_object
#define DOM_RET_OBJ(obj, domobject)
Definition xml_common.h:76
PHP_DOM_EXPORT dom_object * php_dom_object_get_data(xmlNodePtr obj)
libxml_doc_props * dom_doc_propsptr
Definition xml_common.h:23
#define Z_DOMOBJ_P(zv)
Definition xml_common.h:36
PHP_DOM_EXPORT bool php_dom_create_object(xmlNodePtr obj, zval *return_value, dom_object *domobj)
PHP_DOM_EXPORT void php_dom_xpath_callbacks_ctor(php_dom_xpath_callbacks *registry)
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API ZEND_COLD void zend_value_error(const char *format,...)
Definition zend.c:1849
ZEND_API ZEND_COLD void zend_illegal_container_offset(const zend_string *container, const zval *offset, int type)
Definition zend.c:1802
#define ZEND_TSRMLS_CACHE_UPDATE()
Definition zend.h:69
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type)
Definition zend_API.c:1849
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:423
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define RETURN_STRING(s)
Definition zend_API.h:1043
#define RETVAL_STRING(s)
Definition zend_API.h:1017
#define RETURN_NULL()
Definition zend_API.h:1036
#define ZEND_DECLARE_MODULE_GLOBALS(module_name)
Definition zend_API.h:268
#define ZEND_GET_MODULE(name)
Definition zend_API.h:241
#define RETVAL_STRING_FAST(s)
Definition zend_API.h:1019
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETURN_EMPTY_STRING()
Definition zend_API.h:1047
#define ecalloc(nmemb, size)
Definition zend_alloc.h:158
#define efree(ptr)
Definition zend_alloc.h:155
#define estrdup(s)
Definition zend_alloc.h:164
#define erealloc(ptr, size)
Definition zend_alloc.h:159
#define ALLOC_HASHTABLE(ht)
Definition zend_alloc.h:231
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
strncmp(string $string1, string $string2, int $length)
strcmp(string $string1, string $string2)
zend_string_release_ex(func->internal_function.function_name, 0)
struct _zend_property_info zend_property_info
#define ZEND_CALL_USES_STRICT_TYPES(call)
#define ZEND_INTERNAL_CLASS
#define BP_VAR_IS
#define snprintf
ZEND_API zend_class_entry * zend_ce_exception
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error_ex(const char *class_name, const char *prop_name)
ZEND_API bool zend_never_inline zend_verify_property_type(const zend_property_info *info, zval *property, bool strict)
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, bool overwrite)
Definition zend_hash.c:2547
ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
Definition zend_hash.c:2240
ZEND_API HashTable *ZEND_FASTCALL zend_array_dup(HashTable *source)
Definition zend_hash.c:2438
ZEND_API zval *ZEND_FASTCALL zend_hash_update(HashTable *ht, zend_string *key, zval *pData)
Definition zend_hash.c:997
ZEND_API zend_result ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key)
Definition zend_hash.c:1534
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
#define ZEND_HANDLE_NUMERIC(key, idx)
Definition zend_hash.h:420
#define ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(ht, _key, _ptr)
Definition zend_hash.h:1433
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
ZEND_API zend_class_entry * zend_ce_countable
ZEND_API zend_class_entry * zend_ce_aggregate
int32_t zend_long
Definition zend_long.h:42
uint32_t zend_ulong
Definition zend_long.h:43
struct _zend_string zend_string
#define ZEND_MOD_CONFLICTS(name)
#define ZEND_MOD_END
struct _zend_module_dep zend_module_dep
struct _zend_module_entry zend_module_entry
#define ZEND_MOD_REQUIRED(name)
#define STANDARD_MODULE_PROPERTIES_EX
#define STANDARD_MODULE_HEADER_EX
ZEND_API zval * zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *name, int type, void **cache_slot)
ZEND_API HashTable * zend_std_get_properties(zend_object *zobj)
ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has_set_exists, void **cache_slot)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API zval * zend_std_write_property(zend_object *zobj, zend_string *name, zval *value, void **cache_slot)
ZEND_API zend_property_info * zend_get_property_info(const zend_class_entry *ce, zend_string *member, int silent)
ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void **cache_slot)
ZEND_API zval * zend_std_read_property(zend_object *zobj, zend_string *name, int type, void **cache_slot, zval *rv)
ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, zend_object *old_object)
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object)
#define OBJ_RELEASE(obj)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t length)
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length)
int last
#define ZEND_IGNORE_VALUE(x)
#define EXPECTED(condition)
#define zend_always_inline
#define XtOffsetOf(s_type, field)
#define ZEND_ASSERT(c)
#define UNEXPECTED(condition)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
#define ZEND_LONG_INT_OVFL(zlong)
ZEND_API zend_string_init_interned_func_t zend_string_init_interned
Definition zend_string.c:31
ZEND_API zend_string * zend_empty_string
Definition zend_string.c:51
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_INIT_LITERAL(s, persistent)
#define zend_string_equals_literal(str, literal)
#define zend_string_equals_literal_ci(str, c)
#define dval(x)
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define ZVAL_UNDEF(z)
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
#define ZVAL_NULL(z)
#define ZVAL_DEREF(z)
#define IS_STRING
Definition zend_types.h:606
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_OBJ_P(zval_p)
Definition zend_types.h:990
#define Z_OBJ_HT_P(zval_p)
Definition zend_types.h:993
#define IS_DOUBLE
Definition zend_types.h:605
#define Z_ISUNDEF(zval)
Definition zend_types.h:956
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define GC_DELREF(p)
Definition zend_types.h:710
#define GC_ADDREF(p)
Definition zend_types.h:709
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
#define IS_NULL
Definition zend_types.h:601
@ FAILURE
Definition zend_types.h:61
#define IS_OBJECT
Definition zend_types.h:608
#define IS_LONG
Definition zend_types.h:604
#define ZEND_TYPE_IS_SET(t)
Definition zend_types.h:166
#define ZVAL_NEW_STR(z, s)
#define ZVAL_COPY(z, v)
#define ZVAL_OBJ_COPY(z, o)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
unsigned char zend_uchar
Definition zend_types.h:57
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define Z_TYPE(zval)
Definition zend_types.h:659
#define Z_DVAL_P(zval_p)
Definition zend_types.h:969
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zval retval
zval * return_value
zend_string * name
object
zval * ret
value