]> granicus.if.org Git - php/commitdiff
- Turns out the external entity loader is not a per-thread global but a true
authorGustavo André dos Santos Lopes <cataphract@php.net>
Tue, 30 Aug 2011 01:08:22 +0000 (01:08 +0000)
committerGustavo André dos Santos Lopes <cataphract@php.net>
Tue, 30 Aug 2011 01:08:22 +0000 (01:08 +0000)
  global. Changed code accordingly; however, applications that embed PHP and
  also use libxml2 may be affected negatively.

ext/libxml/libxml.c
ext/libxml/php_libxml.h

index 39f3ee2f119894d8b549e097363d3c0b0b14fbb8..cd91570a9a37e68aec91bff58c89971d325985c2 100644 (file)
@@ -55,6 +55,7 @@
 /* a true global for initialization */
 static int _php_libxml_initialized = 0;
 static int _php_libxml_per_request_initialization = 1;
+static xmlExternalEntityLoader _php_libxml_default_entity_loader;
 
 typedef struct _php_libxml_func_handler {
        php_libxml_export_node export_func;
@@ -268,7 +269,6 @@ static PHP_GINIT_FUNCTION(libxml)
        libxml_globals->stream_context = NULL;
        libxml_globals->error_buffer.c = NULL;
        libxml_globals->error_list = NULL;
-       libxml_globals->defaultEntityLoader = NULL;
        libxml_globals->entity_loader.fci.size = 0;
 }
 
@@ -549,6 +549,131 @@ static void php_libxml_internal_error_handler(int error_type, void *ctx, const c
        }
 }
 
+static xmlParserInputPtr _php_libxml_external_entity_loader(const char *URL,
+               const char *ID, xmlParserCtxtPtr context)
+{
+    xmlParserInputPtr  ret                     = NULL;
+    const char                 *resource       = NULL;
+       zval                            *public         = NULL,
+                                               *system         = NULL,
+                                               *ctxzv          = NULL,
+                                               **params[]      = {&public, &system, &ctxzv},
+                                               *retval_ptr     = NULL;
+       int                                     retval;
+       zend_fcall_info         *fci;
+       TSRMLS_FETCH();
+
+       fci = &LIBXML(entity_loader).fci;
+       
+       if (fci->size == 0) {
+               /* no custom user-land callback set up; delegate to original loader */
+               return _php_libxml_default_entity_loader(URL, ID, context);
+       }
+
+       ALLOC_INIT_ZVAL(public);
+       if (ID != NULL) {
+               ZVAL_STRING(public, ID, 1);
+       }
+       ALLOC_INIT_ZVAL(system);
+       if (URL != NULL) {
+               ZVAL_STRING(system, URL, 1);
+       }
+       MAKE_STD_ZVAL(ctxzv);
+       array_init_size(ctxzv, 4);
+
+#define ADD_NULL_OR_STRING_KEY(memb) \
+       if (context->memb == NULL) { \
+               add_assoc_null_ex(ctxzv, #memb, sizeof(#memb)); \
+       } else { \
+               add_assoc_string_ex(ctxzv, #memb, sizeof(#memb), \
+                               (char *)context->memb, 1); \
+       }
+       
+       ADD_NULL_OR_STRING_KEY(directory)
+       ADD_NULL_OR_STRING_KEY(intSubName)
+       ADD_NULL_OR_STRING_KEY(extSubURI)
+       ADD_NULL_OR_STRING_KEY(extSubSystem)
+       
+#undef ADD_NULL_OR_STRING_KEY
+       
+       fci->retval_ptr_ptr     = &retval_ptr;
+       fci->params                     = params;
+       fci->param_count        = sizeof(params)/sizeof(*params);
+       fci->no_separation      = 1;
+       
+       retval = zend_call_function(fci, &LIBXML(entity_loader).fcc TSRMLS_CC);
+       if (retval != SUCCESS || fci->retval_ptr_ptr == NULL) {
+               php_libxml_ctx_error(context,
+                               "Call to user entity loader callback '%s' has failed",
+                               fci->function_name);
+       } else {
+               retval_ptr = *fci->retval_ptr_ptr;
+               if (retval_ptr == NULL) {
+                       php_libxml_ctx_error(context,
+                                       "Call to user entity loader callback '%s' has failed; "
+                                       "probably it has thrown an exception",
+                                       fci->function_name);
+               } else if (Z_TYPE_P(retval_ptr) == IS_STRING) {
+is_string:
+                       resource = Z_STRVAL_P(retval_ptr);
+               } else if (Z_TYPE_P(retval_ptr) == IS_RESOURCE) {
+                       php_stream *stream;
+                       php_stream_from_zval_no_verify(stream, &retval_ptr);
+                       if (stream == NULL) {
+                               php_libxml_ctx_error(context,
+                                               "The user entity loader callback '%s' has returned a "
+                                               "resource, but it is not a stream",
+                                               fci->function_name);
+                       } else {
+                               /* TODO: allow storing the encoding in the stream context? */
+                               xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
+                               xmlParserInputBufferPtr pib = xmlAllocParserInputBuffer(enc);
+                               if (pib == NULL) {
+                                       php_libxml_ctx_error(context, "Could not allocate parser "
+                                                       "input buffer");
+                               } else {
+                                       /* make stream not being closed when the zval is freed */
+                                       zend_list_addref(stream->rsrc_id);
+                                       pib->context = stream;
+                                       pib->readcallback = php_libxml_streams_IO_read;
+                                       pib->closecallback = php_libxml_streams_IO_close;
+                                       
+                                       ret = xmlNewIOInputStream(context, pib, enc);
+                                       if (ret == NULL) {
+                                               xmlFreeParserInputBuffer(pib);
+                                       }
+                               }
+                       }
+               } else if (Z_TYPE_P(retval_ptr) != IS_NULL) {
+                       /* retval not string nor resource nor null; convert to string */
+                       SEPARATE_ZVAL(&retval_ptr);
+               convert_to_string(retval_ptr);
+                       goto is_string;
+               } /* else is null; don't try anything */
+       }
+
+       if (ret == NULL) {
+               if (resource == NULL) {
+                       if (ID == NULL) {
+                               ID = "NULL";
+                       }
+                       php_libxml_ctx_error(context,
+                                       "Failed to load external entity \"%s\"\n", ID);
+               } else {
+                       /* we got the resource in the form of a string; open it */
+                       ret = xmlNewInputFromFile(context, resource);
+               }
+       }
+
+       zval_ptr_dtor(&public);
+       zval_ptr_dtor(&system);
+       zval_ptr_dtor(&ctxzv);
+       if (retval_ptr != NULL) {
+               zval_ptr_dtor(&retval_ptr);
+       }
+    return ret;
+}
+
 PHP_LIBXML_API void php_libxml_ctx_error(void *ctx, const char *msg, ...)
 {
        va_list args;
@@ -586,6 +711,9 @@ PHP_LIBXML_API void php_libxml_initialize(void)
        if (!_php_libxml_initialized) {
                /* we should be the only one's to ever init!! */
                xmlInitParser();
+               
+               _php_libxml_default_entity_loader = xmlGetExternalEntityLoader();
+               xmlSetExternalEntityLoader(_php_libxml_external_entity_loader);
 
                zend_hash_init(&php_libxml_exports, 0, NULL, NULL, 1);
 
@@ -926,126 +1054,6 @@ static PHP_FUNCTION(libxml_disable_entity_loader)
 }
 /* }}} */
 
-static xmlParserInputPtr _php_libxml_user_entity_loader(const char *URL,
-               const char *ID, xmlParserCtxtPtr context)
-{
-    xmlParserInputPtr  ret                     = NULL;
-    const char                 *resource       = NULL;
-       zval                            *public         = NULL,
-                                               *system         = NULL,
-                                               *ctxzv          = NULL,
-                                               **params[]      = {&public, &system, &ctxzv},
-                                               *retval_ptr     = NULL;
-       int                                     retval;
-       zend_fcall_info         *fci;
-       TSRMLS_FETCH();
-
-       fci = &LIBXML(entity_loader).fci;
-
-       ALLOC_INIT_ZVAL(public);
-       if (ID != NULL) {
-               ZVAL_STRING(public, ID, 1);
-       }
-       ALLOC_INIT_ZVAL(system);
-       if (URL != NULL) {
-               ZVAL_STRING(system, URL, 1);
-       }
-       MAKE_STD_ZVAL(ctxzv);
-       array_init_size(ctxzv, 4);
-
-#define ADD_NULL_OR_STRING_KEY(memb) \
-       if (context->memb == NULL) { \
-               add_assoc_null_ex(ctxzv, #memb, sizeof(#memb)); \
-       } else { \
-               add_assoc_string_ex(ctxzv, #memb, sizeof(#memb), \
-                               (char *)context->memb, 1); \
-       }
-       
-       ADD_NULL_OR_STRING_KEY(directory)
-       ADD_NULL_OR_STRING_KEY(intSubName)
-       ADD_NULL_OR_STRING_KEY(extSubURI)
-       ADD_NULL_OR_STRING_KEY(extSubSystem)
-       
-#undef ADD_NULL_OR_STRING_KEY
-       
-       fci->retval_ptr_ptr     = &retval_ptr;
-       fci->params                     = params;
-       fci->param_count        = sizeof(params)/sizeof(*params);
-       fci->no_separation      = 1;
-       
-       retval = zend_call_function(fci, &LIBXML(entity_loader).fcc TSRMLS_CC);
-       if (retval != SUCCESS || fci->retval_ptr_ptr == NULL) {
-               php_libxml_ctx_error(context,
-                               "Call to user entity loader callback '%s' has failed",
-                               fci->function_name);
-       } else {
-               retval_ptr = *fci->retval_ptr_ptr;
-               if (retval_ptr == NULL) {
-                       php_libxml_ctx_error(context,
-                                       "Call to user entity loader callback '%s' has failed; "
-                                       "probably it has thrown an exception",
-                                       fci->function_name);
-               } else if (Z_TYPE_P(retval_ptr) == IS_STRING) {
-is_string:
-                       resource = Z_STRVAL_P(retval_ptr);
-               } else if (Z_TYPE_P(retval_ptr) == IS_RESOURCE) {
-                       php_stream *stream;
-                       php_stream_from_zval_no_verify(stream, &retval_ptr);
-                       if (stream == NULL) {
-                               php_libxml_ctx_error(context,
-                                               "The user entity loader callback '%s' has returned a "
-                                               "resource, but it is not a stream",
-                                               fci->function_name);
-                       } else {
-                               /* TODO: allow storing the encoding in the stream context? */
-                               xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
-                               xmlParserInputBufferPtr pib = xmlAllocParserInputBuffer(enc);
-                               if (pib == NULL) {
-                                       php_libxml_ctx_error(context, "Could not allocate parser "
-                                                       "input buffer");
-                               } else {
-                                       /* make stream not being closed when the zval is freed */
-                                       zend_list_addref(stream->rsrc_id);
-                                       pib->context = stream;
-                                       pib->readcallback = php_libxml_streams_IO_read;
-                                       pib->closecallback = php_libxml_streams_IO_close;
-                                       
-                                       ret = xmlNewIOInputStream(context, pib, enc);
-                                       if (ret == NULL) {
-                                               xmlFreeParserInputBuffer(pib);
-                                       }
-                               }
-                       }
-               } else if (Z_TYPE_P(retval_ptr) != IS_NULL) {
-                       /* retval not string nor resource nor null; convert to string */
-                       SEPARATE_ZVAL(&retval_ptr);
-               convert_to_string(retval_ptr);
-                       goto is_string;
-               } /* else is null; don't try anything */
-       }
-
-       if (ret == NULL) {
-               if (resource == NULL) {
-                       if (ID == NULL) {
-                               ID = "NULL";
-                       }
-                       php_libxml_ctx_error(context,
-                                       "Failed to load external entity \"%s\"\n", ID);
-               } else {
-                       /* we got the resource in the form of a string; open it */
-                       ret = xmlNewInputFromFile(context, resource);
-               }
-       }
-
-       zval_ptr_dtor(&public);
-       zval_ptr_dtor(&system);
-       zval_ptr_dtor(&ctxzv);
-       if (retval_ptr != NULL) {
-               zval_ptr_dtor(&retval_ptr);
-       }
-    return ret;
-}
-
 /* {{{ proto void libxml_set_external_entity_loader(callback resolver_function) 
    Changes the default external entity loader */
 static PHP_FUNCTION(libxml_set_external_entity_loader)
@@ -1057,21 +1065,15 @@ static PHP_FUNCTION(libxml_set_external_entity_loader)
                return;
        }
        
+       _php_libxml_destroy_fci(&LIBXML(entity_loader).fci);
+       
        if (fci.size > 0) { /* argument not null */
-               /* save for later invocations with NULL */
-               if (LIBXML(defaultEntityLoader) == NULL) {
-                       LIBXML(defaultEntityLoader) = xmlGetExternalEntityLoader();
-               }
-               _php_libxml_destroy_fci(&LIBXML(entity_loader).fci);
                LIBXML(entity_loader).fci = fci;
                Z_ADDREF_P(fci.function_name);
                if (fci.object_ptr != NULL) {
                        Z_ADDREF_P(fci.object_ptr);
                }
                LIBXML(entity_loader).fcc = fcc;
-               xmlSetExternalEntityLoader(_php_libxml_user_entity_loader);
-       } else {
-               xmlSetExternalEntityLoader(LIBXML(defaultEntityLoader));
        }
        
        RETURN_TRUE;
index 8fe7fe4ad66a855f729d7f53ea7d5c9515274f1b..f1c8b7af69b61ddc1f743713e67540bdc5eeedd4 100644 (file)
@@ -43,7 +43,6 @@ ZEND_BEGIN_MODULE_GLOBALS(libxml)
        zval *stream_context;
        smart_str error_buffer;
        zend_llist *error_list;
-       xmlExternalEntityLoader defaultEntityLoader; /* saved here to allow it restored */
        struct _php_libxml_entity_resolver {
                zend_fcall_info                 fci;
                zend_fcall_info_cache   fcc;