1 | /* |
2 | +----------------------------------------------------------------------+ |
3 | | PHP Version 5 | |
4 | +----------------------------------------------------------------------+ |
5 | | Copyright (c) 1997-2015 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: Sterling Hughes <sterling@php.net> | |
16 | +----------------------------------------------------------------------+ |
17 | */ |
18 | |
19 | #include "php.h" |
20 | #if defined(HAVE_LIBXML) && (defined(HAVE_XML) || defined(HAVE_XMLRPC)) && !defined(HAVE_LIBEXPAT) |
21 | #include "expat_compat.h" |
22 | |
23 | typedef struct _php_xml_ns { |
24 | xmlNsPtr nsptr; |
25 | int ref_count; |
26 | void *next; |
27 | void *prev; |
28 | } php_xml_ns; |
29 | |
30 | #ifdef LIBXML_EXPAT_COMPAT |
31 | |
32 | #define IS_NS_DECL(__ns) \ |
33 | ((__ns) != NULL && strlen(__ns) == 5 && *(__ns) == 'x' && *((__ns)+1) == 'm' && \ |
34 | *((__ns)+2) == 'l' && *((__ns)+3) == 'n' && *((__ns)+4) == 's') |
35 | |
36 | static void |
37 | _qualify_namespace(XML_Parser parser, const xmlChar *name, const xmlChar *URI, xmlChar **qualified) |
38 | { |
39 | if (URI) { |
40 | /* Use libxml functions otherwise its memory deallocation is screwed up */ |
41 | *qualified = xmlStrdup(URI); |
42 | *qualified = xmlStrncat(*qualified, parser->_ns_separator, 1); |
43 | *qualified = xmlStrncat(*qualified, name, xmlStrlen(name)); |
44 | } else { |
45 | *qualified = xmlStrdup(name); |
46 | } |
47 | } |
48 | |
49 | static void |
50 | _start_element_handler(void *user, const xmlChar *name, const xmlChar **attributes) |
51 | { |
52 | XML_Parser parser = (XML_Parser) user; |
53 | xmlChar *qualified_name = NULL; |
54 | |
55 | if (parser->h_start_element == NULL) { |
56 | if (parser->h_default) { |
57 | int attno = 0; |
58 | |
59 | qualified_name = xmlStrncatNew((xmlChar *)"<" , name, xmlStrlen(name)); |
60 | if (attributes) { |
61 | while (attributes[attno] != NULL) { |
62 | int att_len; |
63 | char *att_string, *att_name, *att_value; |
64 | |
65 | att_name = (char *)attributes[attno++]; |
66 | att_value = (char *)attributes[attno++]; |
67 | |
68 | att_len = spprintf(&att_string, 0, " %s=\"%s\"" , att_name, att_value); |
69 | |
70 | qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_string, att_len); |
71 | efree(att_string); |
72 | } |
73 | |
74 | } |
75 | qualified_name = xmlStrncat(qualified_name, (xmlChar *)">" , 1); |
76 | parser->h_default(parser->user, (const XML_Char *) qualified_name, xmlStrlen(qualified_name)); |
77 | xmlFree(qualified_name); |
78 | } |
79 | return; |
80 | } |
81 | |
82 | qualified_name = xmlStrdup(name); |
83 | |
84 | parser->h_start_element(parser->user, (const XML_Char *) qualified_name, (const XML_Char **) attributes); |
85 | |
86 | xmlFree(qualified_name); |
87 | } |
88 | |
89 | static void |
90 | _start_element_handler_ns(void *user, const xmlChar *name, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar ** namespaces, int nb_attributes, int nb_defaulted, const xmlChar ** attributes) |
91 | { |
92 | XML_Parser parser = (XML_Parser) user; |
93 | xmlChar *qualified_name = NULL; |
94 | xmlChar **attrs = NULL; |
95 | int i; |
96 | int z = 0; |
97 | int y = 0; |
98 | |
99 | if (nb_namespaces > 0 && parser->h_start_ns != NULL) { |
100 | for (i = 0; i < nb_namespaces; i += 1) { |
101 | parser->h_start_ns(parser->user, (const XML_Char *) namespaces[y], (const XML_Char *) namespaces[y+1]); |
102 | y += 2; |
103 | } |
104 | y = 0; |
105 | } |
106 | |
107 | if (parser->h_start_element == NULL) { |
108 | if (parser->h_default) { |
109 | |
110 | if (prefix) { |
111 | qualified_name = xmlStrncatNew((xmlChar *)"<" , prefix, xmlStrlen(prefix)); |
112 | qualified_name = xmlStrncat(qualified_name, (xmlChar *)":" , 1); |
113 | qualified_name = xmlStrncat(qualified_name, name, xmlStrlen(name)); |
114 | } else { |
115 | qualified_name = xmlStrncatNew((xmlChar *)"<" , name, xmlStrlen(name)); |
116 | } |
117 | |
118 | if (namespaces) { |
119 | int i, j; |
120 | for (i = 0,j = 0;j < nb_namespaces;j++) { |
121 | int ns_len; |
122 | char *ns_string, *ns_prefix, *ns_url; |
123 | |
124 | ns_prefix = (char *) namespaces[i++]; |
125 | ns_url = (char *) namespaces[i++]; |
126 | |
127 | if (ns_prefix) { |
128 | ns_len = spprintf(&ns_string, 0, " xmlns:%s=\"%s\"" , ns_prefix, ns_url); |
129 | } else { |
130 | ns_len = spprintf(&ns_string, 0, " xmlns=\"%s\"" , ns_url); |
131 | } |
132 | qualified_name = xmlStrncat(qualified_name, (xmlChar *)ns_string, ns_len); |
133 | |
134 | efree(ns_string); |
135 | } |
136 | } |
137 | |
138 | if (attributes) { |
139 | for (i = 0; i < nb_attributes; i += 1) { |
140 | int att_len; |
141 | char *att_string, *att_name, *att_value, *att_prefix, *att_valueend; |
142 | |
143 | att_name = (char *) attributes[y++]; |
144 | att_prefix = (char *)attributes[y++]; |
145 | y++; |
146 | att_value = (char *)attributes[y++]; |
147 | att_valueend = (char *)attributes[y++]; |
148 | |
149 | if (att_prefix) { |
150 | att_len = spprintf(&att_string, 0, " %s:%s=\"" , att_prefix, att_name); |
151 | } else { |
152 | att_len = spprintf(&att_string, 0, " %s=\"" , att_name); |
153 | } |
154 | |
155 | qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_string, att_len); |
156 | qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_value, att_valueend - att_value); |
157 | qualified_name = xmlStrncat(qualified_name, (xmlChar *)"\"" , 1); |
158 | |
159 | efree(att_string); |
160 | } |
161 | |
162 | } |
163 | qualified_name = xmlStrncat(qualified_name, (xmlChar *)">" , 1); |
164 | parser->h_default(parser->user, (const XML_Char *) qualified_name, xmlStrlen(qualified_name)); |
165 | xmlFree(qualified_name); |
166 | } |
167 | return; |
168 | } |
169 | _qualify_namespace(parser, name, URI, &qualified_name); |
170 | |
171 | if (attributes != NULL) { |
172 | xmlChar *qualified_name_attr = NULL; |
173 | attrs = safe_emalloc((nb_attributes * 2) + 1, sizeof(int *), 0); |
174 | |
175 | for (i = 0; i < nb_attributes; i += 1) { |
176 | |
177 | if (attributes[y+1] != NULL) { |
178 | _qualify_namespace(parser, attributes[y] , attributes[y + 2], &qualified_name_attr); |
179 | } else { |
180 | qualified_name_attr = xmlStrdup(attributes[y]); |
181 | } |
182 | attrs[z] = qualified_name_attr; |
183 | attrs[z + 1] = xmlStrndup(attributes[y + 3] , (int) (attributes[y + 4] - attributes[y + 3])); |
184 | z += 2; |
185 | y += 5; |
186 | } |
187 | |
188 | attrs[z] = NULL; |
189 | } |
190 | parser->h_start_element(parser->user, (const XML_Char *) qualified_name, (const XML_Char **) attrs); |
191 | if (attrs) { |
192 | for (i = 0; i < z; i++) { |
193 | xmlFree(attrs[i]); |
194 | } |
195 | efree(attrs); |
196 | } |
197 | xmlFree(qualified_name); |
198 | } |
199 | |
200 | static void |
201 | _namespace_handler(XML_Parser parser, xmlNsPtr nsptr) |
202 | { |
203 | if (nsptr != NULL) { |
204 | _namespace_handler(parser, nsptr->next); |
205 | parser->h_end_ns(parser->user, nsptr->prefix); |
206 | } |
207 | } |
208 | |
209 | static void |
210 | _end_element_handler(void *user, const xmlChar *name) |
211 | { |
212 | xmlChar *qualified_name; |
213 | XML_Parser parser = (XML_Parser) user; |
214 | |
215 | if (parser->h_end_element == NULL) { |
216 | if (parser->h_default) { |
217 | char *end_element; |
218 | |
219 | spprintf(&end_element, 0, "</%s>" , (char *)name); |
220 | parser->h_default(parser->user, (const XML_Char *) end_element, strlen(end_element)); |
221 | efree(end_element); |
222 | } |
223 | return; |
224 | } |
225 | |
226 | qualified_name = xmlStrdup(name); |
227 | |
228 | parser->h_end_element(parser->user, (const XML_Char *) qualified_name); |
229 | |
230 | xmlFree(qualified_name); |
231 | } |
232 | |
233 | static void |
234 | _end_element_handler_ns(void *user, const xmlChar *name, const xmlChar * prefix, const xmlChar *URI) |
235 | { |
236 | xmlChar *qualified_name; |
237 | XML_Parser parser = (XML_Parser) user; |
238 | |
239 | if (parser->h_end_element == NULL) { |
240 | if (parser->h_default) { |
241 | char *end_element; |
242 | int end_element_len; |
243 | |
244 | if (prefix) { |
245 | end_element_len = spprintf(&end_element, 0, "</%s:%s>" , (char *) prefix, (char *)name); |
246 | } else { |
247 | end_element_len = spprintf(&end_element, 0, "</%s>" , (char *)name); |
248 | } |
249 | parser->h_default(parser->user, (const XML_Char *) end_element, end_element_len); |
250 | efree(end_element); |
251 | } |
252 | return; |
253 | } |
254 | |
255 | _qualify_namespace(parser, name, URI, &qualified_name); |
256 | |
257 | parser->h_end_element(parser->user, (const XML_Char *) qualified_name); |
258 | |
259 | xmlFree(qualified_name); |
260 | } |
261 | |
262 | static void |
263 | _cdata_handler(void *user, const xmlChar *cdata, int cdata_len) |
264 | { |
265 | XML_Parser parser = (XML_Parser) user; |
266 | |
267 | if (parser->h_cdata == NULL) { |
268 | if (parser->h_default) { |
269 | parser->h_default(parser->user, (const XML_Char *) cdata, cdata_len); |
270 | } |
271 | return; |
272 | } |
273 | |
274 | parser->h_cdata(parser->user, (const XML_Char *) cdata, cdata_len); |
275 | } |
276 | |
277 | static void |
278 | _pi_handler(void *user, const xmlChar *target, const xmlChar *data) |
279 | { |
280 | XML_Parser parser = (XML_Parser) user; |
281 | |
282 | if (parser->h_pi == NULL) { |
283 | if (parser->h_default) { |
284 | char *full_pi; |
285 | spprintf(&full_pi, 0, "<?%s %s?>" , (char *)target, (char *)data); |
286 | parser->h_default(parser->user, (const XML_Char *) full_pi, strlen(full_pi)); |
287 | efree(full_pi); |
288 | } |
289 | return; |
290 | } |
291 | |
292 | parser->h_pi(parser->user, (const XML_Char *) target, (const XML_Char *) data); |
293 | } |
294 | |
295 | static void |
296 | _unparsed_entity_decl_handler(void *user, |
297 | const xmlChar *name, |
298 | const xmlChar *pub_id, |
299 | const xmlChar *sys_id, |
300 | const xmlChar *notation) |
301 | { |
302 | XML_Parser parser = (XML_Parser) user; |
303 | |
304 | if (parser->h_unparsed_entity_decl == NULL) { |
305 | return; |
306 | } |
307 | |
308 | parser->h_unparsed_entity_decl(parser->user, name, NULL, sys_id, pub_id, notation); |
309 | } |
310 | |
311 | static void |
312 | _notation_decl_handler(void *user, const xmlChar *notation, const xmlChar *pub_id, const xmlChar *sys_id) |
313 | { |
314 | XML_Parser parser = (XML_Parser) user; |
315 | |
316 | if (parser->h_notation_decl == NULL) { |
317 | return; |
318 | } |
319 | |
320 | parser->h_notation_decl(parser->user, notation, NULL, sys_id, pub_id); |
321 | } |
322 | |
323 | static void |
324 | (const xmlChar *data, int data_len, xmlChar **, int *) |
325 | { |
326 | *comment_len = data_len + 7; |
327 | |
328 | *comment = xmlMalloc(*comment_len + 1); |
329 | memcpy(*comment, "<!--" , 4); |
330 | memcpy(*comment + 4, data, data_len); |
331 | memcpy(*comment + 4 + data_len, "-->" , 3); |
332 | |
333 | (*comment)[*comment_len] = '\0'; |
334 | } |
335 | |
336 | static void |
337 | _comment_handler(void *user, const xmlChar *) |
338 | { |
339 | XML_Parser parser = (XML_Parser) user; |
340 | |
341 | if (parser->h_default) { |
342 | xmlChar *; |
343 | int ; |
344 | |
345 | _build_comment(comment, xmlStrlen(comment), &d_comment, &d_comment_len); |
346 | parser->h_default(parser->user, d_comment, d_comment_len); |
347 | xmlFree(d_comment); |
348 | } |
349 | } |
350 | |
351 | static void |
352 | _build_entity(const xmlChar *name, int len, xmlChar **entity, int *entity_len) |
353 | { |
354 | *entity_len = len + 2; |
355 | *entity = xmlMalloc(*entity_len + 1); |
356 | (*entity)[0] = '&'; |
357 | memcpy(*entity+1, name, len); |
358 | (*entity)[len+1] = ';'; |
359 | (*entity)[*entity_len] = '\0'; |
360 | } |
361 | |
362 | static void |
363 | _external_entity_ref_handler(void *user, const xmlChar *names, int type, const xmlChar *sys_id, const xmlChar *pub_id, xmlChar *content) |
364 | { |
365 | XML_Parser parser = (XML_Parser) user; |
366 | |
367 | if (parser->h_external_entity_ref == NULL) { |
368 | return; |
369 | } |
370 | |
371 | parser->h_external_entity_ref(parser, names, "" , sys_id, pub_id); |
372 | } |
373 | |
374 | static xmlEntityPtr |
375 | _get_entity(void *user, const xmlChar *name) |
376 | { |
377 | XML_Parser parser = (XML_Parser) user; |
378 | xmlEntityPtr ret = NULL; |
379 | |
380 | if (parser->parser->inSubset == 0) { |
381 | ret = xmlGetPredefinedEntity(name); |
382 | if (ret == NULL) |
383 | ret = xmlGetDocEntity(parser->parser->myDoc, name); |
384 | |
385 | if (ret == NULL || (parser->parser->instate != XML_PARSER_ENTITY_VALUE && parser->parser->instate != XML_PARSER_ATTRIBUTE_VALUE)) { |
386 | if (ret == NULL || ret->etype == XML_INTERNAL_GENERAL_ENTITY || ret->etype == XML_INTERNAL_PARAMETER_ENTITY || ret->etype == XML_INTERNAL_PREDEFINED_ENTITY) { |
387 | /* Predefined entities will expand unless no cdata handler is present */ |
388 | if (parser->h_default && ! (ret && ret->etype == XML_INTERNAL_PREDEFINED_ENTITY && parser->h_cdata)) { |
389 | xmlChar *entity; |
390 | int len; |
391 | |
392 | _build_entity(name, xmlStrlen(name), &entity, &len); |
393 | parser->h_default(parser->user, (const xmlChar *) entity, len); |
394 | xmlFree(entity); |
395 | } else { |
396 | /* expat will not expand internal entities if default handler is present otherwise |
397 | it will expand and pass them to cdata handler */ |
398 | if (parser->h_cdata && ret) { |
399 | parser->h_cdata(parser->user, ret->content, xmlStrlen(ret->content)); |
400 | } |
401 | } |
402 | } else { |
403 | if (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) { |
404 | _external_entity_ref_handler(user, ret->name, ret->etype, ret->SystemID, ret->ExternalID, NULL); |
405 | } |
406 | } |
407 | } |
408 | } |
409 | |
410 | return ret; |
411 | } |
412 | |
413 | static xmlSAXHandler |
414 | php_xml_compat_handlers = { |
415 | NULL, /* internalSubset */ |
416 | NULL, /* isStandalone */ |
417 | NULL, /* hasInternalSubset */ |
418 | NULL, /* hasExternalSubset */ |
419 | NULL, /* resolveEntity */ |
420 | _get_entity, /* getEntity */ |
421 | NULL, /* entityDecl */ |
422 | _notation_decl_handler, |
423 | NULL, /* attributeDecl */ |
424 | NULL, /* elementDecl */ |
425 | _unparsed_entity_decl_handler, /* unparsedEntity */ |
426 | NULL, /* setDocumentLocator */ |
427 | NULL, /* startDocument */ |
428 | NULL, /* endDocument */ |
429 | _start_element_handler, /* startElement */ |
430 | _end_element_handler, /* endElement */ |
431 | NULL, /* reference */ |
432 | _cdata_handler, |
433 | NULL, /* ignorableWhitespace */ |
434 | _pi_handler, |
435 | _comment_handler, /* comment */ |
436 | NULL, /* warning */ |
437 | NULL, /* error */ |
438 | NULL, /* fatalError */ |
439 | NULL, /* getParameterEntity */ |
440 | _cdata_handler, /* cdataBlock */ |
441 | NULL, /* externalSubset */ |
442 | XML_SAX2_MAGIC, |
443 | NULL, |
444 | _start_element_handler_ns, |
445 | _end_element_handler_ns, |
446 | NULL |
447 | }; |
448 | |
449 | PHPAPI XML_Parser |
450 | XML_ParserCreate(const XML_Char *encoding) |
451 | { |
452 | return XML_ParserCreate_MM(encoding, NULL, NULL); |
453 | } |
454 | |
455 | PHPAPI XML_Parser |
456 | XML_ParserCreateNS(const XML_Char *encoding, const XML_Char sep) |
457 | { |
458 | XML_Char tmp[2]; |
459 | tmp[0] = sep; |
460 | tmp[1] = '\0'; |
461 | return XML_ParserCreate_MM(encoding, NULL, tmp); |
462 | } |
463 | |
464 | PHPAPI XML_Parser |
465 | XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *memsuite, const XML_Char *sep) |
466 | { |
467 | XML_Parser parser; |
468 | |
469 | parser = (XML_Parser) emalloc(sizeof(struct _XML_Parser)); |
470 | memset(parser, 0, sizeof(struct _XML_Parser)); |
471 | parser->use_namespace = 0; |
472 | parser->_ns_separator = NULL; |
473 | |
474 | parser->parser = xmlCreatePushParserCtxt((xmlSAXHandlerPtr) &php_xml_compat_handlers, (void *) parser, NULL, 0, NULL); |
475 | if (parser->parser == NULL) { |
476 | efree(parser); |
477 | return NULL; |
478 | } |
479 | #if LIBXML_VERSION <= 20617 |
480 | /* for older versions of libxml2, allow correct detection of |
481 | * charset in documents with a BOM: */ |
482 | parser->parser->charset = XML_CHAR_ENCODING_NONE; |
483 | #endif |
484 | |
485 | #if LIBXML_VERSION >= 20703 |
486 | xmlCtxtUseOptions(parser->parser, XML_PARSE_OLDSAX); |
487 | #endif |
488 | |
489 | parser->parser->replaceEntities = 1; |
490 | parser->parser->wellFormed = 0; |
491 | if (sep != NULL) { |
492 | parser->use_namespace = 1; |
493 | parser->parser->sax2 = 1; |
494 | parser->_ns_separator = xmlStrdup(sep); |
495 | } else { |
496 | /* Reset flag as XML_SAX2_MAGIC is needed for xmlCreatePushParserCtxt |
497 | so must be set in the handlers */ |
498 | parser->parser->sax->initialized = 1; |
499 | } |
500 | return parser; |
501 | } |
502 | |
503 | PHPAPI void |
504 | XML_SetUserData(XML_Parser parser, void *user) |
505 | { |
506 | parser->user = user; |
507 | } |
508 | |
509 | PHPAPI void * |
510 | XML_GetUserData(XML_Parser parser) |
511 | { |
512 | return parser->user; |
513 | } |
514 | |
515 | PHPAPI void |
516 | XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end) |
517 | { |
518 | parser->h_start_element = start; |
519 | parser->h_end_element = end; |
520 | } |
521 | |
522 | PHPAPI void |
523 | XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler cdata) |
524 | { |
525 | parser->h_cdata = cdata; |
526 | } |
527 | |
528 | PHPAPI void |
529 | XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler pi) |
530 | { |
531 | parser->h_pi = pi; |
532 | } |
533 | |
534 | PHPAPI void |
535 | XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler ) |
536 | { |
537 | parser->h_comment = comment; |
538 | } |
539 | |
540 | PHPAPI void |
541 | XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler d) |
542 | { |
543 | parser->h_default = d; |
544 | } |
545 | |
546 | PHPAPI void |
547 | XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler unparsed_decl) |
548 | { |
549 | parser->h_unparsed_entity_decl = unparsed_decl; |
550 | } |
551 | |
552 | PHPAPI void |
553 | XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler notation_decl) |
554 | { |
555 | parser->h_notation_decl = notation_decl; |
556 | } |
557 | |
558 | PHPAPI void |
559 | XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler ext_entity) |
560 | { |
561 | parser->h_external_entity_ref = ext_entity; |
562 | } |
563 | |
564 | PHPAPI void |
565 | XML_SetStartNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start_ns) |
566 | { |
567 | parser->h_start_ns = start_ns; |
568 | } |
569 | |
570 | PHPAPI void |
571 | XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler end_ns) |
572 | { |
573 | parser->h_end_ns = end_ns; |
574 | } |
575 | |
576 | PHPAPI int |
577 | XML_Parse(XML_Parser parser, const XML_Char *data, int data_len, int is_final) |
578 | { |
579 | int error; |
580 | |
581 | /* The following is a hack to keep BC with PHP 4 while avoiding |
582 | the inifite loop in libxml <= 2.6.17 which occurs when no encoding |
583 | has been defined and none can be detected */ |
584 | #if LIBXML_VERSION <= 20617 |
585 | if (parser->parser->charset == XML_CHAR_ENCODING_NONE) { |
586 | if (data_len >= 4 || (parser->parser->input->buf->buffer->use + data_len >= 4)) { |
587 | xmlChar start[4]; |
588 | int char_count; |
589 | |
590 | char_count = parser->parser->input->buf->buffer->use; |
591 | if (char_count > 4) { |
592 | char_count = 4; |
593 | } |
594 | |
595 | memcpy(start, parser->parser->input->buf->buffer->content, (size_t)char_count); |
596 | memcpy(start + char_count, data, (size_t)(4 - char_count)); |
597 | |
598 | if (xmlDetectCharEncoding(&start[0], 4) == XML_CHAR_ENCODING_NONE) { |
599 | parser->parser->charset = XML_CHAR_ENCODING_UTF8; |
600 | } |
601 | } |
602 | } |
603 | #endif |
604 | |
605 | error = xmlParseChunk(parser->parser, data, data_len, is_final); |
606 | if (!error) { |
607 | return 1; |
608 | } else if (parser->parser->lastError.level > XML_ERR_WARNING ){ |
609 | return 0; |
610 | } else { |
611 | return 1; |
612 | } |
613 | } |
614 | |
615 | PHPAPI int |
616 | XML_GetErrorCode(XML_Parser parser) |
617 | { |
618 | return parser->parser->errNo; |
619 | } |
620 | |
621 | static const XML_Char *const error_mapping[] = { |
622 | (const XML_Char *)"No error" , |
623 | (const XML_Char *)"No memory" , |
624 | (const XML_Char *)"Invalid document start" , |
625 | (const XML_Char *)"Empty document" , |
626 | (const XML_Char *)"Not well-formed (invalid token)" , |
627 | (const XML_Char *)"Invalid document end" , |
628 | (const XML_Char *)"Invalid hexadecimal character reference" , |
629 | (const XML_Char *)"Invalid decimal character reference" , |
630 | (const XML_Char *)"Invalid character reference" , |
631 | (const XML_Char *)"Invalid character" , |
632 | (const XML_Char *)"XML_ERR_CHARREF_AT_EOF" , |
633 | (const XML_Char *)"XML_ERR_CHARREF_IN_PROLOG" , |
634 | (const XML_Char *)"XML_ERR_CHARREF_IN_EPILOG" , |
635 | (const XML_Char *)"XML_ERR_CHARREF_IN_DTD" , |
636 | (const XML_Char *)"XML_ERR_ENTITYREF_AT_EOF" , |
637 | (const XML_Char *)"XML_ERR_ENTITYREF_IN_PROLOG" , |
638 | (const XML_Char *)"XML_ERR_ENTITYREF_IN_EPILOG" , |
639 | (const XML_Char *)"XML_ERR_ENTITYREF_IN_DTD" , |
640 | (const XML_Char *)"PEReference at end of document" , |
641 | (const XML_Char *)"PEReference in prolog" , |
642 | (const XML_Char *)"PEReference in epilog" , |
643 | (const XML_Char *)"PEReference: forbidden within markup decl in internal subset" , |
644 | (const XML_Char *)"XML_ERR_ENTITYREF_NO_NAME" , |
645 | (const XML_Char *)"EntityRef: expecting ';'" , |
646 | (const XML_Char *)"PEReference: no name" , |
647 | (const XML_Char *)"PEReference: expecting ';'" , |
648 | (const XML_Char *)"Undeclared entity error" , |
649 | (const XML_Char *)"Undeclared entity warning" , |
650 | (const XML_Char *)"Unparsed Entity" , |
651 | (const XML_Char *)"XML_ERR_ENTITY_IS_EXTERNAL" , |
652 | (const XML_Char *)"XML_ERR_ENTITY_IS_PARAMETER" , |
653 | (const XML_Char *)"Unknown encoding" , |
654 | (const XML_Char *)"Unsupported encoding" , |
655 | (const XML_Char *)"String not started expecting ' or \"" , |
656 | (const XML_Char *)"String not closed expecting \" or '" , |
657 | (const XML_Char *)"Namespace declaration error" , |
658 | (const XML_Char *)"EntityValue: \" or ' expected" , |
659 | (const XML_Char *)"EntityValue: \" or ' expected" , |
660 | (const XML_Char *)"< in attribute" , |
661 | (const XML_Char *)"Attribute not started" , |
662 | (const XML_Char *)"Attribute not finished" , |
663 | (const XML_Char *)"Attribute without value" , |
664 | (const XML_Char *)"Attribute redefined" , |
665 | (const XML_Char *)"SystemLiteral \" or ' expected" , |
666 | (const XML_Char *)"SystemLiteral \" or ' expected" , |
667 | /* (const XML_Char *)"XML_ERR_COMMENT_NOT_STARTED", <= eliminated on purpose */ |
668 | (const XML_Char *)"Comment not finished" , |
669 | (const XML_Char *)"Processing Instruction not started" , |
670 | (const XML_Char *)"Processing Instruction not finished" , |
671 | (const XML_Char *)"NOTATION: Name expected here" , |
672 | (const XML_Char *)"'>' required to close NOTATION declaration" , |
673 | (const XML_Char *)"'(' required to start ATTLIST enumeration" , |
674 | (const XML_Char *)"'(' required to start ATTLIST enumeration" , |
675 | (const XML_Char *)"MixedContentDecl : '|' or ')*' expected" , |
676 | (const XML_Char *)"XML_ERR_MIXED_NOT_FINISHED" , |
677 | (const XML_Char *)"ELEMENT in DTD not started" , |
678 | (const XML_Char *)"ELEMENT in DTD not finished" , |
679 | (const XML_Char *)"XML declaration not started" , |
680 | (const XML_Char *)"XML declaration not finished" , |
681 | (const XML_Char *)"XML_ERR_CONDSEC_NOT_STARTED" , |
682 | (const XML_Char *)"XML conditional section not closed" , |
683 | (const XML_Char *)"Content error in the external subset" , |
684 | (const XML_Char *)"DOCTYPE not finished" , |
685 | (const XML_Char *)"Sequence ']]>' not allowed in content" , |
686 | (const XML_Char *)"CDATA not finished" , |
687 | (const XML_Char *)"Reserved XML Name" , |
688 | (const XML_Char *)"Space required" , |
689 | (const XML_Char *)"XML_ERR_SEPARATOR_REQUIRED" , |
690 | (const XML_Char *)"NmToken expected in ATTLIST enumeration" , |
691 | (const XML_Char *)"XML_ERR_NAME_REQUIRED" , |
692 | (const XML_Char *)"MixedContentDecl : '#PCDATA' expected" , |
693 | (const XML_Char *)"SYSTEM or PUBLIC, the URI is missing" , |
694 | (const XML_Char *)"PUBLIC, the Public Identifier is missing" , |
695 | (const XML_Char *)"< required" , |
696 | (const XML_Char *)"> required" , |
697 | (const XML_Char *)"</ required" , |
698 | (const XML_Char *)"= required" , |
699 | (const XML_Char *)"Mismatched tag" , |
700 | (const XML_Char *)"Tag not finished" , |
701 | (const XML_Char *)"standalone accepts only 'yes' or 'no'" , |
702 | (const XML_Char *)"Invalid XML encoding name" , |
703 | (const XML_Char *)"Comment must not contain '--' (double-hyphen)" , |
704 | (const XML_Char *)"Invalid encoding" , |
705 | (const XML_Char *)"external parsed entities cannot be standalone" , |
706 | (const XML_Char *)"XML conditional section '[' expected" , |
707 | (const XML_Char *)"Entity value required" , |
708 | (const XML_Char *)"chunk is not well balanced" , |
709 | (const XML_Char *)"extra content at the end of well balanced chunk" , |
710 | (const XML_Char *)"XML_ERR_ENTITY_CHAR_ERROR" , |
711 | (const XML_Char *)"PEReferences forbidden in internal subset" , |
712 | (const XML_Char *)"Detected an entity reference loop" , |
713 | (const XML_Char *)"XML_ERR_ENTITY_BOUNDARY" , |
714 | (const XML_Char *)"Invalid URI" , |
715 | (const XML_Char *)"Fragment not allowed" , |
716 | (const XML_Char *)"XML_WAR_CATALOG_PI" , |
717 | (const XML_Char *)"XML_ERR_NO_DTD" , |
718 | (const XML_Char *)"conditional section INCLUDE or IGNORE keyword expected" , /* 95 */ |
719 | (const XML_Char *)"Version in XML Declaration missing" , /* 96 */ |
720 | (const XML_Char *)"XML_WAR_UNKNOWN_VERSION" , /* 97 */ |
721 | (const XML_Char *)"XML_WAR_LANG_VALUE" , /* 98 */ |
722 | (const XML_Char *)"XML_WAR_NS_URI" , /* 99 */ |
723 | (const XML_Char *)"XML_WAR_NS_URI_RELATIVE" , /* 100 */ |
724 | (const XML_Char *)"Missing encoding in text declaration" /* 101 */ |
725 | }; |
726 | |
727 | PHPAPI const XML_Char * |
728 | XML_ErrorString(int code) |
729 | { |
730 | if (code < 0 || code >= (int)(sizeof(error_mapping) / sizeof(error_mapping[0]))) { |
731 | return "Unknown" ; |
732 | } |
733 | return error_mapping[code]; |
734 | } |
735 | |
736 | PHPAPI int |
737 | XML_GetCurrentLineNumber(XML_Parser parser) |
738 | { |
739 | return parser->parser->input->line; |
740 | } |
741 | |
742 | PHPAPI int |
743 | XML_GetCurrentColumnNumber(XML_Parser parser) |
744 | { |
745 | return parser->parser->input->col; |
746 | } |
747 | |
748 | PHPAPI int |
749 | XML_GetCurrentByteIndex(XML_Parser parser) |
750 | { |
751 | return parser->parser->input->consumed + |
752 | (parser->parser->input->cur - parser->parser->input->base); |
753 | } |
754 | |
755 | PHPAPI int |
756 | XML_GetCurrentByteCount(XML_Parser parser) |
757 | { |
758 | /* WARNING: this is identical to ByteIndex; it should probably |
759 | * be different */ |
760 | return parser->parser->input->consumed + |
761 | (parser->parser->input->cur - parser->parser->input->base); |
762 | } |
763 | |
764 | PHPAPI const XML_Char *XML_ExpatVersion(void) |
765 | { |
766 | return "1.0" ; |
767 | } |
768 | |
769 | PHPAPI void |
770 | XML_ParserFree(XML_Parser parser) |
771 | { |
772 | if (parser->use_namespace) { |
773 | if (parser->_ns_separator) { |
774 | xmlFree(parser->_ns_separator); |
775 | } |
776 | } |
777 | if (parser->parser->myDoc) { |
778 | xmlFreeDoc(parser->parser->myDoc); |
779 | parser->parser->myDoc = NULL; |
780 | } |
781 | xmlFreeParserCtxt(parser->parser); |
782 | efree(parser); |
783 | } |
784 | |
785 | #endif /* LIBXML_EXPAT_COMPAT */ |
786 | #endif |
787 | |
788 | /** |
789 | * Local Variables: |
790 | * tab-width: 4 |
791 | * c-basic-offset: 4 |
792 | * indent-tabs-mode: t |
793 | * End: |
794 | * vim600: fdm=marker |
795 | * vim: ts=4 noet sw=4 |
796 | */ |
797 | |