This source file includes following definitions.
- php_libxml_clear_object
- php_libxml_unregister_node
- php_libxml_node_free
- php_libxml_node_free_list
- PHP_GINIT_FUNCTION
- _php_libxml_destroy_fci
- php_libxml_streams_IO_open_wrapper
- php_libxml_streams_IO_open_read_wrapper
- php_libxml_streams_IO_open_write_wrapper
- php_libxml_streams_IO_read
- php_libxml_streams_IO_write
- php_libxml_streams_IO_close
- php_libxml_input_buffer_create_filename
- php_libxml_output_buffer_create_filename
- _php_libxml_free_error
- _php_list_set_error_structure
- php_libxml_ctx_error_level
- php_libxml_issue_error
- php_libxml_internal_error_handler
- _php_libxml_external_entity_loader
- _php_libxml_pre_ext_ent_loader
- php_libxml_ctx_error
- php_libxml_ctx_warning
- php_libxml_structured_error_handler
- php_libxml_error_handler
- php_libxml_initialize
- php_libxml_shutdown
- php_libxml_switch_context
- PHP_MINIT_FUNCTION
- PHP_RINIT_FUNCTION
- PHP_MSHUTDOWN_FUNCTION
- php_libxml_post_deactivate
- PHP_MINFO_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_libxml_disable_entity_loader
- PHP_FUNCTION
- PHP_FUNCTION
- php_libxml_xmlCheckUTF8
- php_libxml_register_export
- php_libxml_import_node
- php_libxml_increment_node_ptr
- php_libxml_decrement_node_ptr
- php_libxml_increment_doc_ref
- php_libxml_decrement_doc_ref
- php_libxml_node_free_resource
- php_libxml_node_decrement_resource
- DllMain
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #define IS_EXT_MODULE
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "php.h"
29 #include "SAPI.h"
30
31 #define PHP_XML_INTERNAL
32 #include "zend_variables.h"
33 #include "ext/standard/php_string.h"
34 #include "ext/standard/info.h"
35 #include "ext/standard/file.h"
36
37 #if HAVE_LIBXML
38
39 #include <libxml/parser.h>
40 #include <libxml/parserInternals.h>
41 #include <libxml/tree.h>
42 #include <libxml/uri.h>
43 #include <libxml/xmlerror.h>
44 #include <libxml/xmlsave.h>
45 #ifdef LIBXML_SCHEMAS_ENABLED
46 #include <libxml/relaxng.h>
47 #include <libxml/xmlschemas.h>
48 #endif
49
50 #include "php_libxml.h"
51
52 #define PHP_LIBXML_ERROR 0
53 #define PHP_LIBXML_CTX_ERROR 1
54 #define PHP_LIBXML_CTX_WARNING 2
55
56
57 static int _php_libxml_initialized = 0;
58 static int _php_libxml_per_request_initialization = 1;
59 static xmlExternalEntityLoader _php_libxml_default_entity_loader;
60
61 typedef struct _php_libxml_func_handler {
62 php_libxml_export_node export_func;
63 } php_libxml_func_handler;
64
65 static HashTable php_libxml_exports;
66
67 static ZEND_DECLARE_MODULE_GLOBALS(libxml)
68 static PHP_GINIT_FUNCTION(libxml);
69
70 static PHP_FUNCTION(libxml_set_streams_context);
71 static PHP_FUNCTION(libxml_use_internal_errors);
72 static PHP_FUNCTION(libxml_get_last_error);
73 static PHP_FUNCTION(libxml_clear_errors);
74 static PHP_FUNCTION(libxml_get_errors);
75 static PHP_FUNCTION(libxml_set_external_entity_loader);
76 static PHP_FUNCTION(libxml_disable_entity_loader);
77
78 static zend_class_entry *libxmlerror_class_entry;
79
80
81 #ifdef COMPILE_DL_LIBXML
82 ZEND_GET_MODULE(libxml)
83 #endif
84
85
86
87 static PHP_MINIT_FUNCTION(libxml);
88 static PHP_RINIT_FUNCTION(libxml);
89 static PHP_MSHUTDOWN_FUNCTION(libxml);
90 static PHP_MINFO_FUNCTION(libxml);
91 static int php_libxml_post_deactivate(void);
92
93
94
95
96 ZEND_BEGIN_ARG_INFO(arginfo_libxml_set_streams_context, 0)
97 ZEND_ARG_INFO(0, context)
98 ZEND_END_ARG_INFO()
99
100 ZEND_BEGIN_ARG_INFO_EX(arginfo_libxml_use_internal_errors, 0, 0, 0)
101 ZEND_ARG_INFO(0, use_errors)
102 ZEND_END_ARG_INFO()
103
104 ZEND_BEGIN_ARG_INFO(arginfo_libxml_get_last_error, 0)
105 ZEND_END_ARG_INFO()
106
107 ZEND_BEGIN_ARG_INFO(arginfo_libxml_get_errors, 0)
108 ZEND_END_ARG_INFO()
109
110 ZEND_BEGIN_ARG_INFO(arginfo_libxml_clear_errors, 0)
111 ZEND_END_ARG_INFO()
112
113 ZEND_BEGIN_ARG_INFO_EX(arginfo_libxml_disable_entity_loader, 0, 0, 0)
114 ZEND_ARG_INFO(0, disable)
115 ZEND_END_ARG_INFO()
116
117 ZEND_BEGIN_ARG_INFO_EX(arginfo_libxml_set_external_entity_loader, 0, 0, 1)
118 ZEND_ARG_INFO(0, resolver_function)
119 ZEND_END_ARG_INFO()
120
121
122
123 static const zend_function_entry libxml_functions[] = {
124 PHP_FE(libxml_set_streams_context, arginfo_libxml_set_streams_context)
125 PHP_FE(libxml_use_internal_errors, arginfo_libxml_use_internal_errors)
126 PHP_FE(libxml_get_last_error, arginfo_libxml_get_last_error)
127 PHP_FE(libxml_clear_errors, arginfo_libxml_clear_errors)
128 PHP_FE(libxml_get_errors, arginfo_libxml_get_errors)
129 PHP_FE(libxml_disable_entity_loader, arginfo_libxml_disable_entity_loader)
130 PHP_FE(libxml_set_external_entity_loader, arginfo_libxml_set_external_entity_loader)
131 PHP_FE_END
132 };
133
134 zend_module_entry libxml_module_entry = {
135 STANDARD_MODULE_HEADER,
136 "libxml",
137 libxml_functions,
138 PHP_MINIT(libxml),
139 PHP_MSHUTDOWN(libxml),
140 PHP_RINIT(libxml),
141 NULL,
142 PHP_MINFO(libxml),
143 NO_VERSION_YET,
144 PHP_MODULE_GLOBALS(libxml),
145 PHP_GINIT(libxml),
146 NULL,
147 php_libxml_post_deactivate,
148 STANDARD_MODULE_PROPERTIES_EX
149 };
150
151
152
153
154 static int php_libxml_clear_object(php_libxml_node_object *object TSRMLS_DC)
155 {
156 if (object->properties) {
157 object->properties = NULL;
158 }
159 php_libxml_decrement_node_ptr(object TSRMLS_CC);
160 return php_libxml_decrement_doc_ref(object TSRMLS_CC);
161 }
162
163 static int php_libxml_unregister_node(xmlNodePtr nodep TSRMLS_DC)
164 {
165 php_libxml_node_object *wrapper;
166
167 php_libxml_node_ptr *nodeptr = nodep->_private;
168
169 if (nodeptr != NULL) {
170 wrapper = nodeptr->_private;
171 if (wrapper) {
172 php_libxml_clear_object(wrapper TSRMLS_CC);
173 } else {
174 if (nodeptr->node != NULL && nodeptr->node->type != XML_DOCUMENT_NODE) {
175 nodeptr->node->_private = NULL;
176 }
177 nodeptr->node = NULL;
178 }
179 }
180
181 return -1;
182 }
183
184 static void php_libxml_node_free(xmlNodePtr node)
185 {
186 if(node) {
187 if (node->_private != NULL) {
188 ((php_libxml_node_ptr *) node->_private)->node = NULL;
189 }
190 switch (node->type) {
191 case XML_ATTRIBUTE_NODE:
192 xmlFreeProp((xmlAttrPtr) node);
193 break;
194 case XML_ENTITY_DECL:
195 case XML_ELEMENT_DECL:
196 case XML_ATTRIBUTE_DECL:
197 break;
198 case XML_NOTATION_NODE:
199
200 if (node->name != NULL) {
201 xmlFree((char *) node->name);
202 }
203 if (((xmlEntityPtr) node)->ExternalID != NULL) {
204 xmlFree((char *) ((xmlEntityPtr) node)->ExternalID);
205 }
206 if (((xmlEntityPtr) node)->SystemID != NULL) {
207 xmlFree((char *) ((xmlEntityPtr) node)->SystemID);
208 }
209 xmlFree(node);
210 break;
211 case XML_NAMESPACE_DECL:
212 if (node->ns) {
213 xmlFreeNs(node->ns);
214 node->ns = NULL;
215 }
216 node->type = XML_ELEMENT_NODE;
217 default:
218 xmlFreeNode(node);
219 }
220 }
221 }
222
223 static void php_libxml_node_free_list(xmlNodePtr node TSRMLS_DC)
224 {
225 xmlNodePtr curnode;
226
227 if (node != NULL) {
228 curnode = node;
229 while (curnode != NULL) {
230 node = curnode;
231 switch (node->type) {
232
233 case XML_NOTATION_NODE:
234 case XML_ENTITY_DECL:
235 break;
236 case XML_ENTITY_REF_NODE:
237 php_libxml_node_free_list((xmlNodePtr) node->properties TSRMLS_CC);
238 break;
239 case XML_ATTRIBUTE_NODE:
240 if ((node->doc != NULL) && (((xmlAttrPtr) node)->atype == XML_ATTRIBUTE_ID)) {
241 xmlRemoveID(node->doc, (xmlAttrPtr) node);
242 }
243 case XML_ATTRIBUTE_DECL:
244 case XML_DTD_NODE:
245 case XML_DOCUMENT_TYPE_NODE:
246 case XML_NAMESPACE_DECL:
247 case XML_TEXT_NODE:
248 php_libxml_node_free_list(node->children TSRMLS_CC);
249 break;
250 default:
251 php_libxml_node_free_list(node->children TSRMLS_CC);
252 php_libxml_node_free_list((xmlNodePtr) node->properties TSRMLS_CC);
253 }
254
255 curnode = node->next;
256 xmlUnlinkNode(node);
257 if (php_libxml_unregister_node(node TSRMLS_CC) == 0) {
258 node->doc = NULL;
259 }
260 php_libxml_node_free(node);
261 }
262 }
263 }
264
265
266
267
268 static PHP_GINIT_FUNCTION(libxml)
269 {
270 libxml_globals->stream_context = NULL;
271 libxml_globals->error_buffer.c = NULL;
272 libxml_globals->error_list = NULL;
273 libxml_globals->entity_loader.fci.size = 0;
274 libxml_globals->entity_loader_disabled = 0;
275 }
276
277 static void _php_libxml_destroy_fci(zend_fcall_info *fci)
278 {
279 if (fci->size > 0) {
280 zval_ptr_dtor(&fci->function_name);
281 if (fci->object_ptr != NULL) {
282 zval_ptr_dtor(&fci->object_ptr);
283 }
284 fci->size = 0;
285 }
286 }
287
288
289
290
291 static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char *mode, const int read_only)
292 {
293 php_stream_statbuf ssbuf;
294 php_stream_context *context = NULL;
295 php_stream_wrapper *wrapper = NULL;
296 char *resolved_path;
297 const char *path_to_open = NULL;
298 void *ret_val = NULL;
299 int isescaped=0;
300 xmlURI *uri;
301
302 TSRMLS_FETCH();
303
304 uri = xmlParseURI(filename);
305 if (uri && (uri->scheme == NULL ||
306 (xmlStrncmp(BAD_CAST uri->scheme, BAD_CAST "file", 4) == 0))) {
307 resolved_path = xmlURIUnescapeString(filename, 0, NULL);
308 isescaped = 1;
309 #if LIBXML_VERSION >= 20902 && defined(PHP_WIN32)
310
311
312
313 {
314 size_t pre_len = sizeof("file:/") - 1;
315
316 if (strncasecmp(resolved_path, "file:/", pre_len) == 0
317 && '/' != resolved_path[pre_len]) {
318 xmlChar *tmp = xmlStrdup(resolved_path + pre_len);
319 xmlFree(resolved_path);
320 resolved_path = tmp;
321 }
322 }
323 #endif
324 } else {
325 resolved_path = (char *)filename;
326 }
327
328 if (uri) {
329 xmlFreeURI(uri);
330 }
331
332 if (resolved_path == NULL) {
333 return NULL;
334 }
335
336
337
338
339
340
341
342 wrapper = php_stream_locate_url_wrapper(resolved_path, &path_to_open, 0 TSRMLS_CC);
343 if (wrapper && read_only && wrapper->wops->url_stat) {
344 if (wrapper->wops->url_stat(wrapper, path_to_open, PHP_STREAM_URL_STAT_QUIET, &ssbuf, NULL TSRMLS_CC) == -1) {
345 if (isescaped) {
346 xmlFree(resolved_path);
347 }
348 return NULL;
349 }
350 }
351
352 context = php_stream_context_from_zval(LIBXML(stream_context), 0);
353
354 ret_val = php_stream_open_wrapper_ex(path_to_open, (char *)mode, REPORT_ERRORS, NULL, context);
355 if (isescaped) {
356 xmlFree(resolved_path);
357 }
358 return ret_val;
359 }
360
361 static void *php_libxml_streams_IO_open_read_wrapper(const char *filename)
362 {
363 return php_libxml_streams_IO_open_wrapper(filename, "rb", 1);
364 }
365
366 static void *php_libxml_streams_IO_open_write_wrapper(const char *filename)
367 {
368 return php_libxml_streams_IO_open_wrapper(filename, "wb", 0);
369 }
370
371 static int php_libxml_streams_IO_read(void *context, char *buffer, int len)
372 {
373 TSRMLS_FETCH();
374 return php_stream_read((php_stream*)context, buffer, len);
375 }
376
377 static int php_libxml_streams_IO_write(void *context, const char *buffer, int len)
378 {
379 TSRMLS_FETCH();
380 return php_stream_write((php_stream*)context, buffer, len);
381 }
382
383 static int php_libxml_streams_IO_close(void *context)
384 {
385 TSRMLS_FETCH();
386 return php_stream_close((php_stream*)context);
387 }
388
389 static xmlParserInputBufferPtr
390 php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc)
391 {
392 xmlParserInputBufferPtr ret;
393 void *context = NULL;
394 TSRMLS_FETCH();
395
396 if (LIBXML(entity_loader_disabled)) {
397 return NULL;
398 }
399
400 if (URI == NULL)
401 return(NULL);
402
403 context = php_libxml_streams_IO_open_read_wrapper(URI);
404
405 if (context == NULL) {
406 return(NULL);
407 }
408
409
410 ret = xmlAllocParserInputBuffer(enc);
411 if (ret != NULL) {
412 ret->context = context;
413 ret->readcallback = php_libxml_streams_IO_read;
414 ret->closecallback = php_libxml_streams_IO_close;
415 } else
416 php_libxml_streams_IO_close(context);
417
418 return(ret);
419 }
420
421 static xmlOutputBufferPtr
422 php_libxml_output_buffer_create_filename(const char *URI,
423 xmlCharEncodingHandlerPtr encoder,
424 int compression ATTRIBUTE_UNUSED)
425 {
426 xmlOutputBufferPtr ret;
427 xmlURIPtr puri;
428 void *context = NULL;
429 char *unescaped = NULL;
430
431 if (URI == NULL)
432 return(NULL);
433
434 puri = xmlParseURI(URI);
435 if (puri != NULL) {
436 if (puri->scheme != NULL)
437 unescaped = xmlURIUnescapeString(URI, 0, NULL);
438 xmlFreeURI(puri);
439 }
440
441 if (unescaped != NULL) {
442 context = php_libxml_streams_IO_open_write_wrapper(unescaped);
443 xmlFree(unescaped);
444 }
445
446
447 if (context == NULL) {
448 context = php_libxml_streams_IO_open_write_wrapper(URI);
449 }
450
451 if (context == NULL) {
452 return(NULL);
453 }
454
455
456 ret = xmlAllocOutputBuffer(encoder);
457 if (ret != NULL) {
458 ret->context = context;
459 ret->writecallback = php_libxml_streams_IO_write;
460 ret->closecallback = php_libxml_streams_IO_close;
461 }
462
463 return(ret);
464 }
465
466 static int _php_libxml_free_error(xmlErrorPtr error)
467 {
468
469 xmlResetError(error);
470 return 1;
471 }
472
473 static void _php_list_set_error_structure(xmlErrorPtr error, const char *msg)
474 {
475 xmlError error_copy;
476 int ret;
477
478 TSRMLS_FETCH();
479
480 memset(&error_copy, 0, sizeof(xmlError));
481
482 if (error) {
483 ret = xmlCopyError(error, &error_copy);
484 } else {
485 error_copy.domain = 0;
486 error_copy.code = XML_ERR_INTERNAL_ERROR;
487 error_copy.level = XML_ERR_ERROR;
488 error_copy.line = 0;
489 error_copy.node = NULL;
490 error_copy.int1 = 0;
491 error_copy.int2 = 0;
492 error_copy.ctxt = NULL;
493 error_copy.message = xmlStrdup(msg);
494 error_copy.file = NULL;
495 error_copy.str1 = NULL;
496 error_copy.str2 = NULL;
497 error_copy.str3 = NULL;
498 ret = 0;
499 }
500
501 if (ret == 0) {
502 zend_llist_add_element(LIBXML(error_list), &error_copy);
503 }
504 }
505
506 static void php_libxml_ctx_error_level(int level, void *ctx, const char *msg TSRMLS_DC)
507 {
508 xmlParserCtxtPtr parser;
509
510 parser = (xmlParserCtxtPtr) ctx;
511
512 if (parser != NULL && parser->input != NULL) {
513 if (parser->input->filename) {
514 php_error_docref(NULL TSRMLS_CC, level, "%s in %s, line: %d", msg, parser->input->filename, parser->input->line);
515 } else {
516 php_error_docref(NULL TSRMLS_CC, level, "%s in Entity, line: %d", msg, parser->input->line);
517 }
518 }
519 }
520
521 void php_libxml_issue_error(int level, const char *msg TSRMLS_DC)
522 {
523 if (LIBXML(error_list)) {
524 _php_list_set_error_structure(NULL, msg);
525 } else {
526 php_error_docref(NULL TSRMLS_CC, level, "%s", msg);
527 }
528 }
529
530 static void php_libxml_internal_error_handler(int error_type, void *ctx, const char **msg, va_list ap)
531 {
532 char *buf;
533 int len, len_iter, output = 0;
534
535 TSRMLS_FETCH();
536
537 len = vspprintf(&buf, 0, *msg, ap);
538 len_iter = len;
539
540
541 while (len_iter && buf[--len_iter] == '\n') {
542 buf[len_iter] = '\0';
543 output = 1;
544 }
545
546 smart_str_appendl(&LIBXML(error_buffer), buf, len);
547
548 efree(buf);
549
550 if (output == 1) {
551 if (LIBXML(error_list)) {
552 _php_list_set_error_structure(NULL, LIBXML(error_buffer).c);
553 } else {
554 switch (error_type) {
555 case PHP_LIBXML_CTX_ERROR:
556 php_libxml_ctx_error_level(E_WARNING, ctx, LIBXML(error_buffer).c TSRMLS_CC);
557 break;
558 case PHP_LIBXML_CTX_WARNING:
559 php_libxml_ctx_error_level(E_NOTICE, ctx, LIBXML(error_buffer).c TSRMLS_CC);
560 break;
561 default:
562 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", LIBXML(error_buffer).c);
563 }
564 }
565 smart_str_free(&LIBXML(error_buffer));
566 }
567 }
568
569 static xmlParserInputPtr _php_libxml_external_entity_loader(const char *URL,
570 const char *ID, xmlParserCtxtPtr context)
571 {
572 xmlParserInputPtr ret = NULL;
573 const char *resource = NULL;
574 zval *public = NULL,
575 *system = NULL,
576 *ctxzv = NULL,
577 **params[] = {&public, &system, &ctxzv},
578 *retval_ptr = NULL;
579 int retval;
580 zend_fcall_info *fci;
581 TSRMLS_FETCH();
582
583 fci = &LIBXML(entity_loader).fci;
584
585 if (fci->size == 0) {
586
587 return _php_libxml_default_entity_loader(URL, ID, context);
588 }
589
590 ALLOC_INIT_ZVAL(public);
591 if (ID != NULL) {
592 ZVAL_STRING(public, ID, 1);
593 }
594 ALLOC_INIT_ZVAL(system);
595 if (URL != NULL) {
596 ZVAL_STRING(system, URL, 1);
597 }
598 MAKE_STD_ZVAL(ctxzv);
599 array_init_size(ctxzv, 4);
600
601 #define ADD_NULL_OR_STRING_KEY(memb) \
602 if (context->memb == NULL) { \
603 add_assoc_null_ex(ctxzv, #memb, sizeof(#memb)); \
604 } else { \
605 add_assoc_string_ex(ctxzv, #memb, sizeof(#memb), \
606 (char *)context->memb, 1); \
607 }
608
609 ADD_NULL_OR_STRING_KEY(directory)
610 ADD_NULL_OR_STRING_KEY(intSubName)
611 ADD_NULL_OR_STRING_KEY(extSubURI)
612 ADD_NULL_OR_STRING_KEY(extSubSystem)
613
614 #undef ADD_NULL_OR_STRING_KEY
615
616 fci->retval_ptr_ptr = &retval_ptr;
617 fci->params = params;
618 fci->param_count = sizeof(params)/sizeof(*params);
619 fci->no_separation = 1;
620
621 retval = zend_call_function(fci, &LIBXML(entity_loader).fcc TSRMLS_CC);
622 if (retval != SUCCESS || fci->retval_ptr_ptr == NULL) {
623 php_libxml_ctx_error(context,
624 "Call to user entity loader callback '%s' has failed",
625 fci->function_name);
626 } else {
627 retval_ptr = *fci->retval_ptr_ptr;
628 if (retval_ptr == NULL) {
629 php_libxml_ctx_error(context,
630 "Call to user entity loader callback '%s' has failed; "
631 "probably it has thrown an exception",
632 fci->function_name);
633 } else if (Z_TYPE_P(retval_ptr) == IS_STRING) {
634 is_string:
635 resource = Z_STRVAL_P(retval_ptr);
636 } else if (Z_TYPE_P(retval_ptr) == IS_RESOURCE) {
637 php_stream *stream;
638 php_stream_from_zval_no_verify(stream, &retval_ptr);
639 if (stream == NULL) {
640 php_libxml_ctx_error(context,
641 "The user entity loader callback '%s' has returned a "
642 "resource, but it is not a stream",
643 fci->function_name);
644 } else {
645
646 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
647 xmlParserInputBufferPtr pib = xmlAllocParserInputBuffer(enc);
648 if (pib == NULL) {
649 php_libxml_ctx_error(context, "Could not allocate parser "
650 "input buffer");
651 } else {
652
653 zend_list_addref(stream->rsrc_id);
654 pib->context = stream;
655 pib->readcallback = php_libxml_streams_IO_read;
656 pib->closecallback = php_libxml_streams_IO_close;
657
658 ret = xmlNewIOInputStream(context, pib, enc);
659 if (ret == NULL) {
660 xmlFreeParserInputBuffer(pib);
661 }
662 }
663 }
664 } else if (Z_TYPE_P(retval_ptr) != IS_NULL) {
665
666 SEPARATE_ZVAL(&retval_ptr);
667 convert_to_string(retval_ptr);
668 goto is_string;
669 }
670 }
671
672 if (ret == NULL) {
673 if (resource == NULL) {
674 if (ID == NULL) {
675 ID = "NULL";
676 }
677 php_libxml_ctx_error(context,
678 "Failed to load external entity \"%s\"\n", ID);
679 } else {
680
681 ret = xmlNewInputFromFile(context, resource);
682 }
683 }
684
685 zval_ptr_dtor(&public);
686 zval_ptr_dtor(&system);
687 zval_ptr_dtor(&ctxzv);
688 if (retval_ptr != NULL) {
689 zval_ptr_dtor(&retval_ptr);
690 }
691 return ret;
692 }
693
694 static xmlParserInputPtr _php_libxml_pre_ext_ent_loader(const char *URL,
695 const char *ID, xmlParserCtxtPtr context)
696 {
697 TSRMLS_FETCH();
698
699
700
701
702
703
704
705
706
707
708 if (xmlGenericError == php_libxml_error_handler && PG(modules_activated)) {
709 return _php_libxml_external_entity_loader(URL, ID, context);
710 } else {
711 return _php_libxml_default_entity_loader(URL, ID, context);
712 }
713 }
714
715 PHP_LIBXML_API void php_libxml_ctx_error(void *ctx, const char *msg, ...)
716 {
717 va_list args;
718 va_start(args, msg);
719 php_libxml_internal_error_handler(PHP_LIBXML_CTX_ERROR, ctx, &msg, args);
720 va_end(args);
721 }
722
723 PHP_LIBXML_API void php_libxml_ctx_warning(void *ctx, const char *msg, ...)
724 {
725 va_list args;
726 va_start(args, msg);
727 php_libxml_internal_error_handler(PHP_LIBXML_CTX_WARNING, ctx, &msg, args);
728 va_end(args);
729 }
730
731 PHP_LIBXML_API void php_libxml_structured_error_handler(void *userData, xmlErrorPtr error)
732 {
733 _php_list_set_error_structure(error, NULL);
734
735 return;
736 }
737
738 PHP_LIBXML_API void php_libxml_error_handler(void *ctx, const char *msg, ...)
739 {
740 va_list args;
741 va_start(args, msg);
742 php_libxml_internal_error_handler(PHP_LIBXML_ERROR, ctx, &msg, args);
743 va_end(args);
744 }
745
746
747 PHP_LIBXML_API void php_libxml_initialize(void)
748 {
749 if (!_php_libxml_initialized) {
750
751 xmlInitParser();
752
753 _php_libxml_default_entity_loader = xmlGetExternalEntityLoader();
754 xmlSetExternalEntityLoader(_php_libxml_pre_ext_ent_loader);
755
756 zend_hash_init(&php_libxml_exports, 0, NULL, NULL, 1);
757
758 _php_libxml_initialized = 1;
759 }
760 }
761
762 PHP_LIBXML_API void php_libxml_shutdown(void)
763 {
764 if (_php_libxml_initialized) {
765 #if defined(LIBXML_SCHEMAS_ENABLED)
766 xmlRelaxNGCleanupTypes();
767 #endif
768 xmlCleanupParser();
769 zend_hash_destroy(&php_libxml_exports);
770
771 xmlSetExternalEntityLoader(_php_libxml_default_entity_loader);
772 _php_libxml_initialized = 0;
773 }
774 }
775
776 PHP_LIBXML_API zval *php_libxml_switch_context(zval *context TSRMLS_DC)
777 {
778 zval *oldcontext;
779
780 oldcontext = LIBXML(stream_context);
781 LIBXML(stream_context) = context;
782 return oldcontext;
783
784 }
785
786 static PHP_MINIT_FUNCTION(libxml)
787 {
788 zend_class_entry ce;
789
790 php_libxml_initialize();
791
792 REGISTER_LONG_CONSTANT("LIBXML_VERSION", LIBXML_VERSION, CONST_CS | CONST_PERSISTENT);
793 REGISTER_STRING_CONSTANT("LIBXML_DOTTED_VERSION", LIBXML_DOTTED_VERSION, CONST_CS | CONST_PERSISTENT);
794 REGISTER_STRING_CONSTANT("LIBXML_LOADED_VERSION", (char *)xmlParserVersion, CONST_CS | CONST_PERSISTENT);
795
796
797 REGISTER_LONG_CONSTANT("LIBXML_NOENT", XML_PARSE_NOENT, CONST_CS | CONST_PERSISTENT);
798 REGISTER_LONG_CONSTANT("LIBXML_DTDLOAD", XML_PARSE_DTDLOAD, CONST_CS | CONST_PERSISTENT);
799 REGISTER_LONG_CONSTANT("LIBXML_DTDATTR", XML_PARSE_DTDATTR, CONST_CS | CONST_PERSISTENT);
800 REGISTER_LONG_CONSTANT("LIBXML_DTDVALID", XML_PARSE_DTDVALID, CONST_CS | CONST_PERSISTENT);
801 REGISTER_LONG_CONSTANT("LIBXML_NOERROR", XML_PARSE_NOERROR, CONST_CS | CONST_PERSISTENT);
802 REGISTER_LONG_CONSTANT("LIBXML_NOWARNING", XML_PARSE_NOWARNING, CONST_CS | CONST_PERSISTENT);
803 REGISTER_LONG_CONSTANT("LIBXML_NOBLANKS", XML_PARSE_NOBLANKS, CONST_CS | CONST_PERSISTENT);
804 REGISTER_LONG_CONSTANT("LIBXML_XINCLUDE", XML_PARSE_XINCLUDE, CONST_CS | CONST_PERSISTENT);
805 REGISTER_LONG_CONSTANT("LIBXML_NSCLEAN", XML_PARSE_NSCLEAN, CONST_CS | CONST_PERSISTENT);
806 REGISTER_LONG_CONSTANT("LIBXML_NOCDATA", XML_PARSE_NOCDATA, CONST_CS | CONST_PERSISTENT);
807 REGISTER_LONG_CONSTANT("LIBXML_NONET", XML_PARSE_NONET, CONST_CS | CONST_PERSISTENT);
808 REGISTER_LONG_CONSTANT("LIBXML_PEDANTIC", XML_PARSE_PEDANTIC, CONST_CS | CONST_PERSISTENT);
809 #if LIBXML_VERSION >= 20621
810 REGISTER_LONG_CONSTANT("LIBXML_COMPACT", XML_PARSE_COMPACT, CONST_CS | CONST_PERSISTENT);
811 REGISTER_LONG_CONSTANT("LIBXML_NOXMLDECL", XML_SAVE_NO_DECL, CONST_CS | CONST_PERSISTENT);
812 #endif
813 #if LIBXML_VERSION >= 20703
814 REGISTER_LONG_CONSTANT("LIBXML_PARSEHUGE", XML_PARSE_HUGE, CONST_CS | CONST_PERSISTENT);
815 #endif
816 REGISTER_LONG_CONSTANT("LIBXML_NOEMPTYTAG", LIBXML_SAVE_NOEMPTYTAG, CONST_CS | CONST_PERSISTENT);
817
818
819 #if defined(LIBXML_SCHEMAS_ENABLED) && LIBXML_VERSION >= 20614
820 REGISTER_LONG_CONSTANT("LIBXML_SCHEMA_CREATE", XML_SCHEMA_VAL_VC_I_CREATE, CONST_CS | CONST_PERSISTENT);
821 #endif
822
823
824 #if LIBXML_VERSION >= 20707
825 REGISTER_LONG_CONSTANT("LIBXML_HTML_NOIMPLIED", HTML_PARSE_NOIMPLIED, CONST_CS | CONST_PERSISTENT);
826 #endif
827
828 #if LIBXML_VERSION >= 20708
829 REGISTER_LONG_CONSTANT("LIBXML_HTML_NODEFDTD", HTML_PARSE_NODEFDTD, CONST_CS | CONST_PERSISTENT);
830 #endif
831
832
833 REGISTER_LONG_CONSTANT("LIBXML_ERR_NONE", XML_ERR_NONE, CONST_CS | CONST_PERSISTENT);
834 REGISTER_LONG_CONSTANT("LIBXML_ERR_WARNING", XML_ERR_WARNING, CONST_CS | CONST_PERSISTENT);
835 REGISTER_LONG_CONSTANT("LIBXML_ERR_ERROR", XML_ERR_ERROR, CONST_CS | CONST_PERSISTENT);
836 REGISTER_LONG_CONSTANT("LIBXML_ERR_FATAL", XML_ERR_FATAL, CONST_CS | CONST_PERSISTENT);
837
838 INIT_CLASS_ENTRY(ce, "LibXMLError", NULL);
839 libxmlerror_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
840
841 if (sapi_module.name) {
842 static const char * const supported_sapis[] = {
843 "cgi-fcgi",
844 "fpm-fcgi",
845 "litespeed",
846 NULL
847 };
848 const char * const *sapi_name;
849
850 for (sapi_name = supported_sapis; *sapi_name; sapi_name++) {
851 if (strcmp(sapi_module.name, *sapi_name) == 0) {
852 _php_libxml_per_request_initialization = 0;
853 break;
854 }
855 }
856 }
857
858 if (!_php_libxml_per_request_initialization) {
859
860 xmlSetGenericErrorFunc(NULL, php_libxml_error_handler);
861 xmlParserInputBufferCreateFilenameDefault(php_libxml_input_buffer_create_filename);
862 xmlOutputBufferCreateFilenameDefault(php_libxml_output_buffer_create_filename);
863 }
864
865 return SUCCESS;
866 }
867
868
869 static PHP_RINIT_FUNCTION(libxml)
870 {
871 if (_php_libxml_per_request_initialization) {
872
873 xmlSetGenericErrorFunc(NULL, php_libxml_error_handler);
874 xmlParserInputBufferCreateFilenameDefault(php_libxml_input_buffer_create_filename);
875 xmlOutputBufferCreateFilenameDefault(php_libxml_output_buffer_create_filename);
876
877
878
879
880
881 LIBXML(entity_loader_disabled) = 0;
882 }
883 return SUCCESS;
884 }
885
886
887 static PHP_MSHUTDOWN_FUNCTION(libxml)
888 {
889 if (!_php_libxml_per_request_initialization) {
890 xmlSetGenericErrorFunc(NULL, NULL);
891
892 xmlParserInputBufferCreateFilenameDefault(NULL);
893 xmlOutputBufferCreateFilenameDefault(NULL);
894 }
895 php_libxml_shutdown();
896
897 return SUCCESS;
898 }
899
900 static int php_libxml_post_deactivate(void)
901 {
902 TSRMLS_FETCH();
903
904 if (_php_libxml_per_request_initialization) {
905 xmlSetGenericErrorFunc(NULL, NULL);
906
907 xmlParserInputBufferCreateFilenameDefault(NULL);
908 xmlOutputBufferCreateFilenameDefault(NULL);
909 }
910 xmlSetStructuredErrorFunc(NULL, NULL);
911
912 if (LIBXML(stream_context)) {
913
914 efree(LIBXML(stream_context));
915 LIBXML(stream_context) = NULL;
916 }
917 smart_str_free(&LIBXML(error_buffer));
918 if (LIBXML(error_list)) {
919 zend_llist_destroy(LIBXML(error_list));
920 efree(LIBXML(error_list));
921 LIBXML(error_list) = NULL;
922 }
923 xmlResetLastError();
924
925 _php_libxml_destroy_fci(&LIBXML(entity_loader).fci);
926
927 return SUCCESS;
928 }
929
930
931 static PHP_MINFO_FUNCTION(libxml)
932 {
933 php_info_print_table_start();
934 php_info_print_table_row(2, "libXML support", "active");
935 php_info_print_table_row(2, "libXML Compiled Version", LIBXML_DOTTED_VERSION);
936 php_info_print_table_row(2, "libXML Loaded Version", (char *)xmlParserVersion);
937 php_info_print_table_row(2, "libXML streams", "enabled");
938 php_info_print_table_end();
939 }
940
941
942
943
944 static PHP_FUNCTION(libxml_set_streams_context)
945 {
946 zval *arg;
947
948 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg) == FAILURE) {
949 return;
950 }
951 if (LIBXML(stream_context)) {
952 zval_ptr_dtor(&LIBXML(stream_context));
953 LIBXML(stream_context) = NULL;
954 }
955 Z_ADDREF_P(arg);
956 LIBXML(stream_context) = arg;
957 }
958
959
960
961
962 static PHP_FUNCTION(libxml_use_internal_errors)
963 {
964 xmlStructuredErrorFunc current_handler;
965 zend_bool use_errors=0, retval;
966
967 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &use_errors) == FAILURE) {
968 return;
969 }
970
971 current_handler = xmlStructuredError;
972 if (current_handler && current_handler == php_libxml_structured_error_handler) {
973 retval = 1;
974 } else {
975 retval = 0;
976 }
977
978 if (ZEND_NUM_ARGS() == 0) {
979 RETURN_BOOL(retval);
980 }
981
982 if (use_errors == 0) {
983 xmlSetStructuredErrorFunc(NULL, NULL);
984 if (LIBXML(error_list)) {
985 zend_llist_destroy(LIBXML(error_list));
986 efree(LIBXML(error_list));
987 LIBXML(error_list) = NULL;
988 }
989 } else {
990 xmlSetStructuredErrorFunc(NULL, php_libxml_structured_error_handler);
991 if (LIBXML(error_list) == NULL) {
992 LIBXML(error_list) = (zend_llist *) emalloc(sizeof(zend_llist));
993 zend_llist_init(LIBXML(error_list), sizeof(xmlError), (llist_dtor_func_t) _php_libxml_free_error, 0);
994 }
995 }
996 RETURN_BOOL(retval);
997 }
998
999
1000
1001
1002 static PHP_FUNCTION(libxml_get_last_error)
1003 {
1004 xmlErrorPtr error;
1005
1006 error = xmlGetLastError();
1007
1008 if (error) {
1009 object_init_ex(return_value, libxmlerror_class_entry);
1010 add_property_long(return_value, "level", error->level);
1011 add_property_long(return_value, "code", error->code);
1012 add_property_long(return_value, "column", error->int2);
1013 if (error->message) {
1014 add_property_string(return_value, "message", error->message, 1);
1015 } else {
1016 add_property_stringl(return_value, "message", "", 0, 1);
1017 }
1018 if (error->file) {
1019 add_property_string(return_value, "file", error->file, 1);
1020 } else {
1021 add_property_stringl(return_value, "file", "", 0, 1);
1022 }
1023 add_property_long(return_value, "line", error->line);
1024 } else {
1025 RETURN_FALSE;
1026 }
1027 }
1028
1029
1030
1031
1032 static PHP_FUNCTION(libxml_get_errors)
1033 {
1034
1035 xmlErrorPtr error;
1036
1037 if (array_init(return_value) == FAILURE) {
1038 RETURN_FALSE;
1039 }
1040
1041 if (LIBXML(error_list)) {
1042
1043 error = zend_llist_get_first(LIBXML(error_list));
1044
1045 while (error != NULL) {
1046 zval *z_error;
1047 MAKE_STD_ZVAL(z_error);
1048
1049 object_init_ex(z_error, libxmlerror_class_entry);
1050 add_property_long(z_error, "level", error->level);
1051 add_property_long(z_error, "code", error->code);
1052 add_property_long(z_error, "column", error->int2);
1053 if (error->message) {
1054 add_property_string(z_error, "message", error->message, 1);
1055 } else {
1056 add_property_stringl(z_error, "message", "", 0, 1);
1057 }
1058 if (error->file) {
1059 add_property_string(z_error, "file", error->file, 1);
1060 } else {
1061 add_property_stringl(z_error, "file", "", 0, 1);
1062 }
1063 add_property_long(z_error, "line", error->line);
1064 add_next_index_zval(return_value, z_error);
1065
1066 error = zend_llist_get_next(LIBXML(error_list));
1067 }
1068 }
1069 }
1070
1071
1072
1073
1074 static PHP_FUNCTION(libxml_clear_errors)
1075 {
1076 xmlResetLastError();
1077 if (LIBXML(error_list)) {
1078 zend_llist_clean(LIBXML(error_list));
1079 }
1080 }
1081
1082
1083 PHP_LIBXML_API zend_bool php_libxml_disable_entity_loader(zend_bool disable TSRMLS_DC)
1084 {
1085 zend_bool old = LIBXML(entity_loader_disabled);
1086
1087 LIBXML(entity_loader_disabled) = disable;
1088 return old;
1089 }
1090
1091
1092
1093 static PHP_FUNCTION(libxml_disable_entity_loader)
1094 {
1095 zend_bool disable = 1;
1096
1097 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &disable) == FAILURE) {
1098 return;
1099 }
1100
1101 RETURN_BOOL(php_libxml_disable_entity_loader(disable TSRMLS_CC));
1102 }
1103
1104
1105
1106
1107 static PHP_FUNCTION(libxml_set_external_entity_loader)
1108 {
1109 zend_fcall_info fci;
1110 zend_fcall_info_cache fcc;
1111 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f!", &fci, &fcc)
1112 == FAILURE) {
1113 return;
1114 }
1115
1116 _php_libxml_destroy_fci(&LIBXML(entity_loader).fci);
1117
1118 if (fci.size > 0) {
1119 LIBXML(entity_loader).fci = fci;
1120 Z_ADDREF_P(fci.function_name);
1121 if (fci.object_ptr != NULL) {
1122 Z_ADDREF_P(fci.object_ptr);
1123 }
1124 LIBXML(entity_loader).fcc = fcc;
1125 }
1126
1127 RETURN_TRUE;
1128 }
1129
1130
1131
1132 int php_libxml_xmlCheckUTF8(const unsigned char *s)
1133 {
1134 int i;
1135 unsigned char c;
1136
1137 for (i = 0; (c = s[i++]);) {
1138 if ((c & 0x80) == 0) {
1139 } else if ((c & 0xe0) == 0xc0) {
1140 if ((s[i++] & 0xc0) != 0x80) {
1141 return 0;
1142 }
1143 } else if ((c & 0xf0) == 0xe0) {
1144 if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) {
1145 return 0;
1146 }
1147 } else if ((c & 0xf8) == 0xf0) {
1148 if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) {
1149 return 0;
1150 }
1151 } else {
1152 return 0;
1153 }
1154 }
1155 return 1;
1156 }
1157
1158 int php_libxml_register_export(zend_class_entry *ce, php_libxml_export_node export_function)
1159 {
1160 php_libxml_func_handler export_hnd;
1161
1162
1163 php_libxml_initialize();
1164 export_hnd.export_func = export_function;
1165
1166 return zend_hash_add(&php_libxml_exports, ce->name, ce->name_length + 1, &export_hnd, sizeof(export_hnd), NULL);
1167 }
1168
1169 PHP_LIBXML_API xmlNodePtr php_libxml_import_node(zval *object TSRMLS_DC)
1170 {
1171 zend_class_entry *ce = NULL;
1172 xmlNodePtr node = NULL;
1173 php_libxml_func_handler *export_hnd;
1174
1175 if (object->type == IS_OBJECT) {
1176 ce = Z_OBJCE_P(object);
1177 while (ce->parent != NULL) {
1178 ce = ce->parent;
1179 }
1180 if (zend_hash_find(&php_libxml_exports, ce->name, ce->name_length + 1, (void **) &export_hnd) == SUCCESS) {
1181 node = export_hnd->export_func(object TSRMLS_CC);
1182 }
1183 }
1184 return node;
1185 }
1186
1187 PHP_LIBXML_API int php_libxml_increment_node_ptr(php_libxml_node_object *object, xmlNodePtr node, void *private_data TSRMLS_DC)
1188 {
1189 int ret_refcount = -1;
1190
1191 if (object != NULL && node != NULL) {
1192 if (object->node != NULL) {
1193 if (object->node->node == node) {
1194 return object->node->refcount;
1195 } else {
1196 php_libxml_decrement_node_ptr(object TSRMLS_CC);
1197 }
1198 }
1199 if (node->_private != NULL) {
1200 object->node = node->_private;
1201 ret_refcount = ++object->node->refcount;
1202
1203 if (object->node->_private == NULL) {
1204 object->node->_private = private_data;
1205 }
1206 } else {
1207 ret_refcount = 1;
1208 object->node = emalloc(sizeof(php_libxml_node_ptr));
1209 object->node->node = node;
1210 object->node->refcount = 1;
1211 object->node->_private = private_data;
1212 node->_private = object->node;
1213 }
1214 }
1215
1216 return ret_refcount;
1217 }
1218
1219 PHP_LIBXML_API int php_libxml_decrement_node_ptr(php_libxml_node_object *object TSRMLS_DC)
1220 {
1221 int ret_refcount = -1;
1222 php_libxml_node_ptr *obj_node;
1223
1224 if (object != NULL && object->node != NULL) {
1225 obj_node = (php_libxml_node_ptr *) object->node;
1226 ret_refcount = --obj_node->refcount;
1227 if (ret_refcount == 0) {
1228 if (obj_node->node != NULL) {
1229 obj_node->node->_private = NULL;
1230 }
1231 efree(obj_node);
1232 }
1233 object->node = NULL;
1234 }
1235
1236 return ret_refcount;
1237 }
1238
1239 PHP_LIBXML_API int php_libxml_increment_doc_ref(php_libxml_node_object *object, xmlDocPtr docp TSRMLS_DC)
1240 {
1241 int ret_refcount = -1;
1242
1243 if (object->document != NULL) {
1244 object->document->refcount++;
1245 ret_refcount = object->document->refcount;
1246 } else if (docp != NULL) {
1247 ret_refcount = 1;
1248 object->document = emalloc(sizeof(php_libxml_ref_obj));
1249 object->document->ptr = docp;
1250 object->document->refcount = ret_refcount;
1251 object->document->doc_props = NULL;
1252 }
1253
1254 return ret_refcount;
1255 }
1256
1257 PHP_LIBXML_API int php_libxml_decrement_doc_ref(php_libxml_node_object *object TSRMLS_DC)
1258 {
1259 int ret_refcount = -1;
1260
1261 if (object != NULL && object->document != NULL) {
1262 ret_refcount = --object->document->refcount;
1263 if (ret_refcount == 0) {
1264 if (object->document->ptr != NULL) {
1265 xmlFreeDoc((xmlDoc *) object->document->ptr);
1266 }
1267 if (object->document->doc_props != NULL) {
1268 if (object->document->doc_props->classmap) {
1269 zend_hash_destroy(object->document->doc_props->classmap);
1270 FREE_HASHTABLE(object->document->doc_props->classmap);
1271 }
1272 efree(object->document->doc_props);
1273 }
1274 efree(object->document);
1275 object->document = NULL;
1276 }
1277 }
1278
1279 return ret_refcount;
1280 }
1281
1282 PHP_LIBXML_API void php_libxml_node_free_resource(xmlNodePtr node TSRMLS_DC)
1283 {
1284 if (!node) {
1285 return;
1286 }
1287
1288 switch (node->type) {
1289 case XML_DOCUMENT_NODE:
1290 case XML_HTML_DOCUMENT_NODE:
1291 break;
1292 default:
1293 if (node->parent == NULL || node->type == XML_NAMESPACE_DECL) {
1294 php_libxml_node_free_list((xmlNodePtr) node->children TSRMLS_CC);
1295 switch (node->type) {
1296
1297 case XML_ATTRIBUTE_DECL:
1298 case XML_DTD_NODE:
1299 case XML_DOCUMENT_TYPE_NODE:
1300 case XML_ENTITY_DECL:
1301 case XML_ATTRIBUTE_NODE:
1302 case XML_NAMESPACE_DECL:
1303 case XML_TEXT_NODE:
1304 break;
1305 default:
1306 php_libxml_node_free_list((xmlNodePtr) node->properties TSRMLS_CC);
1307 }
1308 if (php_libxml_unregister_node(node TSRMLS_CC) == 0) {
1309 node->doc = NULL;
1310 }
1311 php_libxml_node_free(node);
1312 } else {
1313 php_libxml_unregister_node(node TSRMLS_CC);
1314 }
1315 }
1316 }
1317
1318 PHP_LIBXML_API void php_libxml_node_decrement_resource(php_libxml_node_object *object TSRMLS_DC)
1319 {
1320 int ret_refcount = -1;
1321 xmlNodePtr nodep;
1322 php_libxml_node_ptr *obj_node;
1323
1324 if (object != NULL && object->node != NULL) {
1325 obj_node = (php_libxml_node_ptr *) object->node;
1326 nodep = object->node->node;
1327 ret_refcount = php_libxml_decrement_node_ptr(object TSRMLS_CC);
1328 if (ret_refcount == 0) {
1329 php_libxml_node_free_resource(nodep TSRMLS_CC);
1330 } else {
1331 if (obj_node && object == obj_node->_private) {
1332 obj_node->_private = NULL;
1333 }
1334 }
1335 }
1336 if (object != NULL && object->document != NULL) {
1337
1338 php_libxml_decrement_doc_ref(object TSRMLS_CC);
1339 }
1340 }
1341
1342
1343 #ifdef PHP_WIN32
1344 PHP_LIBXML_API BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1345 {
1346 return xmlDllMain(hinstDLL, fdwReason, lpvReserved);
1347 }
1348 #endif
1349
1350 #endif
1351
1352
1353
1354
1355
1356
1357
1358
1359