@@ -89,6 +89,7 @@ static HashTable dom_xpath_prop_handlers;
8989
9090static zend_object * dom_objects_namespace_node_new (zend_class_entry * class_type );
9191static void dom_object_namespace_node_free_storage (zend_object * object );
92+ static xmlNodePtr php_dom_create_fake_namespace_decl_node_ptr (xmlNodePtr nodep , xmlNsPtr original );
9293
9394typedef int (* dom_read_t )(dom_object * obj , zval * retval );
9495typedef int (* dom_write_t )(dom_object * obj , zval * newval );
@@ -477,6 +478,19 @@ PHP_FUNCTION(dom_import_simplexml)
477478
478479static dom_object * dom_objects_set_class (zend_class_entry * class_type );
479480
481+ static void dom_update_refcount_after_clone (dom_object * original , xmlNodePtr original_node , dom_object * clone , xmlNodePtr cloned_node )
482+ {
483+ /* If we cloned a document then we must create new doc proxy */
484+ if (cloned_node -> doc == original_node -> doc ) {
485+ clone -> document = original -> document ;
486+ }
487+ php_libxml_increment_doc_ref ((php_libxml_node_object * )clone , cloned_node -> doc );
488+ php_libxml_increment_node_ptr ((php_libxml_node_object * )clone , cloned_node , (void * )clone );
489+ if (original -> document != clone -> document ) {
490+ dom_copy_doc_props (original -> document , clone -> document );
491+ }
492+ }
493+
480494static zend_object * dom_objects_store_clone_obj (zend_object * zobject ) /* {{{ */
481495{
482496 dom_object * intern = php_dom_obj_from_obj (zobject );
@@ -489,15 +503,7 @@ static zend_object *dom_objects_store_clone_obj(zend_object *zobject) /* {{{ */
489503 if (node != NULL ) {
490504 xmlNodePtr cloned_node = xmlDocCopyNode (node , node -> doc , 1 );
491505 if (cloned_node != NULL ) {
492- /* If we cloned a document then we must create new doc proxy */
493- if (cloned_node -> doc == node -> doc ) {
494- clone -> document = intern -> document ;
495- }
496- php_libxml_increment_doc_ref ((php_libxml_node_object * )clone , cloned_node -> doc );
497- php_libxml_increment_node_ptr ((php_libxml_node_object * )clone , cloned_node , (void * )clone );
498- if (intern -> document != clone -> document ) {
499- dom_copy_doc_props (intern -> document , clone -> document );
500- }
506+ dom_update_refcount_after_clone (intern , node , clone , cloned_node );
501507 }
502508
503509 }
@@ -509,6 +515,26 @@ static zend_object *dom_objects_store_clone_obj(zend_object *zobject) /* {{{ */
509515}
510516/* }}} */
511517
518+ static zend_object * dom_object_namespace_node_clone_obj (zend_object * zobject )
519+ {
520+ dom_object_namespace_node * intern = php_dom_namespace_node_obj_from_obj (zobject );
521+ zend_object * clone = dom_objects_namespace_node_new (intern -> dom .std .ce );
522+ dom_object_namespace_node * clone_intern = php_dom_namespace_node_obj_from_obj (clone );
523+
524+ xmlNodePtr original_node = dom_object_get_node (& intern -> dom );
525+ ZEND_ASSERT (original_node -> type == XML_NAMESPACE_DECL );
526+ xmlNodePtr cloned_node = php_dom_create_fake_namespace_decl_node_ptr (original_node -> parent , original_node -> ns );
527+
528+ if (intern -> parent_intern ) {
529+ clone_intern -> parent_intern = intern -> parent_intern ;
530+ GC_ADDREF (& clone_intern -> parent_intern -> std );
531+ }
532+ dom_update_refcount_after_clone (& intern -> dom , original_node , & clone_intern -> dom , cloned_node );
533+
534+ zend_objects_clone_members (clone , & intern -> dom .std );
535+ return clone ;
536+ }
537+
512538static void dom_copy_prop_handler (zval * zv ) /* {{{ */
513539{
514540 dom_prop_handler * hnd = Z_PTR_P (zv );
@@ -577,6 +603,7 @@ PHP_MINIT_FUNCTION(dom)
577603 memcpy (& dom_object_namespace_node_handlers , & dom_object_handlers , sizeof (zend_object_handlers ));
578604 dom_object_namespace_node_handlers .offset = XtOffsetOf (dom_object_namespace_node , dom .std );
579605 dom_object_namespace_node_handlers .free_obj = dom_object_namespace_node_free_storage ;
606+ dom_object_namespace_node_handlers .clone_obj = dom_object_namespace_node_clone_obj ;
580607
581608 zend_hash_init (& classes , 0 , NULL , NULL , 1 );
582609
@@ -1579,8 +1606,7 @@ xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName) {
15791606}
15801607/* }}} end dom_get_nsdecl */
15811608
1582- /* Note: Assumes the additional lifetime was already added in the caller. */
1583- xmlNodePtr php_dom_create_fake_namespace_decl (xmlNodePtr nodep , xmlNsPtr original , zval * return_value , dom_object * parent_intern )
1609+ static xmlNodePtr php_dom_create_fake_namespace_decl_node_ptr (xmlNodePtr nodep , xmlNsPtr original )
15841610{
15851611 xmlNodePtr attrp ;
15861612 xmlNsPtr curns = xmlNewNs (NULL , original -> href , NULL );
@@ -1593,11 +1619,16 @@ xmlNodePtr php_dom_create_fake_namespace_decl(xmlNodePtr nodep, xmlNsPtr origina
15931619 attrp -> type = XML_NAMESPACE_DECL ;
15941620 attrp -> parent = nodep ;
15951621 attrp -> ns = curns ;
1622+ return attrp ;
1623+ }
15961624
1625+ /* Note: Assumes the additional lifetime was already added in the caller. */
1626+ xmlNodePtr php_dom_create_fake_namespace_decl (xmlNodePtr nodep , xmlNsPtr original , zval * return_value , dom_object * parent_intern )
1627+ {
1628+ xmlNodePtr attrp = php_dom_create_fake_namespace_decl_node_ptr (nodep , original );
15971629 php_dom_create_object (attrp , return_value , parent_intern );
15981630 /* This object must exist, because we just created an object for it via php_dom_create_object(). */
1599- dom_object * obj = ((php_libxml_node_ptr * )attrp -> _private )-> _private ;
1600- php_dom_namespace_node_obj_from_obj (& obj -> std )-> parent_intern = parent_intern ;
1631+ php_dom_namespace_node_obj_from_obj (Z_OBJ_P (return_value ))-> parent_intern = parent_intern ;
16011632 return attrp ;
16021633}
16031634
0 commit comments