]> granicus.if.org Git - php/commitdiff
Fixed for Bug #26384 (domxslt->process causes segfault with xsl:key)
authorChristian Stocker <chregu@php.net>
Sat, 29 Nov 2003 16:37:37 +0000 (16:37 +0000)
committerChristian Stocker <chregu@php.net>
Sat, 29 Nov 2003 16:37:37 +0000 (16:37 +0000)
ext/xsl/php_xsl.c
ext/xsl/php_xsl.h
ext/xsl/xsltprocessor.c

index 34c8bd8f765255021ad0a2b211b4579ea59737f1..3fc272bc94a068e42a6e97410c080afc405e65d7 100644 (file)
@@ -113,6 +113,7 @@ zend_object_value xsl_objects_new(zend_class_entry *class_type TSRMLS_DC)
        intern->ptr = NULL;
        intern->prop_handler = NULL;
        intern->parameter = NULL;
+       intern->hasKeys = 0;
 
        ALLOC_HASHTABLE(intern->std.properties);
        zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
@@ -145,6 +146,10 @@ PHP_MINIT_FUNCTION(xsl)
        xsltRegisterExtModuleFunction ((const xmlChar *) "function",
                                   (const xmlChar *) "http://php.net/xsl",
                                   xsl_ext_function_object_php);
+       REGISTER_LONG_CONSTANT("XSL_CLONE_AUTO",      0,     CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSL_CLONE_NEVER",    -1,     CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("XSL_CLONE_ALWAYS",    1,     CONST_CS | CONST_PERSISTENT);
 
        return SUCCESS;
 }
index cdcea90f423d67ef291d1055d012b1b194ee12b7..96eb6cfd3ea9aab39426054edfa4d78154746501 100644 (file)
@@ -54,7 +54,8 @@ typedef struct _xsl_object {
        void *ptr;
        HashTable *prop_handler;
        zend_object_handle handle;
-    HashTable *parameter;
+       HashTable *parameter;
+       int hasKeys;
 } xsl_object;
 
 void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC);
@@ -72,8 +73,8 @@ entry = zend_register_internal_class_ex(&ce, parent_ce, NULL TSRMLS_CC);
                RETURN_FALSE; \
        }
 
-    
-    
+
+
 PHP_MINIT_FUNCTION(xsl);
 PHP_MSHUTDOWN_FUNCTION(xsl);
 PHP_RINIT_FUNCTION(xsl);
index c08bf9524ae2b31c7322049b776f6f899ff26851..eb98018046274a56022fed7c7af151ba7ed03666 100644 (file)
@@ -129,8 +129,11 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
        xsltStylesheetPtr sheetp, oldsheetp;
        xsl_object *intern;
        php_libxml_node_object *docobj;
-       int prevSubstValue, prevExtDtdValue;
-       
+       int prevSubstValue, prevExtDtdValue, clone_docu;
+       xmlNode *nodep;
+       zend_object_handlers *std_hnd;
+       zval *cloneDocu, *member;
+
        DOM_GET_THIS(id);
        
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) {
@@ -143,10 +146,10 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
        stylesheet document otherwise the node proxies will be a mess */
        newdoc = xmlCopyDoc(doc, 1);
        xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL);
-
        prevSubstValue = xmlSubstituteEntitiesDefault(1);
        prevExtDtdValue = xmlLoadExtDtdDefaultValue;
        xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+
        sheetp = xsltParseStylesheetDoc(newdoc);
        xmlSubstituteEntitiesDefault(prevSubstValue);
        xmlLoadExtDtdDefaultValue = prevExtDtdValue;
@@ -157,6 +160,28 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
        }
 
        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC); 
+
+       std_hnd = zend_get_std_object_handlers();
+       MAKE_STD_ZVAL(member);
+       ZVAL_STRING(member, "cloneDocument", 0);
+       cloneDocu = std_hnd->read_property(id, member, 1 TSRMLS_CC);
+       convert_to_long(cloneDocu);
+       efree(member);
+       clone_docu = Z_LVAL_P(cloneDocu);
+       if (clone_docu == 0) {
+               /* check if the stylesheet is using xsl:key, if yes, we have to clone the document _always_ before a transformation */
+               nodep = xmlDocGetRootElement(sheetp->doc)->children;
+               while (nodep) {
+                       if (nodep->type == XML_ELEMENT_NODE && xmlStrEqual(nodep->name, "key") && xmlStrEqual(nodep->ns->href, XSLT_NAMESPACE)) {
+                               intern->hasKeys = 1;
+                               break;
+                       }
+                       nodep = nodep->next;
+               }
+       } else {
+               intern->hasKeys = clone_docu;
+       }
+       
        if ((oldsheetp = (xsltStylesheetPtr)intern->ptr)) { 
                /* free wrapper */
                if (((xsltStylesheetPtr) intern->ptr)->_private != NULL) {
@@ -181,7 +206,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
        xmlDoc *doc = NULL;
        xmlDoc *newdocp;
        xsltStylesheetPtr sheetp;
-       int ret, clone = 0;
+       int ret, clone;
        char **params = NULL;
        xsl_object *intern;
        php_libxml_node_object *docobj;
@@ -190,7 +215,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
        sheetp = (xsltStylesheetPtr) intern->ptr;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|l", &docp, &clone) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) {
                RETURN_FALSE;
        }
        DOC_GET_OBJ(doc, docp, xmlDocPtr, docobj);
@@ -199,11 +224,11 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
                params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC);
        }
 
-       if (clone == 1) {
+       if (intern->hasKeys == 1) {
                doc = xmlCopyDoc(doc, 1);
        }
        newdocp = xsltApplyStylesheet(sheetp, doc, (const char**) params);
-       if (clone == 1) {
+       if (intern->hasKeys == 1) {
                xmlFreeDoc(doc);
        }
 
@@ -233,7 +258,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
        xmlDoc *doc = NULL;
        xmlDoc *newdocp;
        xsltStylesheetPtr sheetp;
-       int ret, uri_len, clone = 0;
+       int ret, uri_len, clone;
        char **params = NULL, *uri;
        xsl_object *intern;
        php_libxml_node_object *docobj;
@@ -242,7 +267,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
        sheetp = (xsltStylesheetPtr) intern->ptr;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "os|l", &docp, &uri, &uri_len, &clone) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "os", &docp, &uri, &uri_len) == FAILURE) {
                RETURN_FALSE;
        }
 
@@ -252,13 +277,13 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
                params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC);
        }
 
-       if (clone == 1) {
+       if (intern->hasKeys == 1) {
                doc = xmlCopyDoc(doc, 1);
        }
 
        newdocp = xsltApplyStylesheet(sheetp, doc, (const char**)params);
 
-       if (clone == 1) {
+       if (intern->hasKeys == 1) {
                xmlFreeDoc(doc);
        }
 
@@ -289,7 +314,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
        xmlDoc *doc = NULL;
        xmlDoc *newdocp;
        xsltStylesheetPtr sheetp;
-       int ret, clone = 0;
+       int ret, clone;
        xmlChar *doc_txt_ptr;
        int doc_txt_len;
        char **params = NULL;
@@ -300,7 +325,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
        intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
        sheetp = (xsltStylesheetPtr) intern->ptr;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|l", &docp, &clone) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) {
                RETURN_FALSE;
        }
        DOC_GET_OBJ(doc, docp, xmlDocPtr, docobj);
@@ -309,13 +334,13 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
                params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC);
        }
 
-       if (clone == 1) {
+       if (intern->hasKeys == 1) {
                doc = xmlCopyDoc(doc, 1);
        }
 
        newdocp = xsltApplyStylesheet(sheetp, doc, (const char**)params);
 
-       if (clone == 1) {
+       if (intern->hasKeys == 1) {
                xmlFreeDoc(doc);
        }