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 "ext/standard/php_rand.h"
26 #include "php_dom.h"
27 #include "php_dom_arginfo.h"
28 #include "dom_properties.h"
29 #include "zend_interfaces.h"
30
31 #include "ext/standard/info.h"
32 #define PHP_XPATH 1
33 #define PHP_XPTR 2
34
35 /* {{{ class entries */
36 PHP_DOM_EXPORT zend_class_entry *dom_node_class_entry;
37 PHP_DOM_EXPORT zend_class_entry *dom_domexception_class_entry;
38 PHP_DOM_EXPORT zend_class_entry *dom_parentnode_class_entry;
39 PHP_DOM_EXPORT zend_class_entry *dom_childnode_class_entry;
40 PHP_DOM_EXPORT zend_class_entry *dom_domimplementation_class_entry;
41 PHP_DOM_EXPORT zend_class_entry *dom_documentfragment_class_entry;
42 PHP_DOM_EXPORT zend_class_entry *dom_document_class_entry;
43 PHP_DOM_EXPORT zend_class_entry *dom_nodelist_class_entry;
44 PHP_DOM_EXPORT zend_class_entry *dom_namednodemap_class_entry;
45 PHP_DOM_EXPORT zend_class_entry *dom_characterdata_class_entry;
46 PHP_DOM_EXPORT zend_class_entry *dom_attr_class_entry;
47 PHP_DOM_EXPORT zend_class_entry *dom_element_class_entry;
48 PHP_DOM_EXPORT zend_class_entry *dom_text_class_entry;
49 PHP_DOM_EXPORT zend_class_entry *dom_comment_class_entry;
50 PHP_DOM_EXPORT zend_class_entry *dom_cdatasection_class_entry;
51 PHP_DOM_EXPORT zend_class_entry *dom_documenttype_class_entry;
52 PHP_DOM_EXPORT zend_class_entry *dom_notation_class_entry;
53 PHP_DOM_EXPORT zend_class_entry *dom_entity_class_entry;
54 PHP_DOM_EXPORT zend_class_entry *dom_entityreference_class_entry;
55 PHP_DOM_EXPORT zend_class_entry *dom_processinginstruction_class_entry;
56 #ifdef LIBXML_XPATH_ENABLED
57 PHP_DOM_EXPORT zend_class_entry *dom_xpath_class_entry;
58 #endif
59 PHP_DOM_EXPORT zend_class_entry *dom_namespace_node_class_entry;
60 /* }}} */
61
62 zend_object_handlers dom_object_handlers;
63 zend_object_handlers dom_nnodemap_object_handlers;
64 #ifdef LIBXML_XPATH_ENABLED
65 zend_object_handlers dom_xpath_object_handlers;
66 #endif
67
68 static HashTable classes;
69 /* {{{ prop handler tables */
70 static HashTable dom_document_prop_handlers;
71 static HashTable dom_documentfragment_prop_handlers;
72 static HashTable dom_node_prop_handlers;
73 static HashTable dom_nodelist_prop_handlers;
74 static HashTable dom_namednodemap_prop_handlers;
75 static HashTable dom_characterdata_prop_handlers;
76 static HashTable dom_attr_prop_handlers;
77 static HashTable dom_element_prop_handlers;
78 static HashTable dom_text_prop_handlers;
79 static HashTable dom_documenttype_prop_handlers;
80 static HashTable dom_notation_prop_handlers;
81 static HashTable dom_entity_prop_handlers;
82 static HashTable dom_processinginstruction_prop_handlers;
83 static HashTable dom_namespace_node_prop_handlers;
84 #ifdef LIBXML_XPATH_ENABLED
85 static HashTable dom_xpath_prop_handlers;
86 #endif
87 /* }}} */
88
89 typedef int (*dom_read_t)(dom_object *obj, zval *retval);
90 typedef int (*dom_write_t)(dom_object *obj, zval *newval);
91
92 typedef struct _dom_prop_handler {
93 dom_read_t read_func;
94 dom_write_t write_func;
95 } dom_prop_handler;
96
dom_get_obj_handlers(void)97 static zend_object_handlers* dom_get_obj_handlers(void) {
98 return &dom_object_handlers;
99 }
100
101 /* {{{ int dom_node_is_read_only(xmlNodePtr node) */
dom_node_is_read_only(xmlNodePtr node)102 int dom_node_is_read_only(xmlNodePtr node) {
103 switch (node->type) {
104 case XML_ENTITY_REF_NODE:
105 case XML_ENTITY_NODE:
106 case XML_DOCUMENT_TYPE_NODE:
107 case XML_NOTATION_NODE:
108 case XML_DTD_NODE:
109 case XML_ELEMENT_DECL:
110 case XML_ATTRIBUTE_DECL:
111 case XML_ENTITY_DECL:
112 case XML_NAMESPACE_DECL:
113 return SUCCESS;
114 break;
115 default:
116 if (node->doc == NULL) {
117 return SUCCESS;
118 } else {
119 return FAILURE;
120 }
121 }
122 }
123 /* }}} end dom_node_is_read_only */
124
125 /* {{{ int dom_node_children_valid(xmlNodePtr node) */
dom_node_children_valid(xmlNodePtr node)126 int dom_node_children_valid(xmlNodePtr node) {
127 switch (node->type) {
128 case XML_DOCUMENT_TYPE_NODE:
129 case XML_DTD_NODE:
130 case XML_PI_NODE:
131 case XML_COMMENT_NODE:
132 case XML_TEXT_NODE:
133 case XML_CDATA_SECTION_NODE:
134 case XML_NOTATION_NODE:
135 return FAILURE;
136 break;
137 default:
138 return SUCCESS;
139 }
140 }
141 /* }}} end dom_node_children_valid */
142
143 /* {{{ dom_get_doc_props() */
dom_get_doc_props(php_libxml_ref_obj * document)144 dom_doc_propsptr dom_get_doc_props(php_libxml_ref_obj *document)
145 {
146 dom_doc_propsptr doc_props;
147
148 if (document && document->doc_props) {
149 return document->doc_props;
150 } else {
151 doc_props = emalloc(sizeof(libxml_doc_props));
152 doc_props->formatoutput = 0;
153 doc_props->validateonparse = 0;
154 doc_props->resolveexternals = 0;
155 doc_props->preservewhitespace = 1;
156 doc_props->substituteentities = 0;
157 doc_props->stricterror = 1;
158 doc_props->recover = 0;
159 doc_props->classmap = NULL;
160 if (document) {
161 document->doc_props = doc_props;
162 }
163 return doc_props;
164 }
165 }
166
dom_copy_doc_props(php_libxml_ref_obj * source_doc,php_libxml_ref_obj * dest_doc)167 static void dom_copy_doc_props(php_libxml_ref_obj *source_doc, php_libxml_ref_obj *dest_doc)
168 {
169 dom_doc_propsptr source, dest;
170
171 if (source_doc && dest_doc) {
172
173 source = dom_get_doc_props(source_doc);
174 dest = dom_get_doc_props(dest_doc);
175
176 dest->formatoutput = source->formatoutput;
177 dest->validateonparse = source->validateonparse;
178 dest->resolveexternals = source->resolveexternals;
179 dest->preservewhitespace = source->preservewhitespace;
180 dest->substituteentities = source->substituteentities;
181 dest->stricterror = source->stricterror;
182 dest->recover = source->recover;
183 if (source->classmap) {
184 ALLOC_HASHTABLE(dest->classmap);
185 zend_hash_init(dest->classmap, 0, NULL, NULL, 0);
186 zend_hash_copy(dest->classmap, source->classmap, NULL);
187 }
188
189 }
190 }
191
dom_set_doc_classmap(php_libxml_ref_obj * document,zend_class_entry * basece,zend_class_entry * ce)192 void dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce)
193 {
194 dom_doc_propsptr doc_props;
195
196 if (document) {
197 doc_props = dom_get_doc_props(document);
198 if (doc_props->classmap == NULL) {
199 if (ce == NULL) {
200 return;
201 }
202 ALLOC_HASHTABLE(doc_props->classmap);
203 zend_hash_init(doc_props->classmap, 0, NULL, NULL, 0);
204 }
205 if (ce) {
206 zend_hash_update_ptr(doc_props->classmap, basece->name, ce);
207 } else {
208 zend_hash_del(doc_props->classmap, basece->name);
209 }
210 }
211 }
212
dom_get_doc_classmap(php_libxml_ref_obj * document,zend_class_entry * basece)213 zend_class_entry *dom_get_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece)
214 {
215 dom_doc_propsptr doc_props;
216
217 if (document) {
218 doc_props = dom_get_doc_props(document);
219 if (doc_props->classmap) {
220 zend_class_entry *ce = zend_hash_find_ptr(doc_props->classmap, basece->name);
221 if (ce) {
222 return ce;
223 }
224 }
225 }
226
227 return basece;
228 }
229 /* }}} */
230
231 /* {{{ dom_get_strict_error() */
dom_get_strict_error(php_libxml_ref_obj * document)232 int dom_get_strict_error(php_libxml_ref_obj *document) {
233 int stricterror;
234 dom_doc_propsptr doc_props;
235
236 doc_props = dom_get_doc_props(document);
237 stricterror = doc_props->stricterror;
238 if (document == NULL) {
239 efree(doc_props);
240 }
241
242 return stricterror;
243 }
244 /* }}} */
245
246 /* {{{ xmlNodePtr dom_object_get_node(dom_object *obj) */
dom_object_get_node(dom_object * obj)247 PHP_DOM_EXPORT xmlNodePtr dom_object_get_node(dom_object *obj)
248 {
249 if (obj && obj->ptr != NULL) {
250 return ((php_libxml_node_ptr *)obj->ptr)->node;
251 } else {
252 return NULL;
253 }
254 }
255 /* }}} end dom_object_get_node */
256
257 /* {{{ dom_object *php_dom_object_get_data(xmlNodePtr obj) */
php_dom_object_get_data(xmlNodePtr obj)258 PHP_DOM_EXPORT dom_object *php_dom_object_get_data(xmlNodePtr obj)
259 {
260 if (obj && obj->_private != NULL) {
261 return (dom_object *) ((php_libxml_node_ptr *) obj->_private)->_private;
262 } else {
263 return NULL;
264 }
265 }
266 /* }}} end php_dom_object_get_data */
267
dom_register_prop_handler(HashTable * prop_handler,char * name,size_t name_len,dom_read_t read_func,dom_write_t write_func)268 static void dom_register_prop_handler(HashTable *prop_handler, char *name, size_t name_len, dom_read_t read_func, dom_write_t write_func)
269 {
270 dom_prop_handler hnd;
271 zend_string *str;
272
273 hnd.read_func = read_func;
274 hnd.write_func = write_func;
275 str = zend_string_init_interned(name, name_len, 1);
276 zend_hash_add_mem(prop_handler, str, &hnd, sizeof(dom_prop_handler));
277 zend_string_release_ex(str, 1);
278 }
279
dom_get_property_ptr_ptr(zend_object * object,zend_string * name,int type,void ** cache_slot)280 static zval *dom_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot)
281 {
282 dom_object *obj = php_dom_obj_from_obj(object);
283
284 if (!obj->prop_handler || !zend_hash_exists(obj->prop_handler, name)) {
285 return zend_std_get_property_ptr_ptr(object, name, type, cache_slot);
286 }
287
288 return NULL;
289 }
290
291 /* {{{ dom_read_property */
dom_read_property(zend_object * object,zend_string * name,int type,void ** cache_slot,zval * rv)292 zval *dom_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
293 {
294 dom_object *obj = php_dom_obj_from_obj(object);
295 zval *retval;
296 dom_prop_handler *hnd = NULL;
297
298 if (obj->prop_handler != NULL) {
299 hnd = zend_hash_find_ptr(obj->prop_handler, name);
300 } else if (instanceof_function(obj->std.ce, dom_node_class_entry)) {
301 zend_throw_error(NULL, "Couldn't fetch %s. Node no longer exists", ZSTR_VAL(obj->std.ce->name));
302 retval = &EG(uninitialized_zval);
303 return retval;
304 }
305
306 if (hnd) {
307 int ret = hnd->read_func(obj, rv);
308 if (ret == SUCCESS) {
309 retval = rv;
310 } else {
311 retval = &EG(uninitialized_zval);
312 }
313 } else {
314 retval = zend_std_read_property(object, name, type, cache_slot, rv);
315 }
316
317 return retval;
318 }
319 /* }}} */
320
dom_write_property(zend_object * object,zend_string * name,zval * value,void ** cache_slot)321 zval *dom_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
322 {
323 dom_object *obj = php_dom_obj_from_obj(object);
324 dom_prop_handler *hnd = NULL;
325
326 if (obj->prop_handler != NULL) {
327 hnd = zend_hash_find_ptr(obj->prop_handler, name);
328 }
329
330 if (hnd) {
331 if (!hnd->write_func) {
332 zend_throw_error(NULL, "Cannot write read-only property %s::$%s", ZSTR_VAL(object->ce->name), ZSTR_VAL(name));
333 return &EG(error_zval);
334 }
335
336 zend_property_info *prop = zend_get_property_info(object->ce, name, /* silent */ true);
337 if (prop && ZEND_TYPE_IS_SET(prop->type)) {
338 zval tmp;
339 ZVAL_COPY(&tmp, value);
340 if (!zend_verify_property_type(prop, &tmp, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)))) {
341 zval_ptr_dtor(&tmp);
342 return &EG(error_zval);
343 }
344 hnd->write_func(obj, &tmp);
345 zval_ptr_dtor(&tmp);
346 } else {
347 hnd->write_func(obj, value);
348 }
349
350 return value;
351 }
352
353 return zend_std_write_property(object, name, value, cache_slot);
354 }
355
356 /* {{{ dom_property_exists */
dom_property_exists(zend_object * object,zend_string * name,int check_empty,void ** cache_slot)357 static int dom_property_exists(zend_object *object, zend_string *name, int check_empty, void **cache_slot)
358 {
359 dom_object *obj = php_dom_obj_from_obj(object);
360 dom_prop_handler *hnd = NULL;
361 int retval = 0;
362
363 if (obj->prop_handler != NULL) {
364 hnd = zend_hash_find_ptr(obj->prop_handler, name);
365 }
366 if (hnd) {
367 zval tmp;
368
369 if (check_empty == 2) {
370 retval = 1;
371 } else if (hnd->read_func(obj, &tmp) == SUCCESS) {
372 if (check_empty == 1) {
373 retval = zend_is_true(&tmp);
374 } else if (check_empty == 0) {
375 retval = (Z_TYPE(tmp) != IS_NULL);
376 }
377 zval_ptr_dtor(&tmp);
378 }
379 } else {
380 retval = zend_std_has_property(object, name, check_empty, cache_slot);
381 }
382
383 return retval;
384 }
385 /* }}} */
386
dom_get_debug_info_helper(zend_object * object,int * is_temp)387 static HashTable* dom_get_debug_info_helper(zend_object *object, int *is_temp) /* {{{ */
388 {
389 dom_object *obj = php_dom_obj_from_obj(object);
390 HashTable *debug_info,
391 *prop_handlers = obj->prop_handler,
392 *std_props;
393 zend_string *string_key;
394 dom_prop_handler *entry;
395 zend_string *object_str;
396
397 *is_temp = 1;
398
399 std_props = zend_std_get_properties(object);
400 debug_info = zend_array_dup(std_props);
401
402 if (!prop_handlers) {
403 return debug_info;
404 }
405
406 object_str = zend_string_init("(object value omitted)", sizeof("(object value omitted)")-1, 0);
407
408 ZEND_HASH_FOREACH_STR_KEY_PTR(prop_handlers, string_key, entry) {
409 zval value;
410
411 if (entry->read_func(obj, &value) == FAILURE || !string_key) {
412 continue;
413 }
414
415 if (Z_TYPE(value) == IS_OBJECT) {
416 zval_ptr_dtor(&value);
417 ZVAL_NEW_STR(&value, object_str);
418 zend_string_addref(object_str);
419 }
420
421 zend_hash_update(debug_info, string_key, &value);
422 } ZEND_HASH_FOREACH_END();
423
424 zend_string_release_ex(object_str, 0);
425
426 return debug_info;
427 }
428 /* }}} */
429
dom_get_debug_info(zend_object * object,int * is_temp)430 static HashTable* dom_get_debug_info(zend_object *object, int *is_temp) /* {{{ */
431 {
432 return dom_get_debug_info_helper(object, is_temp);
433 }
434 /* }}} */
435
php_dom_export_node(zval * object)436 void *php_dom_export_node(zval *object) /* {{{ */
437 {
438 php_libxml_node_object *intern;
439 xmlNodePtr nodep = NULL;
440
441 intern = (php_libxml_node_object *) Z_DOMOBJ_P(object);
442 if (intern->node) {
443 nodep = intern->node->node;
444 }
445
446 return nodep;
447 }
448 /* }}} */
449
450 /* {{{ Get a simplexml_element object from dom to allow for processing */
PHP_FUNCTION(dom_import_simplexml)451 PHP_FUNCTION(dom_import_simplexml)
452 {
453 zval *node;
454 xmlNodePtr nodep = NULL;
455 php_libxml_node_object *nodeobj;
456 int ret;
457
458 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &node) == FAILURE) {
459 RETURN_THROWS();
460 }
461
462 nodeobj = (php_libxml_node_object *) ((char *) Z_OBJ_P(node) - Z_OBJ_HT_P(node)->offset);
463 nodep = php_libxml_import_node(node);
464
465 if (nodep && nodeobj && (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE)) {
466 DOM_RET_OBJ((xmlNodePtr) nodep, &ret, (dom_object *)nodeobj);
467 } else {
468 zend_argument_value_error(1, "is not a valid node type");
469 RETURN_THROWS();
470 }
471 }
472 /* }}} */
473
474 static dom_object* dom_objects_set_class(zend_class_entry *class_type);
475
dom_objects_store_clone_obj(zend_object * zobject)476 static zend_object *dom_objects_store_clone_obj(zend_object *zobject) /* {{{ */
477 {
478 dom_object *intern = php_dom_obj_from_obj(zobject);
479 dom_object *clone = dom_objects_set_class(intern->std.ce);
480
481 clone->std.handlers = dom_get_obj_handlers();
482
483 if (instanceof_function(intern->std.ce, dom_node_class_entry)) {
484 xmlNodePtr node = (xmlNodePtr)dom_object_get_node(intern);
485 if (node != NULL) {
486 xmlNodePtr cloned_node = xmlDocCopyNode(node, node->doc, 1);
487 if (cloned_node != NULL) {
488 /* If we cloned a document then we must create new doc proxy */
489 if (cloned_node->doc == node->doc) {
490 clone->document = intern->document;
491 }
492 php_libxml_increment_doc_ref((php_libxml_node_object *)clone, cloned_node->doc);
493 php_libxml_increment_node_ptr((php_libxml_node_object *)clone, cloned_node, (void *)clone);
494 if (intern->document != clone->document) {
495 dom_copy_doc_props(intern->document, clone->document);
496 }
497 }
498
499 }
500 }
501
502 zend_objects_clone_members(&clone->std, &intern->std);
503
504 return &clone->std;
505 }
506 /* }}} */
507
dom_copy_prop_handler(zval * zv)508 static void dom_copy_prop_handler(zval *zv) /* {{{ */
509 {
510 dom_prop_handler *hnd = Z_PTR_P(zv);
511 Z_PTR_P(zv) = malloc(sizeof(dom_prop_handler));
512 memcpy(Z_PTR_P(zv), hnd, sizeof(dom_prop_handler));
513 }
514 /* }}} */
515
dom_dtor_prop_handler(zval * zv)516 static void dom_dtor_prop_handler(zval *zv) /* {{{ */
517 {
518 free(Z_PTR_P(zv));
519 }
520
521 static const zend_module_dep dom_deps[] = {
522 ZEND_MOD_REQUIRED("libxml")
523 ZEND_MOD_CONFLICTS("domxml")
524 ZEND_MOD_END
525 };
526
527 zend_module_entry dom_module_entry = { /* {{{ */
528 STANDARD_MODULE_HEADER_EX, NULL,
529 dom_deps,
530 "dom",
531 ext_functions,
532 PHP_MINIT(dom),
533 PHP_MSHUTDOWN(dom),
534 NULL,
535 NULL,
536 PHP_MINFO(dom),
537 DOM_API_VERSION, /* Extension versionnumber */
538 STANDARD_MODULE_PROPERTIES
539 };
540 /* }}} */
541
542 #ifdef COMPILE_DL_DOM
543 ZEND_GET_MODULE(dom)
544 #endif
545
546 void dom_objects_free_storage(zend_object *object);
547 void dom_nnodemap_objects_free_storage(zend_object *object);
548 static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int type, zval *rv);
549 static int dom_nodelist_has_dimension(zend_object *object, zval *member, int check_empty);
550 static zend_object *dom_objects_store_clone_obj(zend_object *zobject);
551 #ifdef LIBXML_XPATH_ENABLED
552 void dom_xpath_objects_free_storage(zend_object *object);
553 #endif
554
555 /* {{{ PHP_MINIT_FUNCTION(dom) */
PHP_MINIT_FUNCTION(dom)556 PHP_MINIT_FUNCTION(dom)
557 {
558 memcpy(&dom_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
559 dom_object_handlers.offset = XtOffsetOf(dom_object, std);
560 dom_object_handlers.free_obj = dom_objects_free_storage;
561 dom_object_handlers.read_property = dom_read_property;
562 dom_object_handlers.write_property = dom_write_property;
563 dom_object_handlers.get_property_ptr_ptr = dom_get_property_ptr_ptr;
564 dom_object_handlers.clone_obj = dom_objects_store_clone_obj;
565 dom_object_handlers.has_property = dom_property_exists;
566 dom_object_handlers.get_debug_info = dom_get_debug_info;
567
568 memcpy(&dom_nnodemap_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
569 dom_nnodemap_object_handlers.free_obj = dom_nnodemap_objects_free_storage;
570 dom_nnodemap_object_handlers.read_dimension = dom_nodelist_read_dimension;
571 dom_nnodemap_object_handlers.has_dimension = dom_nodelist_has_dimension;
572
573 zend_hash_init(&classes, 0, NULL, NULL, 1);
574
575 dom_domexception_class_entry = register_class_DOMException(zend_ce_exception);
576
577 dom_parentnode_class_entry = register_class_DOMParentNode();
578
579 dom_childnode_class_entry = register_class_DOMChildNode();
580
581 dom_domimplementation_class_entry = register_class_DOMImplementation();
582 dom_domimplementation_class_entry->create_object = dom_objects_new;
583
584 dom_node_class_entry = register_class_DOMNode();
585 dom_node_class_entry->create_object = dom_objects_new;
586
587 zend_hash_init(&dom_node_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
588 dom_register_prop_handler(&dom_node_prop_handlers, "nodeName", sizeof("nodeName")-1, dom_node_node_name_read, NULL);
589 dom_register_prop_handler(&dom_node_prop_handlers, "nodeValue", sizeof("nodeValue")-1, dom_node_node_value_read, dom_node_node_value_write);
590 dom_register_prop_handler(&dom_node_prop_handlers, "nodeType", sizeof("nodeType")-1, dom_node_node_type_read, NULL);
591 dom_register_prop_handler(&dom_node_prop_handlers, "parentNode", sizeof("parentNode")-1, dom_node_parent_node_read, NULL);
592 dom_register_prop_handler(&dom_node_prop_handlers, "childNodes", sizeof("childNodes")-1, dom_node_child_nodes_read, NULL);
593 dom_register_prop_handler(&dom_node_prop_handlers, "firstChild", sizeof("firstChild")-1, dom_node_first_child_read, NULL);
594 dom_register_prop_handler(&dom_node_prop_handlers, "lastChild", sizeof("lastChild")-1, dom_node_last_child_read, NULL);
595 dom_register_prop_handler(&dom_node_prop_handlers, "previousSibling", sizeof("previousSibling")-1, dom_node_previous_sibling_read, NULL);
596 dom_register_prop_handler(&dom_node_prop_handlers, "nextSibling", sizeof("nextSibling")-1, dom_node_next_sibling_read, NULL);
597 dom_register_prop_handler(&dom_node_prop_handlers, "attributes", sizeof("attributes")-1, dom_node_attributes_read, NULL);
598 dom_register_prop_handler(&dom_node_prop_handlers, "ownerDocument", sizeof("ownerDocument")-1, dom_node_owner_document_read, NULL);
599 dom_register_prop_handler(&dom_node_prop_handlers, "namespaceURI", sizeof("namespaceURI")-1, dom_node_namespace_uri_read, NULL);
600 dom_register_prop_handler(&dom_node_prop_handlers, "prefix", sizeof("prefix")-1, dom_node_prefix_read, dom_node_prefix_write);
601 dom_register_prop_handler(&dom_node_prop_handlers, "localName", sizeof("localName")-1, dom_node_local_name_read, NULL);
602 dom_register_prop_handler(&dom_node_prop_handlers, "baseURI", sizeof("baseURI")-1, dom_node_base_uri_read, NULL);
603 dom_register_prop_handler(&dom_node_prop_handlers, "textContent", sizeof("textContent")-1, dom_node_text_content_read, dom_node_text_content_write);
604 zend_hash_add_ptr(&classes, dom_node_class_entry->name, &dom_node_prop_handlers);
605
606 dom_namespace_node_class_entry = register_class_DOMNameSpaceNode();
607 dom_namespace_node_class_entry->create_object = dom_objects_new;
608
609 zend_hash_init(&dom_namespace_node_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
610 dom_register_prop_handler(&dom_namespace_node_prop_handlers, "nodeName", sizeof("nodeName")-1, dom_node_node_name_read, NULL);
611 dom_register_prop_handler(&dom_namespace_node_prop_handlers, "nodeValue", sizeof("nodeValue")-1, dom_node_node_value_read, NULL);
612 dom_register_prop_handler(&dom_namespace_node_prop_handlers, "nodeType", sizeof("nodeType")-1, dom_node_node_type_read, NULL);
613 dom_register_prop_handler(&dom_namespace_node_prop_handlers, "prefix", sizeof("prefix")-1, dom_node_prefix_read, NULL);
614 dom_register_prop_handler(&dom_namespace_node_prop_handlers, "localName", sizeof("localName")-1, dom_node_local_name_read, NULL);
615 dom_register_prop_handler(&dom_namespace_node_prop_handlers, "namespaceURI", sizeof("namespaceURI")-1, dom_node_namespace_uri_read, NULL);
616 dom_register_prop_handler(&dom_namespace_node_prop_handlers, "ownerDocument", sizeof("ownerDocument")-1, dom_node_owner_document_read, NULL);
617 dom_register_prop_handler(&dom_namespace_node_prop_handlers, "parentNode", sizeof("parentNode")-1, dom_node_parent_node_read, NULL);
618 zend_hash_add_ptr(&classes, dom_namespace_node_class_entry->name, &dom_namespace_node_prop_handlers);
619
620 dom_documentfragment_class_entry = register_class_DOMDocumentFragment(dom_node_class_entry, dom_parentnode_class_entry);
621 dom_documentfragment_class_entry->create_object = dom_objects_new;
622 zend_hash_init(&dom_documentfragment_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
623
624 dom_register_prop_handler(&dom_documentfragment_prop_handlers, "firstElementChild", sizeof("firstElementChild")-1, dom_parent_node_first_element_child_read, NULL);
625 dom_register_prop_handler(&dom_documentfragment_prop_handlers, "lastElementChild", sizeof("lastElementChild")-1, dom_parent_node_last_element_child_read, NULL);
626 dom_register_prop_handler(&dom_documentfragment_prop_handlers, "childElementCount", sizeof("childElementCount")-1, dom_parent_node_child_element_count, NULL);
627
628 zend_hash_merge(&dom_documentfragment_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
629 zend_hash_add_ptr(&classes, dom_documentfragment_class_entry->name, &dom_documentfragment_prop_handlers);
630
631 dom_document_class_entry = register_class_DOMDocument(dom_node_class_entry, dom_parentnode_class_entry);
632 dom_document_class_entry->create_object = dom_objects_new;
633 zend_hash_init(&dom_document_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
634 dom_register_prop_handler(&dom_document_prop_handlers, "doctype", sizeof("doctype")-1, dom_document_doctype_read, NULL);
635 dom_register_prop_handler(&dom_document_prop_handlers, "implementation", sizeof("implementation")-1, dom_document_implementation_read, NULL);
636 dom_register_prop_handler(&dom_document_prop_handlers, "documentElement", sizeof("documentElement")-1, dom_document_document_element_read, NULL);
637 dom_register_prop_handler(&dom_document_prop_handlers, "actualEncoding", sizeof("actualEncoding")-1, dom_document_encoding_read, NULL);
638 dom_register_prop_handler(&dom_document_prop_handlers, "encoding", sizeof("encoding")-1, dom_document_encoding_read, dom_document_encoding_write);
639 dom_register_prop_handler(&dom_document_prop_handlers, "xmlEncoding", sizeof("xmlEncoding")-1, dom_document_encoding_read, NULL);
640 dom_register_prop_handler(&dom_document_prop_handlers, "standalone", sizeof("standalone")-1, dom_document_standalone_read, dom_document_standalone_write);
641 dom_register_prop_handler(&dom_document_prop_handlers, "xmlStandalone", sizeof("xmlStandalone")-1, dom_document_standalone_read, dom_document_standalone_write);
642 dom_register_prop_handler(&dom_document_prop_handlers, "version", sizeof("version")-1, dom_document_version_read, dom_document_version_write);
643 dom_register_prop_handler(&dom_document_prop_handlers, "xmlVersion", sizeof("xmlVersion")-1, dom_document_version_read, dom_document_version_write);
644 dom_register_prop_handler(&dom_document_prop_handlers, "strictErrorChecking", sizeof("strictErrorChecking")-1, dom_document_strict_error_checking_read, dom_document_strict_error_checking_write);
645 dom_register_prop_handler(&dom_document_prop_handlers, "documentURI", sizeof("documentURI")-1, dom_document_document_uri_read, dom_document_document_uri_write);
646 dom_register_prop_handler(&dom_document_prop_handlers, "config", sizeof("config")-1, dom_document_config_read, NULL);
647 dom_register_prop_handler(&dom_document_prop_handlers, "formatOutput", sizeof("formatOutput")-1, dom_document_format_output_read, dom_document_format_output_write);
648 dom_register_prop_handler(&dom_document_prop_handlers, "validateOnParse", sizeof("validateOnParse")-1, dom_document_validate_on_parse_read, dom_document_validate_on_parse_write);
649 dom_register_prop_handler(&dom_document_prop_handlers, "resolveExternals", sizeof("resolveExternals")-1, dom_document_resolve_externals_read, dom_document_resolve_externals_write);
650 dom_register_prop_handler(&dom_document_prop_handlers, "preserveWhiteSpace", sizeof("preserveWhitespace")-1, dom_document_preserve_whitespace_read, dom_document_preserve_whitespace_write);
651 dom_register_prop_handler(&dom_document_prop_handlers, "recover", sizeof("recover")-1, dom_document_recover_read, dom_document_recover_write);
652 dom_register_prop_handler(&dom_document_prop_handlers, "substituteEntities", sizeof("substituteEntities")-1, dom_document_substitue_entities_read, dom_document_substitue_entities_write);
653
654 dom_register_prop_handler(&dom_document_prop_handlers, "firstElementChild", sizeof("firstElementChild")-1, dom_parent_node_first_element_child_read, NULL);
655 dom_register_prop_handler(&dom_document_prop_handlers, "lastElementChild", sizeof("lastElementChild")-1, dom_parent_node_last_element_child_read, NULL);
656 dom_register_prop_handler(&dom_document_prop_handlers, "childElementCount", sizeof("childElementCount")-1, dom_parent_node_child_element_count, NULL);
657
658 zend_hash_merge(&dom_document_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
659 zend_hash_add_ptr(&classes, dom_document_class_entry->name, &dom_document_prop_handlers);
660
661 dom_nodelist_class_entry = register_class_DOMNodeList(zend_ce_aggregate, zend_ce_countable);
662 dom_nodelist_class_entry->create_object = dom_nnodemap_objects_new;
663 dom_nodelist_class_entry->get_iterator = php_dom_get_iterator;
664
665 zend_hash_init(&dom_nodelist_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
666 dom_register_prop_handler(&dom_nodelist_prop_handlers, "length", sizeof("length")-1, dom_nodelist_length_read, NULL);
667 zend_hash_add_ptr(&classes, dom_nodelist_class_entry->name, &dom_nodelist_prop_handlers);
668
669 dom_namednodemap_class_entry = register_class_DOMNamedNodeMap(zend_ce_aggregate, zend_ce_countable);
670 dom_namednodemap_class_entry->create_object = dom_nnodemap_objects_new;
671 dom_namednodemap_class_entry->get_iterator = php_dom_get_iterator;
672
673 zend_hash_init(&dom_namednodemap_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
674 dom_register_prop_handler(&dom_namednodemap_prop_handlers, "length", sizeof("length")-1, dom_namednodemap_length_read, NULL);
675 zend_hash_add_ptr(&classes, dom_namednodemap_class_entry->name, &dom_namednodemap_prop_handlers);
676
677 dom_characterdata_class_entry = register_class_DOMCharacterData(dom_node_class_entry, dom_childnode_class_entry);
678 dom_characterdata_class_entry->create_object = dom_objects_new;
679
680 zend_hash_init(&dom_characterdata_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
681 dom_register_prop_handler(&dom_characterdata_prop_handlers, "data", sizeof("data")-1, dom_characterdata_data_read, dom_characterdata_data_write);
682 dom_register_prop_handler(&dom_characterdata_prop_handlers, "length", sizeof("length")-1, dom_characterdata_length_read, NULL);
683 dom_register_prop_handler(&dom_characterdata_prop_handlers, "previousElementSibling", sizeof("previousElementSibling")-1, dom_node_previous_element_sibling_read, NULL);
684 dom_register_prop_handler(&dom_characterdata_prop_handlers, "nextElementSibling", sizeof("nextElementSibling")-1, dom_node_next_element_sibling_read, NULL);
685 zend_hash_merge(&dom_characterdata_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
686 zend_hash_add_ptr(&classes, dom_characterdata_class_entry->name, &dom_characterdata_prop_handlers);
687
688 dom_attr_class_entry = register_class_DOMAttr(dom_node_class_entry);
689 dom_attr_class_entry->create_object = dom_objects_new;
690
691 zend_hash_init(&dom_attr_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
692 dom_register_prop_handler(&dom_attr_prop_handlers, "name", sizeof("name")-1, dom_attr_name_read, NULL);
693 dom_register_prop_handler(&dom_attr_prop_handlers, "specified", sizeof("specified")-1, dom_attr_specified_read, NULL);
694 dom_register_prop_handler(&dom_attr_prop_handlers, "value", sizeof("value")-1, dom_attr_value_read, dom_attr_value_write);
695 dom_register_prop_handler(&dom_attr_prop_handlers, "ownerElement", sizeof("ownerElement")-1, dom_attr_owner_element_read, NULL);
696 dom_register_prop_handler(&dom_attr_prop_handlers, "schemaTypeInfo", sizeof("schemaTypeInfo")-1, dom_attr_schema_type_info_read, NULL);
697 zend_hash_merge(&dom_attr_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
698 zend_hash_add_ptr(&classes, dom_attr_class_entry->name, &dom_attr_prop_handlers);
699
700 dom_element_class_entry = register_class_DOMElement(dom_node_class_entry, dom_parentnode_class_entry, dom_childnode_class_entry);
701 dom_element_class_entry->create_object = dom_objects_new;
702
703 zend_hash_init(&dom_element_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
704 dom_register_prop_handler(&dom_element_prop_handlers, "tagName", sizeof("tagName")-1, dom_element_tag_name_read, NULL);
705 dom_register_prop_handler(&dom_element_prop_handlers, "schemaTypeInfo", sizeof("schemaTypeInfo")-1, dom_element_schema_type_info_read, NULL);
706 dom_register_prop_handler(&dom_element_prop_handlers, "firstElementChild", sizeof("firstElementChild")-1, dom_parent_node_first_element_child_read, NULL);
707 dom_register_prop_handler(&dom_element_prop_handlers, "lastElementChild", sizeof("lastElementChild")-1, dom_parent_node_last_element_child_read, NULL);
708 dom_register_prop_handler(&dom_element_prop_handlers, "childElementCount", sizeof("childElementCount")-1, dom_parent_node_child_element_count, NULL);
709 dom_register_prop_handler(&dom_element_prop_handlers, "previousElementSibling", sizeof("previousElementSibling")-1, dom_node_previous_element_sibling_read, NULL);
710 dom_register_prop_handler(&dom_element_prop_handlers, "nextElementSibling", sizeof("nextElementSibling")-1, dom_node_next_element_sibling_read, NULL);
711 zend_hash_merge(&dom_element_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
712 zend_hash_add_ptr(&classes, dom_element_class_entry->name, &dom_element_prop_handlers);
713
714 dom_text_class_entry = register_class_DOMText(dom_characterdata_class_entry);
715 dom_text_class_entry->create_object = dom_objects_new;
716
717 zend_hash_init(&dom_text_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
718 dom_register_prop_handler(&dom_text_prop_handlers, "wholeText", sizeof("wholeText")-1, dom_text_whole_text_read, NULL);
719 zend_hash_merge(&dom_text_prop_handlers, &dom_characterdata_prop_handlers, dom_copy_prop_handler, 0);
720 zend_hash_add_ptr(&classes, dom_text_class_entry->name, &dom_text_prop_handlers);
721
722 dom_comment_class_entry = register_class_DOMComment(dom_characterdata_class_entry);
723 dom_comment_class_entry->create_object = dom_objects_new;
724 zend_hash_add_ptr(&classes, dom_comment_class_entry->name, &dom_characterdata_prop_handlers);
725
726 dom_cdatasection_class_entry = register_class_DOMCdataSection(dom_text_class_entry);
727 dom_cdatasection_class_entry->create_object = dom_objects_new;
728 zend_hash_add_ptr(&classes, dom_cdatasection_class_entry->name, &dom_text_prop_handlers);
729
730 dom_documenttype_class_entry = register_class_DOMDocumentType(dom_node_class_entry);
731 dom_documenttype_class_entry->create_object = dom_objects_new;
732
733 zend_hash_init(&dom_documenttype_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
734 dom_register_prop_handler(&dom_documenttype_prop_handlers, "name", sizeof("name")-1, dom_documenttype_name_read, NULL);
735 dom_register_prop_handler(&dom_documenttype_prop_handlers, "entities", sizeof("entities")-1, dom_documenttype_entities_read, NULL);
736 dom_register_prop_handler(&dom_documenttype_prop_handlers, "notations", sizeof("notations")-1, dom_documenttype_notations_read, NULL);
737 dom_register_prop_handler(&dom_documenttype_prop_handlers, "publicId", sizeof("publicId")-1, dom_documenttype_public_id_read, NULL);
738 dom_register_prop_handler(&dom_documenttype_prop_handlers, "systemId", sizeof("systemId")-1, dom_documenttype_system_id_read, NULL);
739 dom_register_prop_handler(&dom_documenttype_prop_handlers, "internalSubset", sizeof("internalSubset")-1, dom_documenttype_internal_subset_read, NULL);
740 zend_hash_merge(&dom_documenttype_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
741 zend_hash_add_ptr(&classes, dom_documenttype_class_entry->name, &dom_documenttype_prop_handlers);
742
743 dom_notation_class_entry = register_class_DOMNotation(dom_node_class_entry);
744 dom_notation_class_entry->create_object = dom_objects_new;
745
746 zend_hash_init(&dom_notation_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
747 dom_register_prop_handler(&dom_notation_prop_handlers, "publicId", sizeof("publicId")-1, dom_notation_public_id_read, NULL);
748 dom_register_prop_handler(&dom_notation_prop_handlers, "systemId", sizeof("systemId")-1, dom_notation_system_id_read, NULL);
749 zend_hash_merge(&dom_notation_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
750 zend_hash_add_ptr(&classes, dom_notation_class_entry->name, &dom_notation_prop_handlers);
751
752 dom_entity_class_entry = register_class_DOMEntity(dom_node_class_entry);
753 dom_entity_class_entry->create_object = dom_objects_new;
754
755 zend_hash_init(&dom_entity_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
756 dom_register_prop_handler(&dom_entity_prop_handlers, "publicId", sizeof("publicId")-1, dom_entity_public_id_read, NULL);
757 dom_register_prop_handler(&dom_entity_prop_handlers, "systemId", sizeof("systemId")-1, dom_entity_system_id_read, NULL);
758 dom_register_prop_handler(&dom_entity_prop_handlers, "notationName", sizeof("notationName")-1, dom_entity_notation_name_read, NULL);
759 dom_register_prop_handler(&dom_entity_prop_handlers, "actualEncoding", sizeof("actualEncoding")-1, dom_entity_actual_encoding_read, NULL);
760 dom_register_prop_handler(&dom_entity_prop_handlers, "encoding", sizeof("encoding")-1, dom_entity_encoding_read, NULL);
761 dom_register_prop_handler(&dom_entity_prop_handlers, "version", sizeof("version")-1, dom_entity_version_read, NULL);
762 zend_hash_merge(&dom_entity_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
763 zend_hash_add_ptr(&classes, dom_entity_class_entry->name, &dom_entity_prop_handlers);
764
765 dom_entityreference_class_entry = register_class_DOMEntityReference(dom_node_class_entry);
766 dom_entityreference_class_entry->create_object = dom_objects_new;
767 zend_hash_add_ptr(&classes, dom_entityreference_class_entry->name, &dom_node_prop_handlers);
768
769 dom_processinginstruction_class_entry = register_class_DOMProcessingInstruction(dom_node_class_entry);
770 dom_processinginstruction_class_entry->create_object = dom_objects_new;
771
772 zend_hash_init(&dom_processinginstruction_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
773 dom_register_prop_handler(&dom_processinginstruction_prop_handlers, "target", sizeof("target")-1, dom_processinginstruction_target_read, NULL);
774 dom_register_prop_handler(&dom_processinginstruction_prop_handlers, "data", sizeof("data")-1, dom_processinginstruction_data_read, dom_processinginstruction_data_write);
775 zend_hash_merge(&dom_processinginstruction_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
776 zend_hash_add_ptr(&classes, dom_processinginstruction_class_entry->name, &dom_processinginstruction_prop_handlers);
777
778 #ifdef LIBXML_XPATH_ENABLED
779 memcpy(&dom_xpath_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers));
780 dom_xpath_object_handlers.offset = XtOffsetOf(dom_xpath_object, dom) + XtOffsetOf(dom_object, std);
781 dom_xpath_object_handlers.free_obj = dom_xpath_objects_free_storage;
782
783 dom_xpath_class_entry = register_class_DOMXPath();
784 dom_xpath_class_entry->create_object = dom_xpath_objects_new;
785
786 zend_hash_init(&dom_xpath_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
787 dom_register_prop_handler(&dom_xpath_prop_handlers, "document", sizeof("document")-1, dom_xpath_document_read, NULL);
788 dom_register_prop_handler(&dom_xpath_prop_handlers, "registerNodeNamespaces", sizeof("registerNodeNamespaces")-1, dom_xpath_register_node_ns_read, dom_xpath_register_node_ns_write);
789 zend_hash_add_ptr(&classes, dom_xpath_class_entry->name, &dom_xpath_prop_handlers);
790 #endif
791
792 REGISTER_LONG_CONSTANT("XML_ELEMENT_NODE", XML_ELEMENT_NODE, CONST_CS | CONST_PERSISTENT);
793 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NODE", XML_ATTRIBUTE_NODE, CONST_CS | CONST_PERSISTENT);
794 REGISTER_LONG_CONSTANT("XML_TEXT_NODE", XML_TEXT_NODE, CONST_CS | CONST_PERSISTENT);
795 REGISTER_LONG_CONSTANT("XML_CDATA_SECTION_NODE", XML_CDATA_SECTION_NODE, CONST_CS | CONST_PERSISTENT);
796 REGISTER_LONG_CONSTANT("XML_ENTITY_REF_NODE", XML_ENTITY_REF_NODE, CONST_CS | CONST_PERSISTENT);
797 REGISTER_LONG_CONSTANT("XML_ENTITY_NODE", XML_ENTITY_NODE, CONST_CS | CONST_PERSISTENT);
798 REGISTER_LONG_CONSTANT("XML_PI_NODE", XML_PI_NODE, CONST_CS | CONST_PERSISTENT);
799 REGISTER_LONG_CONSTANT("XML_COMMENT_NODE", XML_COMMENT_NODE, CONST_CS | CONST_PERSISTENT);
800 REGISTER_LONG_CONSTANT("XML_DOCUMENT_NODE", XML_DOCUMENT_NODE, CONST_CS | CONST_PERSISTENT);
801 REGISTER_LONG_CONSTANT("XML_DOCUMENT_TYPE_NODE", XML_DOCUMENT_TYPE_NODE, CONST_CS | CONST_PERSISTENT);
802 REGISTER_LONG_CONSTANT("XML_DOCUMENT_FRAG_NODE", XML_DOCUMENT_FRAG_NODE, CONST_CS | CONST_PERSISTENT);
803 REGISTER_LONG_CONSTANT("XML_NOTATION_NODE", XML_NOTATION_NODE, CONST_CS | CONST_PERSISTENT);
804 REGISTER_LONG_CONSTANT("XML_HTML_DOCUMENT_NODE", XML_HTML_DOCUMENT_NODE, CONST_CS | CONST_PERSISTENT);
805 REGISTER_LONG_CONSTANT("XML_DTD_NODE", XML_DTD_NODE, CONST_CS | CONST_PERSISTENT);
806 REGISTER_LONG_CONSTANT("XML_ELEMENT_DECL_NODE", XML_ELEMENT_DECL, CONST_CS | CONST_PERSISTENT);
807 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_DECL_NODE", XML_ATTRIBUTE_DECL, CONST_CS | CONST_PERSISTENT);
808 REGISTER_LONG_CONSTANT("XML_ENTITY_DECL_NODE", XML_ENTITY_DECL, CONST_CS | CONST_PERSISTENT);
809 REGISTER_LONG_CONSTANT("XML_NAMESPACE_DECL_NODE", XML_NAMESPACE_DECL, CONST_CS | CONST_PERSISTENT);
810 #ifdef XML_GLOBAL_NAMESPACE
811 REGISTER_LONG_CONSTANT("XML_GLOBAL_NAMESPACE", XML_GLOBAL_NAMESPACE, CONST_CS | CONST_PERSISTENT);
812 #endif
813 REGISTER_LONG_CONSTANT("XML_LOCAL_NAMESPACE", XML_LOCAL_NAMESPACE, CONST_CS | CONST_PERSISTENT);
814 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_CDATA", XML_ATTRIBUTE_CDATA, CONST_CS | CONST_PERSISTENT);
815 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_ID", XML_ATTRIBUTE_ID, CONST_CS | CONST_PERSISTENT);
816 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_IDREF", XML_ATTRIBUTE_IDREF, CONST_CS | CONST_PERSISTENT);
817 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_IDREFS", XML_ATTRIBUTE_IDREFS, CONST_CS | CONST_PERSISTENT);
818 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_ENTITY", XML_ATTRIBUTE_ENTITIES, CONST_CS | CONST_PERSISTENT);
819 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NMTOKEN", XML_ATTRIBUTE_NMTOKEN, CONST_CS | CONST_PERSISTENT);
820 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NMTOKENS", XML_ATTRIBUTE_NMTOKENS, CONST_CS | CONST_PERSISTENT);
821 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_ENUMERATION", XML_ATTRIBUTE_ENUMERATION, CONST_CS | CONST_PERSISTENT);
822 REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NOTATION", XML_ATTRIBUTE_NOTATION, CONST_CS | CONST_PERSISTENT);
823
824 /* DOMException Codes */
825 REGISTER_LONG_CONSTANT("DOM_PHP_ERR", PHP_ERR, CONST_CS | CONST_PERSISTENT);
826 REGISTER_LONG_CONSTANT("DOM_INDEX_SIZE_ERR", INDEX_SIZE_ERR, CONST_CS | CONST_PERSISTENT);
827 REGISTER_LONG_CONSTANT("DOMSTRING_SIZE_ERR", DOMSTRING_SIZE_ERR, CONST_CS | CONST_PERSISTENT);
828 REGISTER_LONG_CONSTANT("DOM_HIERARCHY_REQUEST_ERR", HIERARCHY_REQUEST_ERR, CONST_CS | CONST_PERSISTENT);
829 REGISTER_LONG_CONSTANT("DOM_WRONG_DOCUMENT_ERR", WRONG_DOCUMENT_ERR, CONST_CS | CONST_PERSISTENT);
830 REGISTER_LONG_CONSTANT("DOM_INVALID_CHARACTER_ERR", INVALID_CHARACTER_ERR, CONST_CS | CONST_PERSISTENT);
831 REGISTER_LONG_CONSTANT("DOM_NO_DATA_ALLOWED_ERR", NO_DATA_ALLOWED_ERR, CONST_CS | CONST_PERSISTENT);
832 REGISTER_LONG_CONSTANT("DOM_NO_MODIFICATION_ALLOWED_ERR", NO_MODIFICATION_ALLOWED_ERR, CONST_CS | CONST_PERSISTENT);
833 REGISTER_LONG_CONSTANT("DOM_NOT_FOUND_ERR", NOT_FOUND_ERR, CONST_CS | CONST_PERSISTENT);
834 REGISTER_LONG_CONSTANT("DOM_NOT_SUPPORTED_ERR", NOT_SUPPORTED_ERR, CONST_CS | CONST_PERSISTENT);
835 REGISTER_LONG_CONSTANT("DOM_INUSE_ATTRIBUTE_ERR", INUSE_ATTRIBUTE_ERR, CONST_CS | CONST_PERSISTENT);
836 REGISTER_LONG_CONSTANT("DOM_INVALID_STATE_ERR", INVALID_STATE_ERR, CONST_CS | CONST_PERSISTENT);
837 REGISTER_LONG_CONSTANT("DOM_SYNTAX_ERR", SYNTAX_ERR, CONST_CS | CONST_PERSISTENT);
838 REGISTER_LONG_CONSTANT("DOM_INVALID_MODIFICATION_ERR", INVALID_MODIFICATION_ERR, CONST_CS | CONST_PERSISTENT);
839 REGISTER_LONG_CONSTANT("DOM_NAMESPACE_ERR", NAMESPACE_ERR, CONST_CS | CONST_PERSISTENT);
840 REGISTER_LONG_CONSTANT("DOM_INVALID_ACCESS_ERR", INVALID_ACCESS_ERR, CONST_CS | CONST_PERSISTENT);
841 REGISTER_LONG_CONSTANT("DOM_VALIDATION_ERR", VALIDATION_ERR, CONST_CS | CONST_PERSISTENT);
842
843 php_libxml_register_export(dom_node_class_entry, php_dom_export_node);
844
845 return SUCCESS;
846 }
847 /* }}} */
848
849 /* {{{ */
PHP_MINFO_FUNCTION(dom)850 PHP_MINFO_FUNCTION(dom)
851 {
852 php_info_print_table_start();
853 php_info_print_table_row(2, "DOM/XML", "enabled");
854 php_info_print_table_row(2, "DOM/XML API Version", DOM_API_VERSION);
855 php_info_print_table_row(2, "libxml Version", LIBXML_DOTTED_VERSION);
856 #ifdef LIBXML_HTML_ENABLED
857 php_info_print_table_row(2, "HTML Support", "enabled");
858 #endif
859 #ifdef LIBXML_XPATH_ENABLED
860 php_info_print_table_row(2, "XPath Support", "enabled");
861 #endif
862 #ifdef LIBXML_XPTR_ENABLED
863 php_info_print_table_row(2, "XPointer Support", "enabled");
864 #endif
865 #ifdef LIBXML_SCHEMAS_ENABLED
866 php_info_print_table_row(2, "Schema Support", "enabled");
867 php_info_print_table_row(2, "RelaxNG Support", "enabled");
868 #endif
869 php_info_print_table_end();
870 }
871 /* }}} */
872
PHP_MSHUTDOWN_FUNCTION(dom)873 PHP_MSHUTDOWN_FUNCTION(dom) /* {{{ */
874 {
875 zend_hash_destroy(&dom_document_prop_handlers);
876 zend_hash_destroy(&dom_documentfragment_prop_handlers);
877 zend_hash_destroy(&dom_node_prop_handlers);
878 zend_hash_destroy(&dom_namespace_node_prop_handlers);
879 zend_hash_destroy(&dom_nodelist_prop_handlers);
880 zend_hash_destroy(&dom_namednodemap_prop_handlers);
881 zend_hash_destroy(&dom_characterdata_prop_handlers);
882 zend_hash_destroy(&dom_attr_prop_handlers);
883 zend_hash_destroy(&dom_element_prop_handlers);
884 zend_hash_destroy(&dom_text_prop_handlers);
885 zend_hash_destroy(&dom_documenttype_prop_handlers);
886 zend_hash_destroy(&dom_notation_prop_handlers);
887 zend_hash_destroy(&dom_entity_prop_handlers);
888 zend_hash_destroy(&dom_processinginstruction_prop_handlers);
889 #ifdef LIBXML_XPATH_ENABLED
890 zend_hash_destroy(&dom_xpath_prop_handlers);
891 #endif
892 zend_hash_destroy(&classes);
893
894 /* If you want do find memleaks in this module, compile libxml2 with --with-mem-debug and
895 uncomment the following line, this will tell you the amount of not freed memory
896 and the total used memory into apaches error_log */
897 /* xmlMemoryDump();*/
898
899 return SUCCESS;
900 }
901 /* }}} */
902
903 /* {{{ node_list_unlink */
node_list_unlink(xmlNodePtr node)904 void node_list_unlink(xmlNodePtr node)
905 {
906 dom_object *wrapper;
907
908 while (node != NULL) {
909
910 wrapper = php_dom_object_get_data(node);
911
912 if (wrapper != NULL ) {
913 xmlUnlinkNode(node);
914 } else {
915 if (node->type == XML_ENTITY_REF_NODE)
916 break;
917 node_list_unlink(node->children);
918
919 switch (node->type) {
920 case XML_ATTRIBUTE_DECL:
921 case XML_DTD_NODE:
922 case XML_DOCUMENT_TYPE_NODE:
923 case XML_ENTITY_DECL:
924 case XML_ATTRIBUTE_NODE:
925 case XML_TEXT_NODE:
926 break;
927 default:
928 node_list_unlink((xmlNodePtr) node->properties);
929 }
930
931 }
932
933 node = node->next;
934 }
935 }
936 /* }}} end node_list_unlink */
937
938 #ifdef LIBXML_XPATH_ENABLED
939 /* {{{ dom_xpath_objects_free_storage */
dom_xpath_objects_free_storage(zend_object * object)940 void dom_xpath_objects_free_storage(zend_object *object)
941 {
942 dom_xpath_object *intern = php_xpath_obj_from_obj(object);
943
944 zend_object_std_dtor(&intern->dom.std);
945
946 if (intern->dom.ptr != NULL) {
947 xmlXPathFreeContext((xmlXPathContextPtr) intern->dom.ptr);
948 php_libxml_decrement_doc_ref((php_libxml_node_object *) &intern->dom);
949 }
950
951 if (intern->registered_phpfunctions) {
952 zend_hash_destroy(intern->registered_phpfunctions);
953 FREE_HASHTABLE(intern->registered_phpfunctions);
954 }
955
956 if (intern->node_list) {
957 zend_hash_destroy(intern->node_list);
958 FREE_HASHTABLE(intern->node_list);
959 }
960 }
961 /* }}} */
962 #endif
963
964 /* {{{ dom_objects_free_storage */
dom_objects_free_storage(zend_object * object)965 void dom_objects_free_storage(zend_object *object)
966 {
967 dom_object *intern = php_dom_obj_from_obj(object);
968 #if defined(__GNUC__) && __GNUC__ >= 3
969 int retcount __attribute__((unused)); /* keep compiler quiet */
970 #else
971 int retcount;
972 #endif
973
974 zend_object_std_dtor(&intern->std);
975
976 if (intern->ptr != NULL && ((php_libxml_node_ptr *)intern->ptr)->node != NULL) {
977 if (((xmlNodePtr) ((php_libxml_node_ptr *)intern->ptr)->node)->type != XML_DOCUMENT_NODE && ((xmlNodePtr) ((php_libxml_node_ptr *)intern->ptr)->node)->type != XML_HTML_DOCUMENT_NODE) {
978 php_libxml_node_decrement_resource((php_libxml_node_object *) intern);
979 } else {
980 php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
981 retcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
982 }
983 intern->ptr = NULL;
984 }
985 }
986 /* }}} */
987
dom_namednode_iter(dom_object * basenode,int ntype,dom_object * intern,xmlHashTablePtr ht,xmlChar * local,xmlChar * ns)988 void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, xmlChar *local, xmlChar *ns) /* {{{ */
989 {
990 dom_nnodemap_object *mapptr = (dom_nnodemap_object *) intern->ptr;
991
992 ZEND_ASSERT(basenode != NULL);
993
994 ZVAL_OBJ_COPY(&mapptr->baseobj_zv, &basenode->std);
995
996 mapptr->baseobj = basenode;
997 mapptr->nodetype = ntype;
998 mapptr->ht = ht;
999 mapptr->local = local;
1000 mapptr->ns = ns;
1001 }
1002 /* }}} */
1003
dom_objects_set_class(zend_class_entry * class_type)1004 static dom_object* dom_objects_set_class(zend_class_entry *class_type) /* {{{ */
1005 {
1006 dom_object *intern = zend_object_alloc(sizeof(dom_object), class_type);
1007
1008 zend_class_entry *base_class = class_type;
1009 while ((base_class->type != ZEND_INTERNAL_CLASS || base_class->info.internal.module->module_number != dom_module_entry.module_number) && base_class->parent != NULL) {
1010 base_class = base_class->parent;
1011 }
1012
1013 intern->prop_handler = zend_hash_find_ptr(&classes, base_class->name);
1014
1015 zend_object_std_init(&intern->std, class_type);
1016 object_properties_init(&intern->std, class_type);
1017
1018 return intern;
1019 }
1020 /* }}} */
1021
1022 /* {{{ dom_objects_new */
dom_objects_new(zend_class_entry * class_type)1023 zend_object *dom_objects_new(zend_class_entry *class_type)
1024 {
1025 dom_object *intern = dom_objects_set_class(class_type);
1026 intern->std.handlers = dom_get_obj_handlers();
1027 return &intern->std;
1028 }
1029 /* }}} */
1030
1031 #ifdef LIBXML_XPATH_ENABLED
1032 /* {{{ zend_object dom_xpath_objects_new(zend_class_entry *class_type) */
dom_xpath_objects_new(zend_class_entry * class_type)1033 zend_object *dom_xpath_objects_new(zend_class_entry *class_type)
1034 {
1035 dom_xpath_object *intern = zend_object_alloc(sizeof(dom_xpath_object), class_type);
1036
1037 intern->registered_phpfunctions = zend_new_array(0);
1038 intern->register_node_ns = 1;
1039
1040 intern->dom.prop_handler = &dom_xpath_prop_handlers;
1041 intern->dom.std.handlers = &dom_xpath_object_handlers;
1042
1043 zend_object_std_init(&intern->dom.std, class_type);
1044 object_properties_init(&intern->dom.std, class_type);
1045
1046 return &intern->dom.std;
1047 }
1048 /* }}} */
1049 #endif
1050
dom_nnodemap_objects_free_storage(zend_object * object)1051 void dom_nnodemap_objects_free_storage(zend_object *object) /* {{{ */
1052 {
1053 dom_object *intern = php_dom_obj_from_obj(object);
1054 dom_nnodemap_object *objmap = (dom_nnodemap_object *)intern->ptr;
1055
1056 if (objmap) {
1057 if (objmap->local) {
1058 xmlFree(objmap->local);
1059 }
1060 if (objmap->ns) {
1061 xmlFree(objmap->ns);
1062 }
1063 if (!Z_ISUNDEF(objmap->baseobj_zv)) {
1064 zval_ptr_dtor(&objmap->baseobj_zv);
1065 }
1066 efree(objmap);
1067 intern->ptr = NULL;
1068 }
1069
1070 php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
1071
1072 zend_object_std_dtor(&intern->std);
1073 }
1074 /* }}} */
1075
dom_nnodemap_objects_new(zend_class_entry * class_type)1076 zend_object *dom_nnodemap_objects_new(zend_class_entry *class_type) /* {{{ */
1077 {
1078 dom_object *intern;
1079 dom_nnodemap_object *objmap;
1080
1081 intern = dom_objects_set_class(class_type);
1082 intern->ptr = emalloc(sizeof(dom_nnodemap_object));
1083 objmap = (dom_nnodemap_object *)intern->ptr;
1084 ZVAL_UNDEF(&objmap->baseobj_zv);
1085 objmap->baseobj = NULL;
1086 objmap->nodetype = 0;
1087 objmap->ht = NULL;
1088 objmap->local = NULL;
1089 objmap->ns = NULL;
1090
1091 intern->std.handlers = &dom_nnodemap_object_handlers;
1092
1093 return &intern->std;
1094 }
1095 /* }}} */
1096
php_dom_create_iterator(zval * return_value,int ce_type)1097 void php_dom_create_iterator(zval *return_value, int ce_type) /* {{{ */
1098 {
1099 zend_class_entry *ce;
1100
1101 if (ce_type == DOM_NAMEDNODEMAP) {
1102 ce = dom_namednodemap_class_entry;
1103 } else {
1104 ce = dom_nodelist_class_entry;
1105 }
1106
1107 object_init_ex(return_value, ce);
1108 }
1109 /* }}} */
1110
1111 /* {{{ php_dom_create_object */
php_dom_create_object(xmlNodePtr obj,zval * return_value,dom_object * domobj)1112 PHP_DOM_EXPORT bool php_dom_create_object(xmlNodePtr obj, zval *return_value, dom_object *domobj)
1113 {
1114 zend_class_entry *ce;
1115 dom_object *intern;
1116
1117 if (!obj) {
1118 ZVAL_NULL(return_value);
1119 return 0;
1120 }
1121
1122 if ((intern = (dom_object *) php_dom_object_get_data((void *) obj))) {
1123 ZVAL_OBJ_COPY(return_value, &intern->std);
1124 return 1;
1125 }
1126
1127 switch (obj->type) {
1128 case XML_DOCUMENT_NODE:
1129 case XML_HTML_DOCUMENT_NODE:
1130 {
1131 ce = dom_document_class_entry;
1132 break;
1133 }
1134 case XML_DTD_NODE:
1135 case XML_DOCUMENT_TYPE_NODE:
1136 {
1137 ce = dom_documenttype_class_entry;
1138 break;
1139 }
1140 case XML_ELEMENT_NODE:
1141 {
1142 ce = dom_element_class_entry;
1143 break;
1144 }
1145 case XML_ATTRIBUTE_NODE:
1146 {
1147 ce = dom_attr_class_entry;
1148 break;
1149 }
1150 case XML_TEXT_NODE:
1151 {
1152 ce = dom_text_class_entry;
1153 break;
1154 }
1155 case XML_COMMENT_NODE:
1156 {
1157 ce = dom_comment_class_entry;
1158 break;
1159 }
1160 case XML_PI_NODE:
1161 {
1162 ce = dom_processinginstruction_class_entry;
1163 break;
1164 }
1165 case XML_ENTITY_REF_NODE:
1166 {
1167 ce = dom_entityreference_class_entry;
1168 break;
1169 }
1170 case XML_ENTITY_DECL:
1171 case XML_ELEMENT_DECL:
1172 {
1173 ce = dom_entity_class_entry;
1174 break;
1175 }
1176 case XML_CDATA_SECTION_NODE:
1177 {
1178 ce = dom_cdatasection_class_entry;
1179 break;
1180 }
1181 case XML_DOCUMENT_FRAG_NODE:
1182 {
1183 ce = dom_documentfragment_class_entry;
1184 break;
1185 }
1186 case XML_NOTATION_NODE:
1187 {
1188 ce = dom_notation_class_entry;
1189 break;
1190 }
1191 case XML_NAMESPACE_DECL:
1192 {
1193 ce = dom_namespace_node_class_entry;
1194 break;
1195 }
1196 default:
1197 /* TODO Convert to a ZEND assertion? */
1198 zend_throw_error(NULL, "Unsupported node type: %d", obj->type);
1199 ZVAL_NULL(return_value);
1200 return 0;
1201 }
1202
1203 if (domobj && domobj->document) {
1204 ce = dom_get_doc_classmap(domobj->document, ce);
1205 }
1206 object_init_ex(return_value, ce);
1207
1208 intern = Z_DOMOBJ_P(return_value);
1209 if (obj->doc != NULL) {
1210 if (domobj != NULL) {
1211 intern->document = domobj->document;
1212 }
1213 php_libxml_increment_doc_ref((php_libxml_node_object *)intern, obj->doc);
1214 }
1215
1216 php_libxml_increment_node_ptr((php_libxml_node_object *)intern, obj, (void *)intern);
1217 return 0;
1218 }
1219 /* }}} end php_domobject_new */
1220
php_dom_create_implementation(zval * retval)1221 void php_dom_create_implementation(zval *retval) {
1222 object_init_ex(retval, dom_domimplementation_class_entry);
1223 }
1224
1225 /* {{{ int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child) */
dom_hierarchy(xmlNodePtr parent,xmlNodePtr child)1226 int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child)
1227 {
1228 xmlNodePtr nodep;
1229
1230 if (parent == NULL || child == NULL || child->doc != parent->doc) {
1231 return SUCCESS;
1232 }
1233
1234 if (child->type == XML_DOCUMENT_NODE) {
1235 return FAILURE;
1236 }
1237
1238 nodep = parent;
1239
1240 while (nodep) {
1241 if (nodep == child) {
1242 return FAILURE;
1243 }
1244 nodep = nodep->parent;
1245 }
1246
1247 return SUCCESS;
1248 }
1249 /* }}} end dom_hierarchy */
1250
1251 /* {{{ */
dom_has_feature(zend_string * feature,zend_string * version)1252 bool dom_has_feature(zend_string *feature, zend_string *version)
1253 {
1254 if (zend_string_equals_literal(version, "1.0")
1255 || zend_string_equals_literal(version, "2.0")
1256 || zend_string_equals_literal(version, "")
1257 ) {
1258 if (zend_string_equals_literal_ci(feature, "XML")
1259 || (zend_string_equals_literal_ci(feature, "Core") && zend_string_equals_literal(version, "1.0"))
1260 ) {
1261 return true;
1262 }
1263 }
1264
1265 return false;
1266 }
1267 /* }}} end dom_has_feature */
1268
dom_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep,char * ns,char * local,int * cur,int index)1269 xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep, char *ns, char *local, int *cur, int index) /* {{{ */
1270 {
1271 xmlNodePtr ret = NULL;
1272
1273 while (nodep != NULL && (*cur <= index || index == -1)) {
1274 if (nodep->type == XML_ELEMENT_NODE) {
1275 if (xmlStrEqual(nodep->name, (xmlChar *)local) || xmlStrEqual((xmlChar *)"*", (xmlChar *)local)) {
1276 if (ns == NULL || (!strcmp(ns, "") && nodep->ns == NULL) || (nodep->ns != NULL && (xmlStrEqual(nodep->ns->href, (xmlChar *)ns) || xmlStrEqual((xmlChar *)"*", (xmlChar *)ns)))) {
1277 if (*cur == index) {
1278 ret = nodep;
1279 break;
1280 }
1281 (*cur)++;
1282 }
1283 }
1284 ret = dom_get_elements_by_tag_name_ns_raw(nodep->children, ns, local, cur, index);
1285 if (ret != NULL) {
1286 break;
1287 }
1288 }
1289 nodep = nodep->next;
1290 }
1291 return ret;
1292 }
1293 /* }}} */
1294 /* }}} end dom_element_get_elements_by_tag_name_ns_raw */
1295
is_empty_node(xmlNodePtr nodep)1296 static inline bool is_empty_node(xmlNodePtr nodep)
1297 {
1298 xmlChar *strContent = xmlNodeGetContent(nodep);
1299 bool ret = strContent == NULL || *strContent == '\0';
1300 xmlFree(strContent);
1301 return ret;
1302 }
1303
1304 /* {{{ void dom_normalize (xmlNodePtr nodep) */
dom_normalize(xmlNodePtr nodep)1305 void dom_normalize (xmlNodePtr nodep)
1306 {
1307 xmlNodePtr child, nextp, newnextp;
1308 xmlAttrPtr attr;
1309 xmlChar *strContent;
1310
1311 child = nodep->children;
1312 while(child != NULL) {
1313 switch (child->type) {
1314 case XML_TEXT_NODE:
1315 nextp = child->next;
1316 while (nextp != NULL) {
1317 if (nextp->type == XML_TEXT_NODE) {
1318 newnextp = nextp->next;
1319 strContent = xmlNodeGetContent(nextp);
1320 xmlNodeAddContent(child, strContent);
1321 xmlFree(strContent);
1322 xmlUnlinkNode(nextp);
1323 php_libxml_node_free_resource(nextp);
1324 nextp = newnextp;
1325 } else {
1326 break;
1327 }
1328 }
1329 if (is_empty_node(child)) {
1330 nextp = child->next;
1331 xmlUnlinkNode(child);
1332 php_libxml_node_free_resource(child);
1333 child = nextp;
1334 continue;
1335 }
1336 break;
1337 case XML_ELEMENT_NODE:
1338 dom_normalize (child);
1339 attr = child->properties;
1340 while (attr != NULL) {
1341 dom_normalize((xmlNodePtr) attr);
1342 attr = attr->next;
1343 }
1344 break;
1345 case XML_ATTRIBUTE_NODE:
1346 dom_normalize (child);
1347 break;
1348 default:
1349 break;
1350 }
1351 child = child->next;
1352 }
1353 }
1354 /* }}} end dom_normalize */
1355
1356
1357 /* {{{ void dom_set_old_ns(xmlDoc *doc, xmlNs *ns) */
dom_set_old_ns(xmlDoc * doc,xmlNs * ns)1358 void dom_set_old_ns(xmlDoc *doc, xmlNs *ns) {
1359 xmlNs *cur;
1360
1361 if (doc == NULL)
1362 return;
1363
1364 if (doc->oldNs == NULL) {
1365 doc->oldNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
1366 if (doc->oldNs == NULL) {
1367 return;
1368 }
1369 memset(doc->oldNs, 0, sizeof(xmlNs));
1370 doc->oldNs->type = XML_LOCAL_NAMESPACE;
1371 doc->oldNs->href = xmlStrdup(XML_XML_NAMESPACE);
1372 doc->oldNs->prefix = xmlStrdup((const xmlChar *)"xml");
1373 }
1374
1375 cur = doc->oldNs;
1376 while (cur->next != NULL) {
1377 cur = cur->next;
1378 }
1379 cur->next = ns;
1380 }
1381 /* }}} end dom_set_old_ns */
1382
dom_reconcile_ns(xmlDocPtr doc,xmlNodePtr nodep)1383 void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep) /* {{{ */
1384 {
1385 xmlNsPtr nsptr, nsdftptr, curns, prevns = NULL;
1386
1387 if (nodep->type == XML_ELEMENT_NODE) {
1388 /* Following if block primarily used for inserting nodes created via createElementNS */
1389 if (nodep->nsDef != NULL) {
1390 curns = nodep->nsDef;
1391 while (curns) {
1392 nsdftptr = curns->next;
1393 if (curns->href != NULL) {
1394 if((nsptr = xmlSearchNsByHref(doc, nodep->parent, curns->href)) &&
1395 (curns->prefix == NULL || xmlStrEqual(nsptr->prefix, curns->prefix))) {
1396 curns->next = NULL;
1397 if (prevns == NULL) {
1398 nodep->nsDef = nsdftptr;
1399 } else {
1400 prevns->next = nsdftptr;
1401 }
1402 dom_set_old_ns(doc, curns);
1403 curns = prevns;
1404 }
1405 }
1406 prevns = curns;
1407 curns = nsdftptr;
1408 }
1409 }
1410 xmlReconciliateNs(doc, nodep);
1411 }
1412 }
1413 /* }}} */
1414
1415 /*
1416 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
1417
1418 NAMESPACE_ERR: Raised if
1419
1420 1. the qualifiedName is a malformed qualified name
1421 2. the qualifiedName has a prefix and the namespaceURI is null
1422 */
1423
1424 /* {{{ int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len) */
dom_check_qname(char * qname,char ** localname,char ** prefix,int uri_len,int name_len)1425 int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len) {
1426 if (name_len == 0) {
1427 return NAMESPACE_ERR;
1428 }
1429
1430 *localname = (char *)xmlSplitQName2((xmlChar *)qname, (xmlChar **) prefix);
1431 if (*localname == NULL) {
1432 *localname = (char *)xmlStrdup((xmlChar *)qname);
1433 if (*prefix == NULL && uri_len == 0) {
1434 return 0;
1435 }
1436 }
1437
1438 /* 1 */
1439 if (xmlValidateQName((xmlChar *) qname, 0) != 0) {
1440 return NAMESPACE_ERR;
1441 }
1442
1443 /* 2 */
1444 if (*prefix != NULL && uri_len == 0) {
1445 return NAMESPACE_ERR;
1446 }
1447
1448 return 0;
1449 }
1450 /* }}} */
1451
1452 /*
1453 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
1454
1455 NAMESPACE_ERR: Raised if
1456
1457 3. the qualifiedName has a prefix that is "xml" and the namespaceURI is different from "http://www.w3.org/XML/1998/namespace" [XML Namespaces]
1458 4. the qualifiedName or its prefix is "xmlns" and the namespaceURI is different from "http://www.w3.org/2000/xmlns/"
1459 5. the namespaceURI is "http://www.w3.org/2000/xmlns/" and neither the qualifiedName nor its prefix is "xmlns".
1460 */
1461
1462 /* {{{ xmlNsPtr dom_get_ns(xmlNodePtr nodep, char *uri, int *errorcode, char *prefix) */
dom_get_ns(xmlNodePtr nodep,char * uri,int * errorcode,char * prefix)1463 xmlNsPtr dom_get_ns(xmlNodePtr nodep, char *uri, int *errorcode, char *prefix) {
1464 xmlNsPtr nsptr = NULL;
1465
1466 *errorcode = 0;
1467
1468 if (! ((prefix && !strcmp (prefix, "xml") && strcmp(uri, (char *)XML_XML_NAMESPACE)) ||
1469 (prefix && !strcmp (prefix, "xmlns") && strcmp(uri, (char *)DOM_XMLNS_NAMESPACE)) ||
1470 (prefix && !strcmp(uri, (char *)DOM_XMLNS_NAMESPACE) && strcmp (prefix, "xmlns")))) {
1471 nsptr = xmlNewNs(nodep, (xmlChar *)uri, (xmlChar *)prefix);
1472 }
1473
1474 if (nsptr == NULL) {
1475 *errorcode = NAMESPACE_ERR;
1476 }
1477
1478 return nsptr;
1479
1480 }
1481 /* }}} end dom_get_ns */
1482
1483 /* {{{ xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName) */
dom_get_nsdecl(xmlNode * node,xmlChar * localName)1484 xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName) {
1485 xmlNsPtr cur;
1486 xmlNs *ret = NULL;
1487 if (node == NULL)
1488 return NULL;
1489
1490 if (localName == NULL || xmlStrEqual(localName, (xmlChar *)"")) {
1491 cur = node->nsDef;
1492 while (cur != NULL) {
1493 if (cur->prefix == NULL && cur->href != NULL) {
1494 ret = cur;
1495 break;
1496 }
1497 cur = cur->next;
1498 }
1499 } else {
1500 cur = node->nsDef;
1501 while (cur != NULL) {
1502 if (cur->prefix != NULL && xmlStrEqual(localName, cur->prefix)) {
1503 ret = cur;
1504 break;
1505 }
1506 cur = cur->next;
1507 }
1508 }
1509 return ret;
1510 }
1511 /* }}} end dom_get_nsdecl */
1512
dom_nodelist_read_dimension(zend_object * object,zval * offset,int type,zval * rv)1513 static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */
1514 {
1515 zval offset_copy;
1516
1517 if (!offset) {
1518 zend_throw_error(NULL, "Cannot access node list without offset");
1519 return NULL;
1520 }
1521
1522 ZVAL_LONG(&offset_copy, zval_get_long(offset));
1523
1524 zend_call_method_with_1_params(object, object->ce, NULL, "item", rv, &offset_copy);
1525
1526 return rv;
1527 } /* }}} end dom_nodelist_read_dimension */
1528
dom_nodelist_has_dimension(zend_object * object,zval * member,int check_empty)1529 static int dom_nodelist_has_dimension(zend_object *object, zval *member, int check_empty)
1530 {
1531 zend_long offset = zval_get_long(member);
1532 zval rv;
1533
1534 if (offset < 0) {
1535 return 0;
1536 } else {
1537 zval *length = zend_read_property(
1538 object->ce, object, "length", sizeof("length") - 1, 0, &rv);
1539 return length && offset < Z_LVAL_P(length);
1540 }
1541 } /* }}} end dom_nodelist_has_dimension */
1542
1543 #endif /* HAVE_DOM */
1544