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