PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - libxml - libxml.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 475
Code covered: 85.9 % Executed lines: 408
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Shane Caraveo <shane@php.net>                               |
      16                 :    |          Wez Furlong <wez@thebrainroom.com>                          |
      17                 :    +----------------------------------------------------------------------+
      18                 :  */
      19                 : 
      20                 : /* $Id: libxml.c 282841 2009-06-26 20:27:44Z rrichards $ */
      21                 : 
      22                 : #define IS_EXT_MODULE
      23                 : 
      24                 : #ifdef HAVE_CONFIG_H
      25                 : #include "config.h"
      26                 : #endif
      27                 : 
      28                 : #include "php.h"
      29                 : 
      30                 : #define PHP_XML_INTERNAL
      31                 : #include "zend_variables.h"
      32                 : #include "ext/standard/php_string.h"
      33                 : #include "ext/standard/info.h"
      34                 : #include "ext/standard/file.h"
      35                 : 
      36                 : #if HAVE_LIBXML
      37                 : 
      38                 : #include <libxml/parser.h>
      39                 : #include <libxml/parserInternals.h>
      40                 : #include <libxml/tree.h>
      41                 : #include <libxml/uri.h>
      42                 : #include <libxml/xmlerror.h>
      43                 : #include <libxml/xmlsave.h>
      44                 : #ifdef LIBXML_SCHEMAS_ENABLED
      45                 : #include <libxml/relaxng.h>
      46                 : #endif
      47                 : 
      48                 : #include "php_libxml.h"
      49                 : 
      50                 : #define PHP_LIBXML_ERROR 0
      51                 : #define PHP_LIBXML_CTX_ERROR 1
      52                 : #define PHP_LIBXML_CTX_WARNING 2
      53                 : 
      54                 : /* a true global for initialization */
      55                 : static int _php_libxml_initialized = 0;
      56                 : 
      57                 : typedef struct _php_libxml_func_handler {
      58                 :         php_libxml_export_node export_func;
      59                 : } php_libxml_func_handler;
      60                 : 
      61                 : static HashTable php_libxml_exports;
      62                 : 
      63                 : static ZEND_DECLARE_MODULE_GLOBALS(libxml)
      64                 : static PHP_GINIT_FUNCTION(libxml);
      65                 : 
      66                 : static PHP_FUNCTION(libxml_set_streams_context);
      67                 : static PHP_FUNCTION(libxml_use_internal_errors);
      68                 : static PHP_FUNCTION(libxml_get_last_error);
      69                 : static PHP_FUNCTION(libxml_clear_errors);
      70                 : static PHP_FUNCTION(libxml_get_errors);
      71                 : static PHP_FUNCTION(libxml_disable_entity_loader);
      72                 : 
      73                 : static zend_class_entry *libxmlerror_class_entry;
      74                 : 
      75                 : /* {{{ dynamically loadable module stuff */
      76                 : #ifdef COMPILE_DL_LIBXML
      77                 : ZEND_GET_MODULE(libxml)
      78                 : #endif /* COMPILE_DL_LIBXML */
      79                 : /* }}} */
      80                 : 
      81                 : /* {{{ function prototypes */
      82                 : static PHP_MINIT_FUNCTION(libxml);
      83                 : static PHP_RINIT_FUNCTION(libxml);
      84                 : static PHP_MSHUTDOWN_FUNCTION(libxml);
      85                 : static PHP_RSHUTDOWN_FUNCTION(libxml);
      86                 : static PHP_MINFO_FUNCTION(libxml);
      87                 : 
      88                 : /* }}} */
      89                 : 
      90                 : /* {{{ arginfo */
      91                 : static
      92                 : ZEND_BEGIN_ARG_INFO(arginfo_libxml_set_streams_context, 0)
      93                 :         ZEND_ARG_INFO(0, context)
      94                 : ZEND_END_ARG_INFO()
      95                 : 
      96                 : static
      97                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_libxml_use_internal_errors, 0, 0, 0)
      98                 :         ZEND_ARG_INFO(0, use_errors)
      99                 : ZEND_END_ARG_INFO()
     100                 : 
     101                 : static
     102                 : ZEND_BEGIN_ARG_INFO(arginfo_libxml_get_last_error, 0)
     103                 : ZEND_END_ARG_INFO()
     104                 : 
     105                 : static
     106                 : ZEND_BEGIN_ARG_INFO(arginfo_libxml_get_errors, 0)
     107                 : ZEND_END_ARG_INFO()
     108                 : 
     109                 : static
     110                 : ZEND_BEGIN_ARG_INFO(arginfo_libxml_clear_errors, 0)
     111                 : ZEND_END_ARG_INFO()
     112                 : 
     113                 : static
     114                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_libxml_disable_entity_loader, 0, 0, 0)
     115                 :         ZEND_ARG_INFO(0, disable)
     116                 : ZEND_END_ARG_INFO()
     117                 : 
     118                 : /* }}} */
     119                 : 
     120                 : /* {{{ extension definition structures */
     121                 : static zend_function_entry libxml_functions[] = {
     122                 :         PHP_FE(libxml_set_streams_context, arginfo_libxml_set_streams_context)
     123                 :         PHP_FE(libxml_use_internal_errors, arginfo_libxml_use_internal_errors)
     124                 :         PHP_FE(libxml_get_last_error, arginfo_libxml_get_last_error)
     125                 :         PHP_FE(libxml_clear_errors, arginfo_libxml_clear_errors)
     126                 :         PHP_FE(libxml_get_errors, arginfo_libxml_get_errors)
     127                 :         PHP_FE(libxml_disable_entity_loader, arginfo_libxml_disable_entity_loader)
     128                 :         {NULL, NULL, NULL}
     129                 : };
     130                 : 
     131                 : zend_module_entry libxml_module_entry = {
     132                 :         STANDARD_MODULE_HEADER,
     133                 :         "libxml",                /* extension name */
     134                 :         libxml_functions,        /* extension function list */
     135                 :         PHP_MINIT(libxml),       /* extension-wide startup function */
     136                 :         PHP_MSHUTDOWN(libxml),   /* extension-wide shutdown function */
     137                 :         PHP_RINIT(libxml),       /* per-request startup function */
     138                 :         PHP_RSHUTDOWN(libxml),   /* per-request shutdown function */
     139                 :         PHP_MINFO(libxml),       /* information function */
     140                 :         NO_VERSION_YET,
     141                 :         PHP_MODULE_GLOBALS(libxml), /* globals descriptor */
     142                 :         PHP_GINIT(libxml),          /* globals ctor */
     143                 :         NULL,                       /* globals dtor */
     144                 :         NULL,                       /* post deactivate */
     145                 :         STANDARD_MODULE_PROPERTIES_EX
     146                 : };
     147                 : 
     148                 : /* }}} */
     149                 : 
     150                 : /* {{{ internal functions for interoperability */
     151                 : static int php_libxml_clear_object(php_libxml_node_object *object TSRMLS_DC)
     152               7 : {
     153               7 :         if (object->properties) {
     154               7 :                 object->properties = NULL;
     155                 :         }
     156               7 :         php_libxml_decrement_node_ptr(object TSRMLS_CC);
     157               7 :         return php_libxml_decrement_doc_ref(object TSRMLS_CC);
     158                 : }
     159                 : 
     160                 : static int php_libxml_unregister_node(xmlNodePtr nodep TSRMLS_DC)
     161          201358 : {
     162                 :         php_libxml_node_object *wrapper;
     163                 : 
     164          201358 :         php_libxml_node_ptr *nodeptr = nodep->_private;
     165                 : 
     166          201358 :         if (nodeptr != NULL) {
     167              16 :                 wrapper = nodeptr->_private;
     168              16 :                 if (wrapper) {
     169               7 :                         php_libxml_clear_object(wrapper TSRMLS_CC);
     170                 :                 } else {
     171               9 :                         if (nodeptr->node != NULL && nodeptr->node->type != XML_DOCUMENT_NODE) {
     172               9 :                                 nodeptr->node->_private = NULL;
     173                 :                         }
     174               9 :                         nodeptr->node = NULL;
     175                 :                 }
     176                 :         }
     177                 : 
     178          201358 :         return -1;
     179                 : }
     180                 : 
     181                 : static void php_libxml_node_free(xmlNodePtr node)
     182             255 : {
     183             255 :         if(node) {
     184             255 :                 if (node->_private != NULL) {
     185               0 :                         ((php_libxml_node_ptr *) node->_private)->node = NULL;
     186                 :                 }
     187             255 :                 switch (node->type) {
     188                 :                         case XML_ATTRIBUTE_NODE:
     189              27 :                                 xmlFreeProp((xmlAttrPtr) node);
     190              27 :                                 break;
     191                 :                         case XML_ENTITY_DECL:
     192                 :                         case XML_ELEMENT_DECL:
     193                 :                         case XML_ATTRIBUTE_DECL:
     194               0 :                                 break;
     195                 :                         case XML_NOTATION_NODE:
     196                 :                                 /* These require special handling */
     197               5 :                                 if (node->name != NULL) {
     198               5 :                                         xmlFree((char *) node->name);
     199                 :                                 }
     200               5 :                                 if (((xmlEntityPtr) node)->ExternalID != NULL) {
     201               5 :                                         xmlFree((char *) ((xmlEntityPtr) node)->ExternalID);
     202                 :                                 }
     203               5 :                                 if (((xmlEntityPtr) node)->SystemID != NULL) {
     204               4 :                                         xmlFree((char *) ((xmlEntityPtr) node)->SystemID);
     205                 :                                 }
     206               5 :                                 xmlFree(node);
     207               5 :                                 break;
     208                 :                         case XML_NAMESPACE_DECL:
     209               0 :                                 if (node->ns) {
     210               0 :                                         xmlFreeNs(node->ns);
     211               0 :                                         node->ns = NULL;
     212                 :                                 }
     213               0 :                                 node->type = XML_ELEMENT_NODE;
     214                 :                         default:
     215             223 :                                 xmlFreeNode(node);
     216                 :                 }
     217                 :         }
     218             255 : }
     219                 : 
     220                 : static void php_libxml_node_free_list(xmlNodePtr node TSRMLS_DC)
     221             361 : {
     222                 :         xmlNodePtr curnode;
     223                 : 
     224             361 :         if (node != NULL) {
     225              78 :                 curnode = node;
     226             294 :                 while (curnode != NULL) {
     227             138 :                         node = curnode;
     228             138 :                         switch (node->type) {
     229                 :                                 /* Skip property freeing for the following types */
     230                 :                                 case XML_NOTATION_NODE:
     231               0 :                                         break;
     232                 :                                 case XML_ENTITY_REF_NODE:
     233               0 :                                         php_libxml_node_free_list((xmlNodePtr) node->properties TSRMLS_CC);
     234               0 :                                         break;
     235                 :                                 case XML_ATTRIBUTE_NODE:
     236              15 :                                         if ((node->doc != NULL) && (((xmlAttrPtr) node)->atype == XML_ATTRIBUTE_ID)) {
     237               1 :                                                 xmlRemoveID(node->doc, (xmlAttrPtr) node);
     238                 :                                         }
     239                 :                                 case XML_ATTRIBUTE_DECL:
     240                 :                                 case XML_DTD_NODE:
     241                 :                                 case XML_DOCUMENT_TYPE_NODE:
     242                 :                                 case XML_ENTITY_DECL:
     243                 :                                 case XML_NAMESPACE_DECL:
     244                 :                                 case XML_TEXT_NODE:
     245             106 :                                         php_libxml_node_free_list(node->children TSRMLS_CC);
     246             106 :                                         break;
     247                 :                                 default:
     248              32 :                                         php_libxml_node_free_list(node->children TSRMLS_CC);
     249              32 :                                         php_libxml_node_free_list((xmlNodePtr) node->properties TSRMLS_CC);
     250                 :                         }
     251                 : 
     252             138 :                         curnode = node->next;
     253             138 :                         xmlUnlinkNode(node);
     254             138 :                         if (php_libxml_unregister_node(node TSRMLS_CC) == 0) {
     255               0 :                                 node->doc = NULL;
     256                 :                         }
     257             138 :                         php_libxml_node_free(node);
     258                 :                 }
     259                 :         }
     260             361 : }
     261                 : 
     262                 : /* }}} */
     263                 : 
     264                 : /* {{{ startup, shutdown and info functions */
     265                 : static PHP_GINIT_FUNCTION(libxml)
     266           13565 : {
     267           13565 :         libxml_globals->stream_context = NULL;
     268           13565 :         libxml_globals->error_buffer.c = NULL;
     269           13565 :         libxml_globals->error_list = NULL;
     270           13565 : }
     271                 : 
     272                 : /* Channel libxml file io layer through the PHP streams subsystem.
     273                 :  * This allows use of ftps:// and https:// urls */
     274                 : 
     275                 : static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char *mode, const int read_only)
     276             891 : {
     277                 :         php_stream_statbuf ssbuf;
     278             891 :         php_stream_context *context = NULL;
     279             891 :         php_stream_wrapper *wrapper = NULL;
     280             891 :         char *resolved_path, *path_to_open = NULL;
     281             891 :         void *ret_val = NULL;
     282             891 :         int isescaped=0;
     283                 :         xmlURI *uri;
     284                 : 
     285                 :         TSRMLS_FETCH();
     286                 : 
     287             891 :         uri = xmlParseURI((xmlChar *)filename);
     288            1770 :         if (uri && (uri->scheme == NULL || (xmlStrncmp(uri->scheme, "file", 4) == 0))) {
     289             879 :                 resolved_path = xmlURIUnescapeString(filename, 0, NULL);
     290             879 :                 isescaped = 1;
     291                 :         } else {
     292              12 :                 resolved_path = (char *)filename;
     293                 :         }
     294                 : 
     295             891 :         if (uri) {
     296             890 :                 xmlFreeURI(uri);
     297                 :         }
     298                 : 
     299             891 :         if (resolved_path == NULL) {
     300               0 :                 return NULL;
     301                 :         }
     302                 : 
     303                 :         /* logic copied from _php_stream_stat, but we only want to fail
     304                 :            if the wrapper supports stat, otherwise, figure it out from
     305                 :            the open.  This logic is only to support hiding warnings
     306                 :            that the streams layer puts out at times, but for libxml we
     307                 :            may try to open files that don't exist, but it is not a failure
     308                 :            in xml processing (eg. DTD files)  */
     309             891 :         wrapper = php_stream_locate_url_wrapper(resolved_path, &path_to_open, ENFORCE_SAFE_MODE TSRMLS_CC);
     310             891 :         if (wrapper && read_only && wrapper->wops->url_stat) {
     311             865 :                 if (wrapper->wops->url_stat(wrapper, path_to_open, PHP_STREAM_URL_STAT_QUIET, &ssbuf, NULL TSRMLS_CC) == -1) {
     312               2 :                         if (isescaped) {
     313               1 :                                 xmlFree(resolved_path);
     314                 :                         }
     315               2 :                         return NULL;
     316                 :                 }
     317                 :         }
     318                 : 
     319             889 :         if (LIBXML(stream_context)) {
     320               8 :                 context = zend_fetch_resource(&LIBXML(stream_context) TSRMLS_CC, -1, "Stream-Context", NULL, 1, php_le_stream_context());
     321                 :         }
     322                 : 
     323             889 :         ret_val = php_stream_open_wrapper_ex(path_to_open, (char *)mode, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL, context);
     324             889 :         if (isescaped) {
     325             878 :                 xmlFree(resolved_path);
     326                 :         }
     327             889 :         return ret_val;
     328                 : }
     329                 : 
     330                 : static void *php_libxml_streams_IO_open_read_wrapper(const char *filename)
     331             876 : {
     332             876 :         return php_libxml_streams_IO_open_wrapper(filename, "rb", 1);
     333                 : }
     334                 : 
     335                 : static void *php_libxml_streams_IO_open_write_wrapper(const char *filename)
     336              15 : {
     337              15 :         return php_libxml_streams_IO_open_wrapper(filename, "wb", 0);
     338                 : }
     339                 : 
     340                 : static int php_libxml_streams_IO_read(void *context, char *buffer, int len)
     341            3720 : {
     342                 :         TSRMLS_FETCH();
     343            3720 :         return php_stream_read((php_stream*)context, buffer, len);
     344                 : }
     345                 : 
     346                 : static int php_libxml_streams_IO_write(void *context, const char *buffer, int len)
     347              24 : {
     348                 :         TSRMLS_FETCH();
     349              24 :         return php_stream_write((php_stream*)context, buffer, len);
     350                 : }
     351                 : 
     352                 : static int php_libxml_streams_IO_close(void *context)
     353             889 : {
     354                 :         TSRMLS_FETCH();
     355             889 :         return php_stream_close((php_stream*)context);
     356                 : }
     357                 : 
     358                 : static xmlParserInputBufferPtr
     359                 : php_libxml_input_buffer_noload(const char *URI, xmlCharEncoding enc)
     360               0 : {
     361               0 :         return NULL;
     362                 : }
     363                 : 
     364                 : static xmlParserInputBufferPtr
     365                 : php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc)
     366             876 : {
     367                 :         xmlParserInputBufferPtr ret;
     368             876 :         void *context = NULL;
     369                 : 
     370             876 :         if (URI == NULL)
     371               0 :                 return(NULL);
     372                 : 
     373             876 :         context = php_libxml_streams_IO_open_read_wrapper(URI);
     374                 : 
     375             876 :         if (context == NULL) {
     376               2 :                 return(NULL);
     377                 :         }
     378                 : 
     379                 :         /* Allocate the Input buffer front-end. */
     380             874 :         ret = xmlAllocParserInputBuffer(enc);
     381             874 :         if (ret != NULL) {
     382             874 :                 ret->context = context;
     383             874 :                 ret->readcallback = php_libxml_streams_IO_read;
     384             874 :                 ret->closecallback = php_libxml_streams_IO_close;
     385                 :         } else
     386               0 :                 php_libxml_streams_IO_close(context);
     387                 : 
     388             874 :         return(ret);
     389                 : }
     390                 : 
     391                 : static xmlOutputBufferPtr
     392                 : php_libxml_output_buffer_create_filename(const char *URI,
     393                 :                               xmlCharEncodingHandlerPtr encoder,
     394                 :                               int compression ATTRIBUTE_UNUSED)
     395              15 : {
     396                 :         xmlOutputBufferPtr ret;
     397                 :         xmlURIPtr puri;
     398              15 :         void *context = NULL;
     399              15 :         char *unescaped = NULL;
     400                 : 
     401              15 :         if (URI == NULL)
     402               0 :                 return(NULL);
     403                 : 
     404              15 :         puri = xmlParseURI(URI);
     405              15 :         if (puri != NULL) {
     406              15 :                 if (puri->scheme != NULL)
     407               1 :                         unescaped = xmlURIUnescapeString(URI, 0, NULL);
     408              15 :                 xmlFreeURI(puri);
     409                 :         }
     410                 : 
     411              15 :         if (unescaped != NULL) {
     412               1 :                 context = php_libxml_streams_IO_open_write_wrapper(unescaped);
     413               1 :                 xmlFree(unescaped);
     414                 :         }
     415                 : 
     416                 :         /* try with a non-escaped URI this may be a strange filename */
     417              15 :         if (context == NULL) {
     418              14 :                 context = php_libxml_streams_IO_open_write_wrapper(URI);
     419                 :         }
     420                 : 
     421              15 :         if (context == NULL) {
     422               0 :                 return(NULL);
     423                 :         }
     424                 : 
     425                 :         /* Allocate the Output buffer front-end. */
     426              15 :         ret = xmlAllocOutputBuffer(encoder);
     427              15 :         if (ret != NULL) {
     428              15 :                 ret->context = context;
     429              15 :                 ret->writecallback = php_libxml_streams_IO_write;
     430              15 :                 ret->closecallback = php_libxml_streams_IO_close;
     431                 :         }
     432                 : 
     433              15 :         return(ret);
     434                 : }
     435                 : 
     436                 : static int _php_libxml_free_error(xmlErrorPtr error)
     437               2 : {
     438                 :         /* This will free the libxml alloc'd memory */
     439               2 :         xmlResetError(error);
     440               2 :         return 1;
     441                 : }
     442                 : 
     443                 : static void _php_list_set_error_structure(xmlErrorPtr error, const char *msg)
     444               2 : {
     445                 :         xmlError error_copy;
     446                 :         int ret;
     447                 : 
     448                 :         TSRMLS_FETCH();
     449                 : 
     450               2 :         memset(&error_copy, 0, sizeof(xmlError));
     451                 : 
     452               2 :         if (error) {
     453               2 :                 ret = xmlCopyError(error, &error_copy);
     454                 :         } else {
     455               0 :                 error_copy.domain = 0;
     456               0 :                 error_copy.code = XML_ERR_INTERNAL_ERROR;
     457               0 :                 error_copy.level = XML_ERR_ERROR;
     458               0 :                 error_copy.line = 0;
     459               0 :                 error_copy.node = NULL;
     460               0 :                 error_copy.int1 = 0;
     461               0 :                 error_copy.int2 = 0;
     462               0 :                 error_copy.ctxt = NULL;
     463               0 :                 error_copy.message = xmlStrdup(msg);
     464               0 :                 error_copy.file = NULL;
     465               0 :                 error_copy.str1 = NULL;
     466               0 :                 error_copy.str2 = NULL;
     467               0 :                 error_copy.str3 = NULL;
     468               0 :                 ret = 0;
     469                 :         }
     470                 : 
     471               2 :         if (ret == 0) {
     472               2 :                 zend_llist_add_element(LIBXML(error_list), &error_copy);
     473                 :         }
     474               2 : }
     475                 : 
     476                 : static void php_libxml_ctx_error_level(int level, void *ctx, const char *msg TSRMLS_DC)
     477               2 : {
     478                 :         xmlParserCtxtPtr parser;
     479                 : 
     480               2 :         parser = (xmlParserCtxtPtr) ctx;
     481                 : 
     482               2 :         if (parser != NULL && parser->input != NULL) {
     483               2 :                 if (parser->input->filename) {
     484               0 :                         php_error_docref(NULL TSRMLS_CC, level, "%s in %s, line: %d", msg, parser->input->filename, parser->input->line);
     485                 :                 } else {
     486               2 :                         php_error_docref(NULL TSRMLS_CC, level, "%s in Entity, line: %d", msg, parser->input->line);
     487                 :                 }
     488                 :         }
     489               2 : }
     490                 : 
     491                 : void php_libxml_issue_error(int level, const char *msg TSRMLS_DC)
     492               9 : {
     493               9 :         if (LIBXML(error_list)) {
     494               0 :                 _php_list_set_error_structure(NULL, msg);
     495                 :         } else {
     496               9 :                 php_error_docref(NULL TSRMLS_CC, level, "%s", msg);
     497                 :         }
     498               9 : }
     499                 : 
     500                 : static void php_libxml_internal_error_handler(int error_type, void *ctx, const char **msg, va_list ap)
     501              50 : {
     502                 :         char *buf;
     503              50 :         int len, len_iter, output = 0;
     504                 : 
     505                 :         TSRMLS_FETCH();
     506                 : 
     507              50 :         len = vspprintf(&buf, 0, *msg, ap);
     508              50 :         len_iter = len;
     509                 : 
     510                 :         /* remove any trailing \n */
     511             131 :         while (len_iter && buf[--len_iter] == '\n') {
     512              31 :                 buf[len_iter] = '\0';
     513              31 :                 output = 1;
     514                 :         }
     515                 : 
     516              50 :         smart_str_appendl(&LIBXML(error_buffer), buf, len);
     517                 : 
     518              50 :         efree(buf);
     519                 : 
     520              50 :         if (output == 1) {
     521              31 :                 if (LIBXML(error_list)) {
     522               0 :                         _php_list_set_error_structure(NULL, LIBXML(error_buffer).c);
     523                 :                 } else {
     524              31 :                         switch (error_type) {
     525                 :                                 case PHP_LIBXML_CTX_ERROR:
     526               2 :                                         php_libxml_ctx_error_level(E_WARNING, ctx, LIBXML(error_buffer).c TSRMLS_CC);
     527               2 :                                         break;
     528                 :                                 case PHP_LIBXML_CTX_WARNING:
     529               0 :                                         php_libxml_ctx_error_level(E_NOTICE, ctx, LIBXML(error_buffer).c TSRMLS_CC);
     530               0 :                                         break;
     531                 :                                 default:
     532              29 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", LIBXML(error_buffer).c);
     533                 :                         }
     534                 :                 }
     535              31 :                 smart_str_free(&LIBXML(error_buffer));
     536                 :         }
     537              50 : }
     538                 : 
     539                 : void php_libxml_ctx_error(void *ctx, const char *msg, ...)
     540               2 : {
     541                 :         va_list args;
     542               2 :         va_start(args, msg);
     543               2 :         php_libxml_internal_error_handler(PHP_LIBXML_CTX_ERROR, ctx, &msg, args);
     544               2 :         va_end(args);
     545               2 : }
     546                 : 
     547                 : void php_libxml_ctx_warning(void *ctx, const char *msg, ...)
     548               0 : {
     549                 :         va_list args;
     550               0 :         va_start(args, msg);
     551               0 :         php_libxml_internal_error_handler(PHP_LIBXML_CTX_WARNING, ctx, &msg, args);
     552               0 :         va_end(args);
     553               0 : }
     554                 : 
     555                 : PHP_LIBXML_API void php_libxml_structured_error_handler(void *userData, xmlErrorPtr error)
     556               2 : {
     557               2 :         _php_list_set_error_structure(error, NULL);
     558                 : 
     559                 :         return;
     560                 : }
     561                 : 
     562                 : PHP_LIBXML_API void php_libxml_error_handler(void *ctx, const char *msg, ...)
     563              48 : {
     564                 :         va_list args;
     565              48 :         va_start(args, msg);
     566              48 :         php_libxml_internal_error_handler(PHP_LIBXML_ERROR, ctx, &msg, args);
     567              48 :         va_end(args);
     568              48 : }
     569                 : 
     570                 : 
     571                 : PHP_LIBXML_API void php_libxml_initialize(void)
     572           40695 : {
     573           40695 :         if (!_php_libxml_initialized) {
     574                 :                 /* we should be the only one's to ever init!! */
     575           13565 :                 xmlInitParser();
     576                 : 
     577           13565 :                 zend_hash_init(&php_libxml_exports, 0, NULL, NULL, 1);
     578                 : 
     579           13565 :                 _php_libxml_initialized = 1;
     580                 :         }
     581           40695 : }
     582                 : 
     583                 : PHP_LIBXML_API void php_libxml_shutdown(void)
     584           13597 : {
     585           13597 :         if (_php_libxml_initialized) {
     586                 : #if defined(LIBXML_SCHEMAS_ENABLED)
     587           13597 :                 xmlRelaxNGCleanupTypes();
     588                 : #endif
     589           13597 :                 xmlCleanupParser();
     590           13597 :                 zend_hash_destroy(&php_libxml_exports);
     591           13597 :                 _php_libxml_initialized = 0;
     592                 :         }
     593           13597 : }
     594                 : 
     595                 : PHP_LIBXML_API zval *php_libxml_switch_context(zval *context TSRMLS_DC)
     596               4 : {
     597                 :         zval *oldcontext;
     598                 : 
     599               4 :         oldcontext = LIBXML(stream_context);
     600               4 :         LIBXML(stream_context) = context;
     601               4 :         return oldcontext;
     602                 : 
     603                 : }
     604                 : 
     605                 : static PHP_MINIT_FUNCTION(libxml)
     606           13565 : {
     607                 :         zend_class_entry ce;
     608                 : 
     609           13565 :         php_libxml_initialize();
     610                 : 
     611           13565 :         REGISTER_LONG_CONSTANT("LIBXML_VERSION",                      LIBXML_VERSION,                 CONST_CS | CONST_PERSISTENT);
     612           13565 :         REGISTER_STRING_CONSTANT("LIBXML_DOTTED_VERSION",     LIBXML_DOTTED_VERSION,  CONST_CS | CONST_PERSISTENT);
     613                 : 
     614                 :         /* For use with loading xml */
     615           13565 :         REGISTER_LONG_CONSTANT("LIBXML_NOENT",                XML_PARSE_NOENT,                CONST_CS | CONST_PERSISTENT);
     616           13565 :         REGISTER_LONG_CONSTANT("LIBXML_DTDLOAD",      XML_PARSE_DTDLOAD,              CONST_CS | CONST_PERSISTENT);
     617           13565 :         REGISTER_LONG_CONSTANT("LIBXML_DTDATTR",      XML_PARSE_DTDATTR,              CONST_CS | CONST_PERSISTENT);
     618           13565 :         REGISTER_LONG_CONSTANT("LIBXML_DTDVALID",     XML_PARSE_DTDVALID,             CONST_CS | CONST_PERSISTENT);
     619           13565 :         REGISTER_LONG_CONSTANT("LIBXML_NOERROR",      XML_PARSE_NOERROR,              CONST_CS | CONST_PERSISTENT);
     620           13565 :         REGISTER_LONG_CONSTANT("LIBXML_NOWARNING",    XML_PARSE_NOWARNING,    CONST_CS | CONST_PERSISTENT);
     621           13565 :         REGISTER_LONG_CONSTANT("LIBXML_NOBLANKS",     XML_PARSE_NOBLANKS,             CONST_CS | CONST_PERSISTENT);
     622           13565 :         REGISTER_LONG_CONSTANT("LIBXML_XINCLUDE",     XML_PARSE_XINCLUDE,             CONST_CS | CONST_PERSISTENT);
     623           13565 :         REGISTER_LONG_CONSTANT("LIBXML_NSCLEAN",      XML_PARSE_NSCLEAN,              CONST_CS | CONST_PERSISTENT);
     624           13565 :         REGISTER_LONG_CONSTANT("LIBXML_NOCDATA",      XML_PARSE_NOCDATA,              CONST_CS | CONST_PERSISTENT);
     625           13565 :         REGISTER_LONG_CONSTANT("LIBXML_NONET",                XML_PARSE_NONET,                CONST_CS | CONST_PERSISTENT);
     626                 : #if LIBXML_VERSION >= 20621
     627           13565 :         REGISTER_LONG_CONSTANT("LIBXML_COMPACT",      XML_PARSE_COMPACT,              CONST_CS | CONST_PERSISTENT);
     628           13565 :         REGISTER_LONG_CONSTANT("LIBXML_NOXMLDECL",    XML_SAVE_NO_DECL,               CONST_CS | CONST_PERSISTENT);
     629                 : #endif
     630           13565 :         REGISTER_LONG_CONSTANT("LIBXML_NOEMPTYTAG",   LIBXML_SAVE_NOEMPTYTAG, CONST_CS | CONST_PERSISTENT);
     631                 : 
     632                 :         /* Error levels */
     633           13565 :         REGISTER_LONG_CONSTANT("LIBXML_ERR_NONE",             XML_ERR_NONE,           CONST_CS | CONST_PERSISTENT);
     634           13565 :         REGISTER_LONG_CONSTANT("LIBXML_ERR_WARNING",  XML_ERR_WARNING,        CONST_CS | CONST_PERSISTENT);
     635           13565 :         REGISTER_LONG_CONSTANT("LIBXML_ERR_ERROR",            XML_ERR_ERROR,          CONST_CS | CONST_PERSISTENT);
     636           13565 :         REGISTER_LONG_CONSTANT("LIBXML_ERR_FATAL",            XML_ERR_FATAL,          CONST_CS | CONST_PERSISTENT);
     637                 : 
     638           13565 :         INIT_CLASS_ENTRY(ce, "LibXMLError", NULL);
     639           13565 :         libxmlerror_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
     640                 : 
     641           13565 :         return SUCCESS;
     642                 : }
     643                 : 
     644                 : 
     645                 : static PHP_RINIT_FUNCTION(libxml)
     646           13551 : {
     647                 :         /* report errors via handler rather than stderr */
     648           13551 :         xmlSetGenericErrorFunc(NULL, php_libxml_error_handler);
     649           13551 :         xmlParserInputBufferCreateFilenameDefault(php_libxml_input_buffer_create_filename);
     650           13551 :         xmlOutputBufferCreateFilenameDefault(php_libxml_output_buffer_create_filename);
     651           13551 :         return SUCCESS;
     652                 : }
     653                 : 
     654                 : 
     655                 : static PHP_MSHUTDOWN_FUNCTION(libxml)
     656           13597 : {
     657           13597 :         php_libxml_shutdown();
     658                 : 
     659           13597 :         return SUCCESS;
     660                 : }
     661                 : 
     662                 : 
     663                 : static PHP_RSHUTDOWN_FUNCTION(libxml)
     664           13584 : {
     665                 :         /* reset libxml generic error handling */
     666           13584 :         xmlSetGenericErrorFunc(NULL, NULL);
     667           13584 :         xmlSetStructuredErrorFunc(NULL, NULL);
     668                 : 
     669           13584 :         xmlParserInputBufferCreateFilenameDefault(NULL);
     670           13584 :         xmlOutputBufferCreateFilenameDefault(NULL);
     671                 : 
     672           13584 :         if (LIBXML(stream_context)) {
     673               1 :                 zval_ptr_dtor(&LIBXML(stream_context));
     674               1 :                 LIBXML(stream_context) = NULL;
     675                 :         }
     676           13584 :         smart_str_free(&LIBXML(error_buffer));
     677           13584 :         if (LIBXML(error_list)) {
     678               2 :                 zend_llist_destroy(LIBXML(error_list));
     679               2 :                 efree(LIBXML(error_list));
     680               2 :                 LIBXML(error_list) = NULL;
     681                 :         }
     682           13584 :         xmlResetLastError();
     683                 : 
     684           13584 :         return SUCCESS;
     685                 : }
     686                 : 
     687                 : 
     688                 : static PHP_MINFO_FUNCTION(libxml)
     689               6 : {
     690               6 :         php_info_print_table_start();
     691               6 :         php_info_print_table_row(2, "libXML support", "active");
     692               6 :         php_info_print_table_row(2, "libXML Version", LIBXML_DOTTED_VERSION);
     693               6 :         php_info_print_table_row(2, "libXML streams", "enabled");
     694               6 :         php_info_print_table_end();
     695               6 : }
     696                 : /* }}} */
     697                 : 
     698                 : /* {{{ proto void libxml_set_streams_context(resource streams_context) 
     699                 :    Set the streams context for the next libxml document load or write */
     700                 : static PHP_FUNCTION(libxml_set_streams_context)
     701               8 : {
     702                 :         zval *arg;
     703                 : 
     704               8 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
     705               0 :                 return;
     706                 :         }
     707               8 :         if (LIBXML(stream_context)) {
     708               7 :                 zval_ptr_dtor(&LIBXML(stream_context));
     709               7 :                 LIBXML(stream_context) = NULL;
     710                 :         }
     711               8 :         ZVAL_ADDREF(arg);
     712               8 :         LIBXML(stream_context) = arg;
     713                 : }
     714                 : /* }}} */
     715                 : 
     716                 : /* {{{ proto void libxml_use_internal_errors([boolean use_errors]) 
     717                 :    Disable libxml errors and allow user to fetch error information as needed */
     718                 : static PHP_FUNCTION(libxml_use_internal_errors)
     719               7 : {
     720                 :         xmlStructuredErrorFunc current_handler;
     721               7 :         zend_bool use_errors=0, retval;
     722                 : 
     723               7 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &use_errors) == FAILURE) {
     724               1 :                 return;
     725                 :         }
     726                 : 
     727               6 :         current_handler = xmlStructuredError;
     728               8 :         if (current_handler && current_handler == php_libxml_structured_error_handler) {
     729               2 :                 retval = 1;
     730                 :         } else {
     731               4 :                 retval = 0;
     732                 :         }
     733                 : 
     734               6 :         if (ZEND_NUM_ARGS() == 0) {
     735               1 :                 RETURN_BOOL(retval);
     736                 :         }
     737                 : 
     738               5 :         if (use_errors == 0) {
     739               2 :                 xmlSetStructuredErrorFunc(NULL, NULL);
     740               2 :                 if (LIBXML(error_list)) {
     741               1 :                         zend_llist_destroy(LIBXML(error_list));
     742               1 :                         efree(LIBXML(error_list));
     743               1 :                         LIBXML(error_list) = NULL;
     744                 :                 }
     745                 :         } else {
     746               3 :                 xmlSetStructuredErrorFunc(NULL, php_libxml_structured_error_handler);
     747               3 :                 if (LIBXML(error_list) == NULL) {
     748               3 :                         LIBXML(error_list) = (zend_llist *) emalloc(sizeof(zend_llist));
     749               3 :                         zend_llist_init(LIBXML(error_list), sizeof(xmlError), (llist_dtor_func_t) _php_libxml_free_error, 0);
     750                 :                 }
     751                 :         }
     752               5 :         RETURN_BOOL(retval);
     753                 : }
     754                 : /* }}} */
     755                 : 
     756                 : /* {{{ proto object libxml_get_last_error() 
     757                 :    Retrieve last error from libxml */
     758                 : static PHP_FUNCTION(libxml_get_last_error)
     759               2 : {
     760                 :         xmlErrorPtr error;
     761                 : 
     762               2 :         error = xmlGetLastError();
     763                 :         
     764               2 :         if (error) {
     765               1 :                 object_init_ex(return_value, libxmlerror_class_entry);
     766               1 :                 add_property_long(return_value, "level", error->level);
     767               1 :                 add_property_long(return_value, "code", error->code);
     768               1 :                 add_property_long(return_value, "column", error->int2);
     769               1 :                 if (error->message) {
     770               1 :                         add_property_string(return_value, "message", error->message, 1);
     771                 :                 } else {
     772               0 :                         add_property_stringl(return_value, "message", "", 0, 1);
     773                 :                 }
     774               1 :                 if (error->file) {
     775               0 :                         add_property_string(return_value, "file", error->file, 1);
     776                 :                 } else {
     777               1 :                         add_property_stringl(return_value, "file", "", 0, 1);
     778                 :                 }
     779               1 :                 add_property_long(return_value, "line", error->line);
     780                 :         } else {
     781               1 :                 RETURN_FALSE;
     782                 :         }
     783                 : }
     784                 : /* }}} */
     785                 : 
     786                 : /* {{{ proto object libxml_get_errors()
     787                 :    Retrieve array of errors */
     788                 : static PHP_FUNCTION(libxml_get_errors)
     789               2 : {
     790                 :         
     791                 :         xmlErrorPtr error;
     792                 : 
     793               2 :         if (array_init(return_value) == FAILURE) {
     794               0 :                 RETURN_FALSE;
     795                 :         }
     796                 : 
     797               2 :         if (LIBXML(error_list)) {
     798                 : 
     799               2 :                 error = zend_llist_get_first(LIBXML(error_list));
     800                 : 
     801               5 :                 while (error != NULL) {
     802                 :                         zval *z_error;
     803               1 :                         MAKE_STD_ZVAL(z_error);
     804                 : 
     805               1 :                         object_init_ex(z_error, libxmlerror_class_entry);
     806               1 :                         add_property_long(z_error, "level", error->level);
     807               1 :                         add_property_long(z_error, "code", error->code);
     808               1 :                         add_property_long(z_error, "column", error->int2);
     809               1 :                         if (error->message) {
     810               1 :                                 add_property_string(z_error, "message", error->message, 1);
     811                 :                         } else {
     812               0 :                                 add_property_stringl(z_error, "message", "", 0, 1);
     813                 :                         }
     814               1 :                         if (error->file) {
     815               0 :                                 add_property_string(z_error, "file", error->file, 1);
     816                 :                         } else {
     817               1 :                                 add_property_stringl(z_error, "file", "", 0, 1);
     818                 :                         }
     819               1 :                         add_property_long(z_error, "line", error->line);
     820               1 :                         add_next_index_zval(return_value, z_error);
     821                 : 
     822               1 :                         error = zend_llist_get_next(LIBXML(error_list));
     823                 :                 }
     824                 :         }
     825                 : }
     826                 : /* }}} */
     827                 : 
     828                 : /* {{{ proto void libxml_clear_errors() 
     829                 :    Clear last error from libxml */
     830                 : static PHP_FUNCTION(libxml_clear_errors)
     831               1 : {
     832               1 :         xmlResetLastError();
     833               1 :         if (LIBXML(error_list)) {
     834               1 :                 zend_llist_clean(LIBXML(error_list));
     835                 :         }
     836               1 : }
     837                 : /* }}} */
     838                 : 
     839                 : /* {{{ proto bool libxml_disable_entity_loader([boolean disable]) 
     840                 :    Disable/Enable ability to load external entities */
     841                 : static PHP_FUNCTION(libxml_disable_entity_loader)
     842               0 : {
     843               0 :         zend_bool disable = 1;
     844                 :         xmlParserInputBufferCreateFilenameFunc old;
     845                 : 
     846               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &disable) == FAILURE) {
     847               0 :                 return;
     848                 :         }
     849                 : 
     850               0 :         if (disable == 0) {
     851               0 :                 old = xmlParserInputBufferCreateFilenameDefault(php_libxml_input_buffer_create_filename);
     852                 :         } else {
     853               0 :                 old = xmlParserInputBufferCreateFilenameDefault(php_libxml_input_buffer_noload);
     854                 :         }
     855                 : 
     856               0 :         if (old == php_libxml_input_buffer_noload) {
     857               0 :                 RETURN_TRUE;
     858                 :         }
     859                 : 
     860               0 :         RETURN_FALSE;
     861                 : }
     862                 : /* }}} */
     863                 : 
     864                 : /* {{{ Common functions shared by extensions */
     865                 : int php_libxml_xmlCheckUTF8(const unsigned char *s)
     866             780 : {
     867                 :         int i;
     868                 :         unsigned char c;
     869                 : 
     870            9123 :         for (i = 0; (c = s[i++]);) {
     871            7564 :                 if ((c & 0x80) == 0) {
     872             157 :                 } else if ((c & 0xe0) == 0xc0) {
     873             156 :                         if ((s[i++] & 0xc0) != 0x80) {
     874               0 :                                 return 0;
     875                 :                         }
     876               1 :                 } else if ((c & 0xf0) == 0xe0) {
     877               0 :                         if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) {
     878               0 :                                 return 0;
     879                 :                         }
     880               1 :                 } else if ((c & 0xf8) == 0xf0) {
     881               0 :                         if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) {
     882               0 :                                 return 0;
     883                 :                         }
     884                 :                 } else {
     885               1 :                         return 0;
     886                 :                 }
     887                 :         }
     888             779 :         return 1;
     889                 : }
     890                 : 
     891                 : int php_libxml_register_export(zend_class_entry *ce, php_libxml_export_node export_function)
     892           27130 : {
     893                 :         php_libxml_func_handler export_hnd;
     894                 :         
     895                 :         /* Initialize in case this module hasnt been loaded yet */
     896           27130 :         php_libxml_initialize();
     897           27130 :         export_hnd.export_func = export_function;
     898                 : 
     899           27130 :         return zend_hash_add(&php_libxml_exports, ce->name, ce->name_length + 1, &export_hnd, sizeof(export_hnd), NULL);
     900                 : }
     901                 : 
     902                 : PHP_LIBXML_API xmlNodePtr php_libxml_import_node(zval *object TSRMLS_DC)
     903              59 : {
     904              59 :         zend_class_entry *ce = NULL;
     905              59 :         xmlNodePtr node = NULL;
     906                 :         php_libxml_func_handler *export_hnd;
     907                 : 
     908              59 :         if (object->type == IS_OBJECT) {
     909              59 :                 ce = Z_OBJCE_P(object);
     910             176 :                 while (ce->parent != NULL) {
     911              58 :                         ce = ce->parent;
     912                 :                 }
     913              59 :                 if (zend_hash_find(&php_libxml_exports, ce->name, ce->name_length + 1, (void **) &export_hnd)  == SUCCESS) {
     914              59 :                         node = export_hnd->export_func(object TSRMLS_CC);
     915                 :                 }
     916                 :         }
     917              59 :         return node;
     918                 : }
     919                 : 
     920                 : PHP_LIBXML_API int php_libxml_increment_node_ptr(php_libxml_node_object *object, xmlNodePtr node, void *private_data TSRMLS_DC)
     921          402223 : {
     922          402223 :         int ret_refcount = -1;
     923                 : 
     924          402223 :         if (object != NULL && node != NULL) {
     925          402223 :                 if (object->node != NULL) {
     926               0 :                         if (object->node->node == node) {
     927               0 :                                 return object->node->refcount;
     928                 :                         } else {
     929               0 :                                 php_libxml_decrement_node_ptr(object TSRMLS_CC);
     930                 :                         }
     931                 :                 }
     932          402223 :                 if (node->_private != NULL) {
     933          200643 :                         object->node = node->_private;
     934          200643 :                         ret_refcount = ++object->node->refcount;
     935                 :                         /* Only dom uses _private */
     936          200643 :                         if (object->node->_private == NULL) {
     937          200643 :                                 object->node->_private = private_data;
     938                 :                         }
     939                 :                 } else {
     940          201580 :                         ret_refcount = 1;
     941          201580 :                         object->node = emalloc(sizeof(php_libxml_node_ptr));
     942          201580 :                         object->node->node = node;
     943          201580 :                         object->node->refcount = 1;
     944          201580 :                         object->node->_private = private_data;
     945          201580 :                         node->_private = object->node;
     946                 :                 }
     947                 :         }
     948                 : 
     949          402223 :         return ret_refcount;
     950                 : }
     951                 : 
     952                 : PHP_LIBXML_API int php_libxml_decrement_node_ptr(php_libxml_node_object *object TSRMLS_DC)
     953          402223 : {
     954          402223 :         int ret_refcount = -1;
     955                 :         php_libxml_node_ptr *obj_node;
     956                 : 
     957          402223 :         if (object != NULL && object->node != NULL) {
     958          402223 :                 obj_node = (php_libxml_node_ptr *) object->node;
     959          402223 :                 ret_refcount = --obj_node->refcount;
     960          402223 :                 if (ret_refcount == 0) {
     961          201580 :                         if (obj_node->node != NULL) {
     962          201571 :                                 obj_node->node->_private = NULL;
     963                 :                         }
     964          201580 :                         efree(obj_node);
     965                 :                 } 
     966          402223 :                 object->node = NULL;
     967                 :         }
     968                 : 
     969          402223 :         return ret_refcount;
     970                 : }
     971                 : 
     972                 : PHP_LIBXML_API int php_libxml_increment_doc_ref(php_libxml_node_object *object, xmlDocPtr docp TSRMLS_DC)
     973            1000 : {
     974            1000 :         int ret_refcount = -1;
     975                 : 
     976            1000 :         if (object->document != NULL) {
     977             496 :                 object->document->refcount++;
     978             496 :                 ret_refcount = object->document->refcount;
     979             504 :         } else if (docp != NULL) {
     980             504 :                 ret_refcount = 1;
     981             504 :                 object->document = emalloc(sizeof(php_libxml_ref_obj));
     982             504 :                 object->document->ptr = docp;
     983             504 :                 object->document->refcount = ret_refcount;
     984             504 :                 object->document->doc_props = NULL;
     985                 :         }
     986                 : 
     987            1000 :         return ret_refcount;
     988                 : }
     989                 : 
     990                 : PHP_LIBXML_API int php_libxml_decrement_doc_ref(php_libxml_node_object *object TSRMLS_DC)
     991          402371 : {
     992          402371 :         int ret_refcount = -1;
     993                 : 
     994          402371 :         if (object != NULL && object->document != NULL) {
     995          402234 :                 ret_refcount = --object->document->refcount;
     996          402234 :                 if (ret_refcount == 0) {
     997             504 :                         if (object->document->ptr != NULL) {
     998             504 :                                 xmlFreeDoc((xmlDoc *) object->document->ptr);
     999                 :                         }
    1000             504 :                         if (object->document->doc_props != NULL) {
    1001             220 :                                 if (object->document->doc_props->classmap) {
    1002               1 :                                         zend_hash_destroy(object->document->doc_props->classmap);
    1003               1 :                                         FREE_HASHTABLE(object->document->doc_props->classmap);
    1004                 :                                 }
    1005             220 :                                 efree(object->document->doc_props);
    1006                 :                         }
    1007             504 :                         efree(object->document);
    1008             504 :                         object->document = NULL;
    1009                 :                 }
    1010                 :         }
    1011                 : 
    1012          402371 :         return ret_refcount;
    1013                 : }
    1014                 : 
    1015                 : void php_libxml_node_free_resource(xmlNodePtr node TSRMLS_DC)
    1016          201229 : {
    1017          201229 :         if (!node) {
    1018               9 :                 return;
    1019                 :         }
    1020                 : 
    1021          201220 :         switch (node->type) {
    1022                 :                 case XML_DOCUMENT_NODE:
    1023                 :                 case XML_HTML_DOCUMENT_NODE:
    1024               0 :                         break;
    1025                 :                 default:
    1026          201337 :                         if (node->parent == NULL || node->type == XML_NAMESPACE_DECL) {
    1027             117 :                                 php_libxml_node_free_list((xmlNodePtr) node->children TSRMLS_CC);
    1028             117 :                                 switch (node->type) {
    1029                 :                                         /* Skip property freeing for the following types */
    1030                 :                                         case XML_ATTRIBUTE_DECL:
    1031                 :                                         case XML_DTD_NODE:
    1032                 :                                         case XML_DOCUMENT_TYPE_NODE:
    1033                 :                                         case XML_ENTITY_DECL:
    1034                 :                                         case XML_ATTRIBUTE_NODE:
    1035                 :                                         case XML_NAMESPACE_DECL:
    1036                 :                                         case XML_TEXT_NODE:
    1037              43 :                                                 break;
    1038                 :                                         default:
    1039              74 :                                                 php_libxml_node_free_list((xmlNodePtr) node->properties TSRMLS_CC);
    1040                 :                                 }
    1041             117 :                                 if (php_libxml_unregister_node(node TSRMLS_CC) == 0) {
    1042               0 :                                         node->doc = NULL;
    1043                 :                                 }
    1044             117 :                                 php_libxml_node_free(node);
    1045                 :                         } else {
    1046          201103 :                                 php_libxml_unregister_node(node TSRMLS_CC);
    1047                 :                         }
    1048                 :         }
    1049                 : }
    1050                 : 
    1051                 : void php_libxml_node_decrement_resource(php_libxml_node_object *object TSRMLS_DC)
    1052          401835 : {
    1053          401835 :         int ret_refcount = -1;
    1054                 :         xmlNodePtr nodep;
    1055                 :         php_libxml_node_ptr *obj_node;
    1056                 : 
    1057          401835 :         if (object != NULL && object->node != NULL) {
    1058          401835 :                 obj_node = (php_libxml_node_ptr *) object->node;
    1059          401835 :                 nodep = object->node->node;
    1060          401835 :                 ret_refcount = php_libxml_decrement_node_ptr(object TSRMLS_CC);
    1061          401835 :                 if (ret_refcount == 0) {
    1062          201192 :                         php_libxml_node_free_resource(nodep TSRMLS_CC);
    1063                 :                 } else {
    1064          200643 :                         if (obj_node && object == obj_node->_private) {
    1065               1 :                                 obj_node->_private = NULL;
    1066                 :                         }
    1067                 :                 }
    1068                 :         }
    1069          401835 :         if (object != NULL && object->document != NULL) {
    1070                 :                 /* Safe to call as if the resource were freed then doc pointer is NULL */
    1071          401814 :                 php_libxml_decrement_doc_ref(object TSRMLS_CC);
    1072                 :         }
    1073          401835 : }
    1074                 : /* }}} */
    1075                 : 
    1076                 : #ifdef PHP_WIN32
    1077                 : PHP_LIBXML_API BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    1078                 : {
    1079                 :         return xmlDllMain(hinstDLL, fdwReason, lpvReserved);
    1080                 : }
    1081                 : #endif
    1082                 : 
    1083                 : #endif
    1084                 : 
    1085                 : /*
    1086                 :  * Local variables:
    1087                 :  * tab-width: 4
    1088                 :  * c-basic-offset: 4
    1089                 :  * End:
    1090                 :  * vim600: sw=4 ts=4 fdm=marker
    1091                 :  * vim<600: sw=4 ts=4
    1092                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:10 +0000 (5 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.