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