Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenparser.c
Go to the documentation of this file.
00001 /* 00002 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly 00003 * implemented on top of the SAX interfaces 00004 * 00005 * References: 00006 * The XML specification: 00007 * http://www.w3.org/TR/REC-xml 00008 * Original 1.0 version: 00009 * http://www.w3.org/TR/1998/REC-xml-19980210 00010 * XML second edition working draft 00011 * http://www.w3.org/TR/2000/WD-xml-2e-20000814 00012 * 00013 * Okay this is a big file, the parser core is around 7000 lines, then it 00014 * is followed by the progressive parser top routines, then the various 00015 * high level APIs to call the parser and a few miscellaneous functions. 00016 * A number of helper functions and deprecated ones have been moved to 00017 * parserInternals.c to reduce this file size. 00018 * As much as possible the functions are associated with their relative 00019 * production in the XML specification. A few productions defining the 00020 * different ranges of character are actually implanted either in 00021 * parserInternals.h or parserInternals.c 00022 * The DOM tree build is realized from the default SAX callbacks in 00023 * the module SAX.c. 00024 * The routines doing the validation checks are in valid.c and called either 00025 * from the SAX callbacks or as standalone functions using a preparsed 00026 * document. 00027 * 00028 * See Copyright for the status of this software. 00029 * 00030 * daniel@veillard.com 00031 */ 00032 00033 #define IN_LIBXML 00034 #include "libxml.h" 00035 00036 #if defined(WIN32) && !defined (__CYGWIN__) 00037 #define XML_DIR_SEP '\\' 00038 #else 00039 #define XML_DIR_SEP '/' 00040 #endif 00041 00042 #include <stdlib.h> 00043 #include <string.h> 00044 #include <stdarg.h> 00045 #include <libxml/xmlmemory.h> 00046 #include <libxml/threads.h> 00047 #include <libxml/globals.h> 00048 #include <libxml/tree.h> 00049 #include <libxml/parser.h> 00050 #include <libxml/parserInternals.h> 00051 #include <libxml/valid.h> 00052 #include <libxml/entities.h> 00053 #include <libxml/xmlerror.h> 00054 #include <libxml/encoding.h> 00055 #include <libxml/xmlIO.h> 00056 #include <libxml/uri.h> 00057 #ifdef LIBXML_CATALOG_ENABLED 00058 #include <libxml/catalog.h> 00059 #endif 00060 #ifdef LIBXML_SCHEMAS_ENABLED 00061 #include <libxml/xmlschemastypes.h> 00062 #include <libxml/relaxng.h> 00063 #endif 00064 #ifdef HAVE_CTYPE_H 00065 #include <ctype.h> 00066 #endif 00067 #ifdef HAVE_STDLIB_H 00068 #include <stdlib.h> 00069 #endif 00070 #ifdef HAVE_SYS_STAT_H 00071 #include <sys/stat.h> 00072 #endif 00073 #ifdef HAVE_FCNTL_H 00074 #include <fcntl.h> 00075 #endif 00076 #ifdef HAVE_UNISTD_H 00077 #include <unistd.h> 00078 #endif 00079 #ifdef HAVE_ZLIB_H 00080 #include <zlib.h> 00081 #endif 00082 00083 static void 00084 xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info); 00085 00086 static xmlParserCtxtPtr 00087 xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID, 00088 const xmlChar *base, xmlParserCtxtPtr pctx); 00089 00090 /************************************************************************ 00091 * * 00092 * Arbitrary limits set in the parser. See XML_PARSE_HUGE * 00093 * * 00094 ************************************************************************/ 00095 00096 #define XML_PARSER_BIG_ENTITY 1000 00097 #define XML_PARSER_LOT_ENTITY 5000 00098 00099 /* 00100 * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity 00101 * replacement over the size in byte of the input indicates that you have 00102 * and eponential behaviour. A value of 10 correspond to at least 3 entity 00103 * replacement per byte of input. 00104 */ 00105 #define XML_PARSER_NON_LINEAR 10 00106 00107 /* 00108 * xmlParserEntityCheck 00109 * 00110 * Function to check non-linear entity expansion behaviour 00111 * This is here to detect and stop exponential linear entity expansion 00112 * This is not a limitation of the parser but a safety 00113 * boundary feature. It can be disabled with the XML_PARSE_HUGE 00114 * parser option. 00115 */ 00116 static int 00117 xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size, 00118 xmlEntityPtr ent) 00119 { 00120 unsigned long consumed = 0; 00121 00122 if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE)) 00123 return (0); 00124 if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) 00125 return (1); 00126 if (size != 0) { 00127 /* 00128 * Do the check based on the replacement size of the entity 00129 */ 00130 if (size < XML_PARSER_BIG_ENTITY) 00131 return(0); 00132 00133 /* 00134 * A limit on the amount of text data reasonably used 00135 */ 00136 if (ctxt->input != NULL) { 00137 consumed = ctxt->input->consumed + 00138 (ctxt->input->cur - ctxt->input->base); 00139 } 00140 consumed += ctxt->sizeentities; 00141 00142 if ((size < XML_PARSER_NON_LINEAR * consumed) && 00143 (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed)) 00144 return (0); 00145 } else if (ent != NULL) { 00146 /* 00147 * use the number of parsed entities in the replacement 00148 */ 00149 size = ent->checked; 00150 00151 /* 00152 * The amount of data parsed counting entities size only once 00153 */ 00154 if (ctxt->input != NULL) { 00155 consumed = ctxt->input->consumed + 00156 (ctxt->input->cur - ctxt->input->base); 00157 } 00158 consumed += ctxt->sizeentities; 00159 00160 /* 00161 * Check the density of entities for the amount of data 00162 * knowing an entity reference will take at least 3 bytes 00163 */ 00164 if (size * 3 < consumed * XML_PARSER_NON_LINEAR) 00165 return (0); 00166 } else { 00167 /* 00168 * strange we got no data for checking just return 00169 */ 00170 return (0); 00171 } 00172 00173 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); 00174 return (1); 00175 } 00176 00185 unsigned int xmlParserMaxDepth = 256; 00186 00187 00188 00189 #define SAX2 1 00190 #define XML_PARSER_BIG_BUFFER_SIZE 300 00191 #define XML_PARSER_BUFFER_SIZE 100 00192 #define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document" 00193 00194 /* 00195 * List of XML prefixed PI allowed by W3C specs 00196 */ 00197 00198 static const char *xmlW3CPIs[] = { 00199 "xml-stylesheet", 00200 NULL 00201 }; 00202 00203 00204 /* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */ 00205 static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt, 00206 const xmlChar **str); 00207 00208 static xmlParserErrors 00209 xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, 00210 xmlSAXHandlerPtr sax, 00211 void *user_data, int depth, const xmlChar *URL, 00212 const xmlChar *ID, xmlNodePtr *list); 00213 00214 static int 00215 xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, 00216 const char *encoding); 00217 #ifdef LIBXML_LEGACY_ENABLED 00218 static void 00219 xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode, 00220 xmlNodePtr lastNode); 00221 #endif /* LIBXML_LEGACY_ENABLED */ 00222 00223 static xmlParserErrors 00224 xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, 00225 const xmlChar *string, void *user_data, xmlNodePtr *lst); 00226 00227 static int 00228 xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity); 00229 00230 /************************************************************************ 00231 * * 00232 * Some factorized error routines * 00233 * * 00234 ************************************************************************/ 00235 00244 static void 00245 xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix, 00246 const xmlChar * localname) 00247 { 00248 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00249 (ctxt->instate == XML_PARSER_EOF)) 00250 return; 00251 if (ctxt != NULL) 00252 ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED; 00253 00254 if (prefix == NULL) 00255 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, 00256 XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0, 00257 (const char *) localname, NULL, NULL, 0, 0, 00258 "Attribute %s redefined\n", localname); 00259 else 00260 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, 00261 XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0, 00262 (const char *) prefix, (const char *) localname, 00263 NULL, 0, 0, "Attribute %s:%s redefined\n", prefix, 00264 localname); 00265 if (ctxt != NULL) { 00266 ctxt->wellFormed = 0; 00267 if (ctxt->recovery == 0) 00268 ctxt->disableSAX = 1; 00269 } 00270 } 00271 00280 static void 00281 xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info) 00282 { 00283 const char *errmsg; 00284 00285 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00286 (ctxt->instate == XML_PARSER_EOF)) 00287 return; 00288 switch (error) { 00289 case XML_ERR_INVALID_HEX_CHARREF: 00290 errmsg = "CharRef: invalid hexadecimal value\n"; 00291 break; 00292 case XML_ERR_INVALID_DEC_CHARREF: 00293 errmsg = "CharRef: invalid decimal value\n"; 00294 break; 00295 case XML_ERR_INVALID_CHARREF: 00296 errmsg = "CharRef: invalid value\n"; 00297 break; 00298 case XML_ERR_INTERNAL_ERROR: 00299 errmsg = "internal error"; 00300 break; 00301 case XML_ERR_PEREF_AT_EOF: 00302 errmsg = "PEReference at end of document\n"; 00303 break; 00304 case XML_ERR_PEREF_IN_PROLOG: 00305 errmsg = "PEReference in prolog\n"; 00306 break; 00307 case XML_ERR_PEREF_IN_EPILOG: 00308 errmsg = "PEReference in epilog\n"; 00309 break; 00310 case XML_ERR_PEREF_NO_NAME: 00311 errmsg = "PEReference: no name\n"; 00312 break; 00313 case XML_ERR_PEREF_SEMICOL_MISSING: 00314 errmsg = "PEReference: expecting ';'\n"; 00315 break; 00316 case XML_ERR_ENTITY_LOOP: 00317 errmsg = "Detected an entity reference loop\n"; 00318 break; 00319 case XML_ERR_ENTITY_NOT_STARTED: 00320 errmsg = "EntityValue: \" or ' expected\n"; 00321 break; 00322 case XML_ERR_ENTITY_PE_INTERNAL: 00323 errmsg = "PEReferences forbidden in internal subset\n"; 00324 break; 00325 case XML_ERR_ENTITY_NOT_FINISHED: 00326 errmsg = "EntityValue: \" or ' expected\n"; 00327 break; 00328 case XML_ERR_ATTRIBUTE_NOT_STARTED: 00329 errmsg = "AttValue: \" or ' expected\n"; 00330 break; 00331 case XML_ERR_LT_IN_ATTRIBUTE: 00332 errmsg = "Unescaped '<' not allowed in attributes values\n"; 00333 break; 00334 case XML_ERR_LITERAL_NOT_STARTED: 00335 errmsg = "SystemLiteral \" or ' expected\n"; 00336 break; 00337 case XML_ERR_LITERAL_NOT_FINISHED: 00338 errmsg = "Unfinished System or Public ID \" or ' expected\n"; 00339 break; 00340 case XML_ERR_MISPLACED_CDATA_END: 00341 errmsg = "Sequence ']]>' not allowed in content\n"; 00342 break; 00343 case XML_ERR_URI_REQUIRED: 00344 errmsg = "SYSTEM or PUBLIC, the URI is missing\n"; 00345 break; 00346 case XML_ERR_PUBID_REQUIRED: 00347 errmsg = "PUBLIC, the Public Identifier is missing\n"; 00348 break; 00349 case XML_ERR_HYPHEN_IN_COMMENT: 00350 errmsg = "Comment must not contain '--' (double-hyphen)\n"; 00351 break; 00352 case XML_ERR_PI_NOT_STARTED: 00353 errmsg = "xmlParsePI : no target name\n"; 00354 break; 00355 case XML_ERR_RESERVED_XML_NAME: 00356 errmsg = "Invalid PI name\n"; 00357 break; 00358 case XML_ERR_NOTATION_NOT_STARTED: 00359 errmsg = "NOTATION: Name expected here\n"; 00360 break; 00361 case XML_ERR_NOTATION_NOT_FINISHED: 00362 errmsg = "'>' required to close NOTATION declaration\n"; 00363 break; 00364 case XML_ERR_VALUE_REQUIRED: 00365 errmsg = "Entity value required\n"; 00366 break; 00367 case XML_ERR_URI_FRAGMENT: 00368 errmsg = "Fragment not allowed"; 00369 break; 00370 case XML_ERR_ATTLIST_NOT_STARTED: 00371 errmsg = "'(' required to start ATTLIST enumeration\n"; 00372 break; 00373 case XML_ERR_NMTOKEN_REQUIRED: 00374 errmsg = "NmToken expected in ATTLIST enumeration\n"; 00375 break; 00376 case XML_ERR_ATTLIST_NOT_FINISHED: 00377 errmsg = "')' required to finish ATTLIST enumeration\n"; 00378 break; 00379 case XML_ERR_MIXED_NOT_STARTED: 00380 errmsg = "MixedContentDecl : '|' or ')*' expected\n"; 00381 break; 00382 case XML_ERR_PCDATA_REQUIRED: 00383 errmsg = "MixedContentDecl : '#PCDATA' expected\n"; 00384 break; 00385 case XML_ERR_ELEMCONTENT_NOT_STARTED: 00386 errmsg = "ContentDecl : Name or '(' expected\n"; 00387 break; 00388 case XML_ERR_ELEMCONTENT_NOT_FINISHED: 00389 errmsg = "ContentDecl : ',' '|' or ')' expected\n"; 00390 break; 00391 case XML_ERR_PEREF_IN_INT_SUBSET: 00392 errmsg = 00393 "PEReference: forbidden within markup decl in internal subset\n"; 00394 break; 00395 case XML_ERR_GT_REQUIRED: 00396 errmsg = "expected '>'\n"; 00397 break; 00398 case XML_ERR_CONDSEC_INVALID: 00399 errmsg = "XML conditional section '[' expected\n"; 00400 break; 00401 case XML_ERR_EXT_SUBSET_NOT_FINISHED: 00402 errmsg = "Content error in the external subset\n"; 00403 break; 00404 case XML_ERR_CONDSEC_INVALID_KEYWORD: 00405 errmsg = 00406 "conditional section INCLUDE or IGNORE keyword expected\n"; 00407 break; 00408 case XML_ERR_CONDSEC_NOT_FINISHED: 00409 errmsg = "XML conditional section not closed\n"; 00410 break; 00411 case XML_ERR_XMLDECL_NOT_STARTED: 00412 errmsg = "Text declaration '<?xml' required\n"; 00413 break; 00414 case XML_ERR_XMLDECL_NOT_FINISHED: 00415 errmsg = "parsing XML declaration: '?>' expected\n"; 00416 break; 00417 case XML_ERR_EXT_ENTITY_STANDALONE: 00418 errmsg = "external parsed entities cannot be standalone\n"; 00419 break; 00420 case XML_ERR_ENTITYREF_SEMICOL_MISSING: 00421 errmsg = "EntityRef: expecting ';'\n"; 00422 break; 00423 case XML_ERR_DOCTYPE_NOT_FINISHED: 00424 errmsg = "DOCTYPE improperly terminated\n"; 00425 break; 00426 case XML_ERR_LTSLASH_REQUIRED: 00427 errmsg = "EndTag: '</' not found\n"; 00428 break; 00429 case XML_ERR_EQUAL_REQUIRED: 00430 errmsg = "expected '='\n"; 00431 break; 00432 case XML_ERR_STRING_NOT_CLOSED: 00433 errmsg = "String not closed expecting \" or '\n"; 00434 break; 00435 case XML_ERR_STRING_NOT_STARTED: 00436 errmsg = "String not started expecting ' or \"\n"; 00437 break; 00438 case XML_ERR_ENCODING_NAME: 00439 errmsg = "Invalid XML encoding name\n"; 00440 break; 00441 case XML_ERR_STANDALONE_VALUE: 00442 errmsg = "standalone accepts only 'yes' or 'no'\n"; 00443 break; 00444 case XML_ERR_DOCUMENT_EMPTY: 00445 errmsg = "Document is empty\n"; 00446 break; 00447 case XML_ERR_DOCUMENT_END: 00448 errmsg = "Extra content at the end of the document\n"; 00449 break; 00450 case XML_ERR_NOT_WELL_BALANCED: 00451 errmsg = "chunk is not well balanced\n"; 00452 break; 00453 case XML_ERR_EXTRA_CONTENT: 00454 errmsg = "extra content at the end of well balanced chunk\n"; 00455 break; 00456 case XML_ERR_VERSION_MISSING: 00457 errmsg = "Malformed declaration expecting version\n"; 00458 break; 00459 #if 0 00460 case: 00461 errmsg = "\n"; 00462 break; 00463 #endif 00464 default: 00465 errmsg = "Unregistered error message\n"; 00466 } 00467 if (ctxt != NULL) 00468 ctxt->errNo = error; 00469 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, 00470 XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, errmsg, 00471 info); 00472 if (ctxt != NULL) { 00473 ctxt->wellFormed = 0; 00474 if (ctxt->recovery == 0) 00475 ctxt->disableSAX = 1; 00476 } 00477 } 00478 00487 static void 00488 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, 00489 const char *msg) 00490 { 00491 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00492 (ctxt->instate == XML_PARSER_EOF)) 00493 return; 00494 if (ctxt != NULL) 00495 ctxt->errNo = error; 00496 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, 00497 XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg); 00498 if (ctxt != NULL) { 00499 ctxt->wellFormed = 0; 00500 if (ctxt->recovery == 0) 00501 ctxt->disableSAX = 1; 00502 } 00503 } 00504 00515 static void 00516 xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, 00517 const char *msg, const xmlChar *str1, const xmlChar *str2) 00518 { 00519 xmlStructuredErrorFunc schannel = NULL; 00520 00521 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00522 (ctxt->instate == XML_PARSER_EOF)) 00523 return; 00524 if ((ctxt != NULL) && (ctxt->sax != NULL) && 00525 (ctxt->sax->initialized == XML_SAX2_MAGIC)) 00526 schannel = ctxt->sax->serror; 00527 if (ctxt != NULL) { 00528 __xmlRaiseError(schannel, 00529 (ctxt->sax) ? ctxt->sax->warning : NULL, 00530 ctxt->userData, 00531 ctxt, NULL, XML_FROM_PARSER, error, 00532 XML_ERR_WARNING, NULL, 0, 00533 (const char *) str1, (const char *) str2, NULL, 0, 0, 00534 msg, (const char *) str1, (const char *) str2); 00535 } else { 00536 __xmlRaiseError(schannel, NULL, NULL, 00537 ctxt, NULL, XML_FROM_PARSER, error, 00538 XML_ERR_WARNING, NULL, 0, 00539 (const char *) str1, (const char *) str2, NULL, 0, 0, 00540 msg, (const char *) str1, (const char *) str2); 00541 } 00542 } 00543 00553 static void 00554 xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error, 00555 const char *msg, const xmlChar *str1, const xmlChar *str2) 00556 { 00557 xmlStructuredErrorFunc schannel = NULL; 00558 00559 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00560 (ctxt->instate == XML_PARSER_EOF)) 00561 return; 00562 if (ctxt != NULL) { 00563 ctxt->errNo = error; 00564 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC)) 00565 schannel = ctxt->sax->serror; 00566 } 00567 if (ctxt != NULL) { 00568 __xmlRaiseError(schannel, 00569 ctxt->vctxt.error, ctxt->vctxt.userData, 00570 ctxt, NULL, XML_FROM_DTD, error, 00571 XML_ERR_ERROR, NULL, 0, (const char *) str1, 00572 (const char *) str2, NULL, 0, 0, 00573 msg, (const char *) str1, (const char *) str2); 00574 ctxt->valid = 0; 00575 } else { 00576 __xmlRaiseError(schannel, NULL, NULL, 00577 ctxt, NULL, XML_FROM_DTD, error, 00578 XML_ERR_ERROR, NULL, 0, (const char *) str1, 00579 (const char *) str2, NULL, 0, 0, 00580 msg, (const char *) str1, (const char *) str2); 00581 } 00582 } 00583 00593 static void 00594 xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error, 00595 const char *msg, int val) 00596 { 00597 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00598 (ctxt->instate == XML_PARSER_EOF)) 00599 return; 00600 if (ctxt != NULL) 00601 ctxt->errNo = error; 00602 __xmlRaiseError(NULL, NULL, NULL, 00603 ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, 00604 NULL, 0, NULL, NULL, NULL, val, 0, msg, val); 00605 if (ctxt != NULL) { 00606 ctxt->wellFormed = 0; 00607 if (ctxt->recovery == 0) 00608 ctxt->disableSAX = 1; 00609 } 00610 } 00611 00623 static void 00624 xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, 00625 const char *msg, const xmlChar *str1, int val, 00626 const xmlChar *str2) 00627 { 00628 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00629 (ctxt->instate == XML_PARSER_EOF)) 00630 return; 00631 if (ctxt != NULL) 00632 ctxt->errNo = error; 00633 __xmlRaiseError(NULL, NULL, NULL, 00634 ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, 00635 NULL, 0, (const char *) str1, (const char *) str2, 00636 NULL, val, 0, msg, str1, val, str2); 00637 if (ctxt != NULL) { 00638 ctxt->wellFormed = 0; 00639 if (ctxt->recovery == 0) 00640 ctxt->disableSAX = 1; 00641 } 00642 } 00643 00653 static void 00654 xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, 00655 const char *msg, const xmlChar * val) 00656 { 00657 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00658 (ctxt->instate == XML_PARSER_EOF)) 00659 return; 00660 if (ctxt != NULL) 00661 ctxt->errNo = error; 00662 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, 00663 XML_FROM_PARSER, error, XML_ERR_FATAL, 00664 NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg, 00665 val); 00666 if (ctxt != NULL) { 00667 ctxt->wellFormed = 0; 00668 if (ctxt->recovery == 0) 00669 ctxt->disableSAX = 1; 00670 } 00671 } 00672 00682 static void 00683 xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, 00684 const char *msg, const xmlChar * val) 00685 { 00686 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00687 (ctxt->instate == XML_PARSER_EOF)) 00688 return; 00689 if (ctxt != NULL) 00690 ctxt->errNo = error; 00691 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, 00692 XML_FROM_PARSER, error, XML_ERR_ERROR, 00693 NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg, 00694 val); 00695 } 00696 00707 static void 00708 xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, 00709 const char *msg, 00710 const xmlChar * info1, const xmlChar * info2, 00711 const xmlChar * info3) 00712 { 00713 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00714 (ctxt->instate == XML_PARSER_EOF)) 00715 return; 00716 if (ctxt != NULL) 00717 ctxt->errNo = error; 00718 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, 00719 XML_ERR_ERROR, NULL, 0, (const char *) info1, 00720 (const char *) info2, (const char *) info3, 0, 0, msg, 00721 info1, info2, info3); 00722 if (ctxt != NULL) 00723 ctxt->nsWellFormed = 0; 00724 } 00725 00736 static void 00737 xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error, 00738 const char *msg, 00739 const xmlChar * info1, const xmlChar * info2, 00740 const xmlChar * info3) 00741 { 00742 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && 00743 (ctxt->instate == XML_PARSER_EOF)) 00744 return; 00745 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, 00746 XML_ERR_WARNING, NULL, 0, (const char *) info1, 00747 (const char *) info2, (const char *) info3, 0, 0, msg, 00748 info1, info2, info3); 00749 } 00750 00751 /************************************************************************ 00752 * * 00753 * Library wide options * 00754 * * 00755 ************************************************************************/ 00756 00767 int 00768 xmlHasFeature(xmlFeature feature) 00769 { 00770 switch (feature) { 00771 case XML_WITH_THREAD: 00772 #ifdef LIBXML_THREAD_ENABLED 00773 return(1); 00774 #else 00775 return(0); 00776 #endif 00777 case XML_WITH_TREE: 00778 #ifdef LIBXML_TREE_ENABLED 00779 return(1); 00780 #else 00781 return(0); 00782 #endif 00783 case XML_WITH_OUTPUT: 00784 #ifdef LIBXML_OUTPUT_ENABLED 00785 return(1); 00786 #else 00787 return(0); 00788 #endif 00789 case XML_WITH_PUSH: 00790 #ifdef LIBXML_PUSH_ENABLED 00791 return(1); 00792 #else 00793 return(0); 00794 #endif 00795 case XML_WITH_READER: 00796 #ifdef LIBXML_READER_ENABLED 00797 return(1); 00798 #else 00799 return(0); 00800 #endif 00801 case XML_WITH_PATTERN: 00802 #ifdef LIBXML_PATTERN_ENABLED 00803 return(1); 00804 #else 00805 return(0); 00806 #endif 00807 case XML_WITH_WRITER: 00808 #ifdef LIBXML_WRITER_ENABLED 00809 return(1); 00810 #else 00811 return(0); 00812 #endif 00813 case XML_WITH_SAX1: 00814 #ifdef LIBXML_SAX1_ENABLED 00815 return(1); 00816 #else 00817 return(0); 00818 #endif 00819 case XML_WITH_FTP: 00820 #ifdef LIBXML_FTP_ENABLED 00821 return(1); 00822 #else 00823 return(0); 00824 #endif 00825 case XML_WITH_HTTP: 00826 #ifdef LIBXML_HTTP_ENABLED 00827 return(1); 00828 #else 00829 return(0); 00830 #endif 00831 case XML_WITH_VALID: 00832 #ifdef LIBXML_VALID_ENABLED 00833 return(1); 00834 #else 00835 return(0); 00836 #endif 00837 case XML_WITH_HTML: 00838 #ifdef LIBXML_HTML_ENABLED 00839 return(1); 00840 #else 00841 return(0); 00842 #endif 00843 case XML_WITH_LEGACY: 00844 #ifdef LIBXML_LEGACY_ENABLED 00845 return(1); 00846 #else 00847 return(0); 00848 #endif 00849 case XML_WITH_C14N: 00850 #ifdef LIBXML_C14N_ENABLED 00851 return(1); 00852 #else 00853 return(0); 00854 #endif 00855 case XML_WITH_CATALOG: 00856 #ifdef LIBXML_CATALOG_ENABLED 00857 return(1); 00858 #else 00859 return(0); 00860 #endif 00861 case XML_WITH_XPATH: 00862 #ifdef LIBXML_XPATH_ENABLED 00863 return(1); 00864 #else 00865 return(0); 00866 #endif 00867 case XML_WITH_XPTR: 00868 #ifdef LIBXML_XPTR_ENABLED 00869 return(1); 00870 #else 00871 return(0); 00872 #endif 00873 case XML_WITH_XINCLUDE: 00874 #ifdef LIBXML_XINCLUDE_ENABLED 00875 return(1); 00876 #else 00877 return(0); 00878 #endif 00879 case XML_WITH_ICONV: 00880 #ifdef LIBXML_ICONV_ENABLED 00881 return(1); 00882 #else 00883 return(0); 00884 #endif 00885 case XML_WITH_ISO8859X: 00886 #ifdef LIBXML_ISO8859X_ENABLED 00887 return(1); 00888 #else 00889 return(0); 00890 #endif 00891 case XML_WITH_UNICODE: 00892 #ifdef LIBXML_UNICODE_ENABLED 00893 return(1); 00894 #else 00895 return(0); 00896 #endif 00897 case XML_WITH_REGEXP: 00898 #ifdef LIBXML_REGEXP_ENABLED 00899 return(1); 00900 #else 00901 return(0); 00902 #endif 00903 case XML_WITH_AUTOMATA: 00904 #ifdef LIBXML_AUTOMATA_ENABLED 00905 return(1); 00906 #else 00907 return(0); 00908 #endif 00909 case XML_WITH_EXPR: 00910 #ifdef LIBXML_EXPR_ENABLED 00911 return(1); 00912 #else 00913 return(0); 00914 #endif 00915 case XML_WITH_SCHEMAS: 00916 #ifdef LIBXML_SCHEMAS_ENABLED 00917 return(1); 00918 #else 00919 return(0); 00920 #endif 00921 case XML_WITH_SCHEMATRON: 00922 #ifdef LIBXML_SCHEMATRON_ENABLED 00923 return(1); 00924 #else 00925 return(0); 00926 #endif 00927 case XML_WITH_MODULES: 00928 #ifdef LIBXML_MODULES_ENABLED 00929 return(1); 00930 #else 00931 return(0); 00932 #endif 00933 case XML_WITH_DEBUG: 00934 #ifdef LIBXML_DEBUG_ENABLED 00935 return(1); 00936 #else 00937 return(0); 00938 #endif 00939 case XML_WITH_DEBUG_MEM: 00940 #ifdef DEBUG_MEMORY_LOCATION 00941 return(1); 00942 #else 00943 return(0); 00944 #endif 00945 case XML_WITH_DEBUG_RUN: 00946 #ifdef LIBXML_DEBUG_RUNTIME 00947 return(1); 00948 #else 00949 return(0); 00950 #endif 00951 case XML_WITH_ZLIB: 00952 #ifdef LIBXML_ZLIB_ENABLED 00953 return(1); 00954 #else 00955 return(0); 00956 #endif 00957 case XML_WITH_ICU: 00958 #ifdef LIBXML_ICU_ENABLED 00959 return(1); 00960 #else 00961 return(0); 00962 #endif 00963 default: 00964 break; 00965 } 00966 return(0); 00967 } 00968 00969 /************************************************************************ 00970 * * 00971 * SAX2 defaulted attributes handling * 00972 * * 00973 ************************************************************************/ 00974 00981 static void 00982 xmlDetectSAX2(xmlParserCtxtPtr ctxt) { 00983 if (ctxt == NULL) return; 00984 #ifdef LIBXML_SAX1_ENABLED 00985 if ((ctxt->sax) && (ctxt->sax->initialized == XML_SAX2_MAGIC) && 00986 ((ctxt->sax->startElementNs != NULL) || 00987 (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1; 00988 #else 00989 ctxt->sax2 = 1; 00990 #endif /* LIBXML_SAX1_ENABLED */ 00991 00992 ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); 00993 ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); 00994 ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); 00995 if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) || 00996 (ctxt->str_xml_ns == NULL)) { 00997 xmlErrMemory(ctxt, NULL); 00998 } 00999 } 01000 01001 typedef struct _xmlDefAttrs xmlDefAttrs; 01002 typedef xmlDefAttrs *xmlDefAttrsPtr; 01003 struct _xmlDefAttrs { 01004 int nbAttrs; /* number of defaulted attributes on that element */ 01005 int maxAttrs; /* the size of the array */ 01006 const xmlChar *values[5]; /* array of localname/prefix/values/external */ 01007 }; 01008 01026 static xmlChar * 01027 xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst) 01028 { 01029 if ((src == NULL) || (dst == NULL)) 01030 return(NULL); 01031 01032 while (*src == 0x20) src++; 01033 while (*src != 0) { 01034 if (*src == 0x20) { 01035 while (*src == 0x20) src++; 01036 if (*src != 0) 01037 *dst++ = 0x20; 01038 } else { 01039 *dst++ = *src++; 01040 } 01041 } 01042 *dst = 0; 01043 if (dst == src) 01044 return(NULL); 01045 return(dst); 01046 } 01047 01059 static const xmlChar * 01060 xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len) 01061 { 01062 int i; 01063 int remove_head = 0; 01064 int need_realloc = 0; 01065 const xmlChar *cur; 01066 01067 if ((ctxt == NULL) || (src == NULL) || (len == NULL)) 01068 return(NULL); 01069 i = *len; 01070 if (i <= 0) 01071 return(NULL); 01072 01073 cur = src; 01074 while (*cur == 0x20) { 01075 cur++; 01076 remove_head++; 01077 } 01078 while (*cur != 0) { 01079 if (*cur == 0x20) { 01080 cur++; 01081 if ((*cur == 0x20) || (*cur == 0)) { 01082 need_realloc = 1; 01083 break; 01084 } 01085 } else 01086 cur++; 01087 } 01088 if (need_realloc) { 01089 xmlChar *ret; 01090 01091 ret = xmlStrndup(src + remove_head, i - remove_head + 1); 01092 if (ret == NULL) { 01093 xmlErrMemory(ctxt, NULL); 01094 return(NULL); 01095 } 01096 xmlAttrNormalizeSpace(ret, ret); 01097 *len = (int) strlen((const char *)ret); 01098 return(ret); 01099 } else if (remove_head) { 01100 *len -= remove_head; 01101 memmove(src, src + remove_head, 1 + *len); 01102 return(src); 01103 } 01104 return(NULL); 01105 } 01106 01116 static void 01117 xmlAddDefAttrs(xmlParserCtxtPtr ctxt, 01118 const xmlChar *fullname, 01119 const xmlChar *fullattr, 01120 const xmlChar *value) { 01121 xmlDefAttrsPtr defaults; 01122 int len; 01123 const xmlChar *name; 01124 const xmlChar *prefix; 01125 01126 /* 01127 * Allows to detect attribute redefinitions 01128 */ 01129 if (ctxt->attsSpecial != NULL) { 01130 if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL) 01131 return; 01132 } 01133 01134 if (ctxt->attsDefault == NULL) { 01135 ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict); 01136 if (ctxt->attsDefault == NULL) 01137 goto mem_error; 01138 } 01139 01140 /* 01141 * split the element name into prefix:localname , the string found 01142 * are within the DTD and then not associated to namespace names. 01143 */ 01144 name = xmlSplitQName3(fullname, &len); 01145 if (name == NULL) { 01146 name = xmlDictLookup(ctxt->dict, fullname, -1); 01147 prefix = NULL; 01148 } else { 01149 name = xmlDictLookup(ctxt->dict, name, -1); 01150 prefix = xmlDictLookup(ctxt->dict, fullname, len); 01151 } 01152 01153 /* 01154 * make sure there is some storage 01155 */ 01156 defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix); 01157 if (defaults == NULL) { 01158 defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) + 01159 (4 * 5) * sizeof(const xmlChar *)); 01160 if (defaults == NULL) 01161 goto mem_error; 01162 defaults->nbAttrs = 0; 01163 defaults->maxAttrs = 4; 01164 if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, 01165 defaults, NULL) < 0) { 01166 xmlFree(defaults); 01167 goto mem_error; 01168 } 01169 } else if (defaults->nbAttrs >= defaults->maxAttrs) { 01170 xmlDefAttrsPtr temp; 01171 01172 temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) + 01173 (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *)); 01174 if (temp == NULL) 01175 goto mem_error; 01176 defaults = temp; 01177 defaults->maxAttrs *= 2; 01178 if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, 01179 defaults, NULL) < 0) { 01180 xmlFree(defaults); 01181 goto mem_error; 01182 } 01183 } 01184 01185 /* 01186 * Split the element name into prefix:localname , the string found 01187 * are within the DTD and hen not associated to namespace names. 01188 */ 01189 name = xmlSplitQName3(fullattr, &len); 01190 if (name == NULL) { 01191 name = xmlDictLookup(ctxt->dict, fullattr, -1); 01192 prefix = NULL; 01193 } else { 01194 name = xmlDictLookup(ctxt->dict, name, -1); 01195 prefix = xmlDictLookup(ctxt->dict, fullattr, len); 01196 } 01197 01198 defaults->values[5 * defaults->nbAttrs] = name; 01199 defaults->values[5 * defaults->nbAttrs + 1] = prefix; 01200 /* intern the string and precompute the end */ 01201 len = xmlStrlen(value); 01202 value = xmlDictLookup(ctxt->dict, value, len); 01203 defaults->values[5 * defaults->nbAttrs + 2] = value; 01204 defaults->values[5 * defaults->nbAttrs + 3] = value + len; 01205 if (ctxt->external) 01206 defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external"; 01207 else 01208 defaults->values[5 * defaults->nbAttrs + 4] = NULL; 01209 defaults->nbAttrs++; 01210 01211 return; 01212 01213 mem_error: 01214 xmlErrMemory(ctxt, NULL); 01215 return; 01216 } 01217 01227 static void 01228 xmlAddSpecialAttr(xmlParserCtxtPtr ctxt, 01229 const xmlChar *fullname, 01230 const xmlChar *fullattr, 01231 int type) 01232 { 01233 if (ctxt->attsSpecial == NULL) { 01234 ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict); 01235 if (ctxt->attsSpecial == NULL) 01236 goto mem_error; 01237 } 01238 01239 if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL) 01240 return; 01241 01242 xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr, 01243 (void *) (long) type); 01244 return; 01245 01246 mem_error: 01247 xmlErrMemory(ctxt, NULL); 01248 return; 01249 } 01250 01256 static void 01257 xmlCleanSpecialAttrCallback(void *payload, void *data, 01258 const xmlChar *fullname, const xmlChar *fullattr, 01259 const xmlChar *unused ATTRIBUTE_UNUSED) { 01260 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data; 01261 01262 if (((long) payload) == XML_ATTRIBUTE_CDATA) { 01263 xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL); 01264 } 01265 } 01266 01275 static void 01276 xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt) 01277 { 01278 if (ctxt->attsSpecial == NULL) 01279 return; 01280 01281 xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt); 01282 01283 if (xmlHashSize(ctxt->attsSpecial) == 0) { 01284 xmlHashFree(ctxt->attsSpecial, NULL); 01285 ctxt->attsSpecial = NULL; 01286 } 01287 return; 01288 } 01289 01348 int 01349 xmlCheckLanguageID(const xmlChar * lang) 01350 { 01351 const xmlChar *cur = lang, *nxt; 01352 01353 if (cur == NULL) 01354 return (0); 01355 if (((cur[0] == 'i') && (cur[1] == '-')) || 01356 ((cur[0] == 'I') && (cur[1] == '-')) || 01357 ((cur[0] == 'x') && (cur[1] == '-')) || 01358 ((cur[0] == 'X') && (cur[1] == '-'))) { 01359 /* 01360 * Still allow IANA code and user code which were coming 01361 * from the previous version of the XML-1.0 specification 01362 * it's deprecated but we should not fail 01363 */ 01364 cur += 2; 01365 while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || 01366 ((cur[0] >= 'a') && (cur[0] <= 'z'))) 01367 cur++; 01368 return(cur[0] == 0); 01369 } 01370 nxt = cur; 01371 while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) || 01372 ((nxt[0] >= 'a') && (nxt[0] <= 'z'))) 01373 nxt++; 01374 if (nxt - cur >= 4) { 01375 /* 01376 * Reserved 01377 */ 01378 if ((nxt - cur > 8) || (nxt[0] != 0)) 01379 return(0); 01380 return(1); 01381 } 01382 if (nxt - cur < 2) 01383 return(0); 01384 /* we got an ISO 639 code */ 01385 if (nxt[0] == 0) 01386 return(1); 01387 if (nxt[0] != '-') 01388 return(0); 01389 01390 nxt++; 01391 cur = nxt; 01392 /* now we can have extlang or script or region or variant */ 01393 if ((nxt[0] >= '0') && (nxt[0] <= '9')) 01394 goto region_m49; 01395 01396 while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) || 01397 ((nxt[0] >= 'a') && (nxt[0] <= 'z'))) 01398 nxt++; 01399 if (nxt - cur == 4) 01400 goto script; 01401 if (nxt - cur == 2) 01402 goto region; 01403 if ((nxt - cur >= 5) && (nxt - cur <= 8)) 01404 goto variant; 01405 if (nxt - cur != 3) 01406 return(0); 01407 /* we parsed an extlang */ 01408 if (nxt[0] == 0) 01409 return(1); 01410 if (nxt[0] != '-') 01411 return(0); 01412 01413 nxt++; 01414 cur = nxt; 01415 /* now we can have script or region or variant */ 01416 if ((nxt[0] >= '0') && (nxt[0] <= '9')) 01417 goto region_m49; 01418 01419 while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) || 01420 ((nxt[0] >= 'a') && (nxt[0] <= 'z'))) 01421 nxt++; 01422 if (nxt - cur == 2) 01423 goto region; 01424 if ((nxt - cur >= 5) && (nxt - cur <= 8)) 01425 goto variant; 01426 if (nxt - cur != 4) 01427 return(0); 01428 /* we parsed a script */ 01429 script: 01430 if (nxt[0] == 0) 01431 return(1); 01432 if (nxt[0] != '-') 01433 return(0); 01434 01435 nxt++; 01436 cur = nxt; 01437 /* now we can have region or variant */ 01438 if ((nxt[0] >= '0') && (nxt[0] <= '9')) 01439 goto region_m49; 01440 01441 while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) || 01442 ((nxt[0] >= 'a') && (nxt[0] <= 'z'))) 01443 nxt++; 01444 01445 if ((nxt - cur >= 5) && (nxt - cur <= 8)) 01446 goto variant; 01447 if (nxt - cur != 2) 01448 return(0); 01449 /* we parsed a region */ 01450 region: 01451 if (nxt[0] == 0) 01452 return(1); 01453 if (nxt[0] != '-') 01454 return(0); 01455 01456 nxt++; 01457 cur = nxt; 01458 /* now we can just have a variant */ 01459 while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) || 01460 ((nxt[0] >= 'a') && (nxt[0] <= 'z'))) 01461 nxt++; 01462 01463 if ((nxt - cur < 5) || (nxt - cur > 8)) 01464 return(0); 01465 01466 /* we parsed a variant */ 01467 variant: 01468 if (nxt[0] == 0) 01469 return(1); 01470 if (nxt[0] != '-') 01471 return(0); 01472 /* extensions and private use subtags not checked */ 01473 return (1); 01474 01475 region_m49: 01476 if (((nxt[1] >= '0') && (nxt[1] <= '9')) && 01477 ((nxt[2] >= '0') && (nxt[2] <= '9'))) { 01478 nxt += 3; 01479 goto region; 01480 } 01481 return(0); 01482 } 01483 01484 /************************************************************************ 01485 * * 01486 * Parser stacks related functions and macros * 01487 * * 01488 ************************************************************************/ 01489 01490 static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, 01491 const xmlChar ** str); 01492 01493 #ifdef SAX2 01494 01505 static int 01506 nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL) 01507 { 01508 if (ctxt->options & XML_PARSE_NSCLEAN) { 01509 int i; 01510 for (i = 0;i < ctxt->nsNr;i += 2) { 01511 if (ctxt->nsTab[i] == prefix) { 01512 /* in scope */ 01513 if (ctxt->nsTab[i + 1] == URL) 01514 return(-2); 01515 /* out of scope keep it */ 01516 break; 01517 } 01518 } 01519 } 01520 if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) { 01521 ctxt->nsMax = 10; 01522 ctxt->nsNr = 0; 01523 ctxt->nsTab = (const xmlChar **) 01524 xmlMalloc(ctxt->nsMax * sizeof(xmlChar *)); 01525 if (ctxt->nsTab == NULL) { 01526 xmlErrMemory(ctxt, NULL); 01527 ctxt->nsMax = 0; 01528 return (-1); 01529 } 01530 } else if (ctxt->nsNr >= ctxt->nsMax) { 01531 const xmlChar ** tmp; 01532 ctxt->nsMax *= 2; 01533 tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab, 01534 ctxt->nsMax * sizeof(ctxt->nsTab[0])); 01535 if (tmp == NULL) { 01536 xmlErrMemory(ctxt, NULL); 01537 ctxt->nsMax /= 2; 01538 return (-1); 01539 } 01540 ctxt->nsTab = tmp; 01541 } 01542 ctxt->nsTab[ctxt->nsNr++] = prefix; 01543 ctxt->nsTab[ctxt->nsNr++] = URL; 01544 return (ctxt->nsNr); 01545 } 01555 static int 01556 nsPop(xmlParserCtxtPtr ctxt, int nr) 01557 { 01558 int i; 01559 01560 if (ctxt->nsTab == NULL) return(0); 01561 if (ctxt->nsNr < nr) { 01562 xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr); 01563 nr = ctxt->nsNr; 01564 } 01565 if (ctxt->nsNr <= 0) 01566 return (0); 01567 01568 for (i = 0;i < nr;i++) { 01569 ctxt->nsNr--; 01570 ctxt->nsTab[ctxt->nsNr] = NULL; 01571 } 01572 return(nr); 01573 } 01574 #endif 01575 01576 static int 01577 xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) { 01578 const xmlChar **atts; 01579 int *attallocs; 01580 int maxatts; 01581 01582 if (ctxt->atts == NULL) { 01583 maxatts = 55; /* allow for 10 attrs by default */ 01584 atts = (const xmlChar **) 01585 xmlMalloc(maxatts * sizeof(xmlChar *)); 01586 if (atts == NULL) goto mem_error; 01587 ctxt->atts = atts; 01588 attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int)); 01589 if (attallocs == NULL) goto mem_error; 01590 ctxt->attallocs = attallocs; 01591 ctxt->maxatts = maxatts; 01592 } else if (nr + 5 > ctxt->maxatts) { 01593 maxatts = (nr + 5) * 2; 01594 atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts, 01595 maxatts * sizeof(const xmlChar *)); 01596 if (atts == NULL) goto mem_error; 01597 ctxt->atts = atts; 01598 attallocs = (int *) xmlRealloc((void *) ctxt->attallocs, 01599 (maxatts / 5) * sizeof(int)); 01600 if (attallocs == NULL) goto mem_error; 01601 ctxt->attallocs = attallocs; 01602 ctxt->maxatts = maxatts; 01603 } 01604 return(ctxt->maxatts); 01605 mem_error: 01606 xmlErrMemory(ctxt, NULL); 01607 return(-1); 01608 } 01609 01619 int 01620 inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value) 01621 { 01622 if ((ctxt == NULL) || (value == NULL)) 01623 return(-1); 01624 if (ctxt->inputNr >= ctxt->inputMax) { 01625 ctxt->inputMax *= 2; 01626 ctxt->inputTab = 01627 (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab, 01628 ctxt->inputMax * 01629 sizeof(ctxt->inputTab[0])); 01630 if (ctxt->inputTab == NULL) { 01631 xmlErrMemory(ctxt, NULL); 01632 xmlFreeInputStream(value); 01633 ctxt->inputMax /= 2; 01634 value = NULL; 01635 return (-1); 01636 } 01637 } 01638 ctxt->inputTab[ctxt->inputNr] = value; 01639 ctxt->input = value; 01640 return (ctxt->inputNr++); 01641 } 01650 xmlParserInputPtr 01651 inputPop(xmlParserCtxtPtr ctxt) 01652 { 01653 xmlParserInputPtr ret; 01654 01655 if (ctxt == NULL) 01656 return(NULL); 01657 if (ctxt->inputNr <= 0) 01658 return (NULL); 01659 ctxt->inputNr--; 01660 if (ctxt->inputNr > 0) 01661 ctxt->input = ctxt->inputTab[ctxt->inputNr - 1]; 01662 else 01663 ctxt->input = NULL; 01664 ret = ctxt->inputTab[ctxt->inputNr]; 01665 ctxt->inputTab[ctxt->inputNr] = NULL; 01666 return (ret); 01667 } 01677 int 01678 nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value) 01679 { 01680 if (ctxt == NULL) return(0); 01681 if (ctxt->nodeNr >= ctxt->nodeMax) { 01682 xmlNodePtr *tmp; 01683 01684 tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab, 01685 ctxt->nodeMax * 2 * 01686 sizeof(ctxt->nodeTab[0])); 01687 if (tmp == NULL) { 01688 xmlErrMemory(ctxt, NULL); 01689 return (-1); 01690 } 01691 ctxt->nodeTab = tmp; 01692 ctxt->nodeMax *= 2; 01693 } 01694 if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) && 01695 ((ctxt->options & XML_PARSE_HUGE) == 0)) { 01696 xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR, 01697 "Excessive depth in document: %d use XML_PARSE_HUGE option\n", 01698 xmlParserMaxDepth); 01699 ctxt->instate = XML_PARSER_EOF; 01700 return(-1); 01701 } 01702 ctxt->nodeTab[ctxt->nodeNr] = value; 01703 ctxt->node = value; 01704 return (ctxt->nodeNr++); 01705 } 01706 01715 xmlNodePtr 01716 nodePop(xmlParserCtxtPtr ctxt) 01717 { 01718 xmlNodePtr ret; 01719 01720 if (ctxt == NULL) return(NULL); 01721 if (ctxt->nodeNr <= 0) 01722 return (NULL); 01723 ctxt->nodeNr--; 01724 if (ctxt->nodeNr > 0) 01725 ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1]; 01726 else 01727 ctxt->node = NULL; 01728 ret = ctxt->nodeTab[ctxt->nodeNr]; 01729 ctxt->nodeTab[ctxt->nodeNr] = NULL; 01730 return (ret); 01731 } 01732 01733 #ifdef LIBXML_PUSH_ENABLED 01734 01745 static int 01746 nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value, 01747 const xmlChar *prefix, const xmlChar *URI, int nsNr) 01748 { 01749 if (ctxt->nameNr >= ctxt->nameMax) { 01750 const xmlChar * *tmp; 01751 void **tmp2; 01752 ctxt->nameMax *= 2; 01753 tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab, 01754 ctxt->nameMax * 01755 sizeof(ctxt->nameTab[0])); 01756 if (tmp == NULL) { 01757 ctxt->nameMax /= 2; 01758 goto mem_error; 01759 } 01760 ctxt->nameTab = tmp; 01761 tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab, 01762 ctxt->nameMax * 3 * 01763 sizeof(ctxt->pushTab[0])); 01764 if (tmp2 == NULL) { 01765 ctxt->nameMax /= 2; 01766 goto mem_error; 01767 } 01768 ctxt->pushTab = tmp2; 01769 } 01770 ctxt->nameTab[ctxt->nameNr] = value; 01771 ctxt->name = value; 01772 ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix; 01773 ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI; 01774 ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr; 01775 return (ctxt->nameNr++); 01776 mem_error: 01777 xmlErrMemory(ctxt, NULL); 01778 return (-1); 01779 } 01788 static const xmlChar * 01789 nameNsPop(xmlParserCtxtPtr ctxt) 01790 { 01791 const xmlChar *ret; 01792 01793 if (ctxt->nameNr <= 0) 01794 return (NULL); 01795 ctxt->nameNr--; 01796 if (ctxt->nameNr > 0) 01797 ctxt->name = ctxt->nameTab[ctxt->nameNr - 1]; 01798 else 01799 ctxt->name = NULL; 01800 ret = ctxt->nameTab[ctxt->nameNr]; 01801 ctxt->nameTab[ctxt->nameNr] = NULL; 01802 return (ret); 01803 } 01804 #endif /* LIBXML_PUSH_ENABLED */ 01805 01815 int 01816 namePush(xmlParserCtxtPtr ctxt, const xmlChar * value) 01817 { 01818 if (ctxt == NULL) return (-1); 01819 01820 if (ctxt->nameNr >= ctxt->nameMax) { 01821 const xmlChar * *tmp; 01822 ctxt->nameMax *= 2; 01823 tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab, 01824 ctxt->nameMax * 01825 sizeof(ctxt->nameTab[0])); 01826 if (tmp == NULL) { 01827 ctxt->nameMax /= 2; 01828 goto mem_error; 01829 } 01830 ctxt->nameTab = tmp; 01831 } 01832 ctxt->nameTab[ctxt->nameNr] = value; 01833 ctxt->name = value; 01834 return (ctxt->nameNr++); 01835 mem_error: 01836 xmlErrMemory(ctxt, NULL); 01837 return (-1); 01838 } 01847 const xmlChar * 01848 namePop(xmlParserCtxtPtr ctxt) 01849 { 01850 const xmlChar *ret; 01851 01852 if ((ctxt == NULL) || (ctxt->nameNr <= 0)) 01853 return (NULL); 01854 ctxt->nameNr--; 01855 if (ctxt->nameNr > 0) 01856 ctxt->name = ctxt->nameTab[ctxt->nameNr - 1]; 01857 else 01858 ctxt->name = NULL; 01859 ret = ctxt->nameTab[ctxt->nameNr]; 01860 ctxt->nameTab[ctxt->nameNr] = NULL; 01861 return (ret); 01862 } 01863 01864 static int spacePush(xmlParserCtxtPtr ctxt, int val) { 01865 if (ctxt->spaceNr >= ctxt->spaceMax) { 01866 int *tmp; 01867 01868 ctxt->spaceMax *= 2; 01869 tmp = (int *) xmlRealloc(ctxt->spaceTab, 01870 ctxt->spaceMax * sizeof(ctxt->spaceTab[0])); 01871 if (tmp == NULL) { 01872 xmlErrMemory(ctxt, NULL); 01873 ctxt->spaceMax /=2; 01874 return(-1); 01875 } 01876 ctxt->spaceTab = tmp; 01877 } 01878 ctxt->spaceTab[ctxt->spaceNr] = val; 01879 ctxt->space = &ctxt->spaceTab[ctxt->spaceNr]; 01880 return(ctxt->spaceNr++); 01881 } 01882 01883 static int spacePop(xmlParserCtxtPtr ctxt) { 01884 int ret; 01885 if (ctxt->spaceNr <= 0) return(0); 01886 ctxt->spaceNr--; 01887 if (ctxt->spaceNr > 0) 01888 ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1]; 01889 else 01890 ctxt->space = &ctxt->spaceTab[0]; 01891 ret = ctxt->spaceTab[ctxt->spaceNr]; 01892 ctxt->spaceTab[ctxt->spaceNr] = -1; 01893 return(ret); 01894 } 01895 01896 /* 01897 * Macros for accessing the content. Those should be used only by the parser, 01898 * and not exported. 01899 * 01900 * Dirty macros, i.e. one often need to make assumption on the context to 01901 * use them 01902 * 01903 * CUR_PTR return the current pointer to the xmlChar to be parsed. 01904 * To be used with extreme caution since operations consuming 01905 * characters may move the input buffer to a different location ! 01906 * CUR returns the current xmlChar value, i.e. a 8 bit value if compiled 01907 * This should be used internally by the parser 01908 * only to compare to ASCII values otherwise it would break when 01909 * running with UTF-8 encoding. 01910 * RAW same as CUR but in the input buffer, bypass any token 01911 * extraction that may have been done 01912 * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only 01913 * to compare on ASCII based substring. 01914 * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined 01915 * strings without newlines within the parser. 01916 * NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII 01917 * defined char within the parser. 01918 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding 01919 * 01920 * NEXT Skip to the next character, this does the proper decoding 01921 * in UTF-8 mode. It also pop-up unfinished entities on the fly. 01922 * NEXTL(l) Skip the current unicode character of l xmlChars long. 01923 * CUR_CHAR(l) returns the current unicode character (int), set l 01924 * to the number of xmlChars used for the encoding [0-5]. 01925 * CUR_SCHAR same but operate on a string instead of the context 01926 * COPY_BUF copy the current unicode char to the target buffer, increment 01927 * the index 01928 * GROW, SHRINK handling of input buffers 01929 */ 01930 01931 #define RAW (*ctxt->input->cur) 01932 #define CUR (*ctxt->input->cur) 01933 #define NXT(val) ctxt->input->cur[(val)] 01934 #define CUR_PTR ctxt->input->cur 01935 01936 #define CMP4( s, c1, c2, c3, c4 ) \ 01937 ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \ 01938 ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 ) 01939 #define CMP5( s, c1, c2, c3, c4, c5 ) \ 01940 ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 ) 01941 #define CMP6( s, c1, c2, c3, c4, c5, c6 ) \ 01942 ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 ) 01943 #define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \ 01944 ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 ) 01945 #define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \ 01946 ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 ) 01947 #define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \ 01948 ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \ 01949 ((unsigned char *) s)[ 8 ] == c9 ) 01950 #define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \ 01951 ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \ 01952 ((unsigned char *) s)[ 9 ] == c10 ) 01953 01954 #define SKIP(val) do { \ 01955 ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val); \ 01956 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ 01957 if ((*ctxt->input->cur == 0) && \ 01958 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \ 01959 xmlPopInput(ctxt); \ 01960 } while (0) 01961 01962 #define SKIPL(val) do { \ 01963 int skipl; \ 01964 for(skipl=0; skipl<val; skipl++) { \ 01965 if (*(ctxt->input->cur) == '\n') { \ 01966 ctxt->input->line++; ctxt->input->col = 1; \ 01967 } else ctxt->input->col++; \ 01968 ctxt->nbChars++; \ 01969 ctxt->input->cur++; \ 01970 } \ 01971 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ 01972 if ((*ctxt->input->cur == 0) && \ 01973 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \ 01974 xmlPopInput(ctxt); \ 01975 } while (0) 01976 01977 #define SHRINK if ((ctxt->progressive == 0) && \ 01978 (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \ 01979 (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \ 01980 xmlSHRINK (ctxt); 01981 01982 static void xmlSHRINK (xmlParserCtxtPtr ctxt) { 01983 xmlParserInputShrink(ctxt->input); 01984 if ((*ctxt->input->cur == 0) && 01985 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) 01986 xmlPopInput(ctxt); 01987 } 01988 01989 #define GROW if ((ctxt->progressive == 0) && \ 01990 (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \ 01991 xmlGROW (ctxt); 01992 01993 static void xmlGROW (xmlParserCtxtPtr ctxt) { 01994 xmlParserInputGrow(ctxt->input, INPUT_CHUNK); 01995 if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) && 01996 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) 01997 xmlPopInput(ctxt); 01998 } 01999 02000 #define SKIP_BLANKS xmlSkipBlankChars(ctxt) 02001 02002 #define NEXT xmlNextChar(ctxt) 02003 02004 #define NEXT1 { \ 02005 ctxt->input->col++; \ 02006 ctxt->input->cur++; \ 02007 ctxt->nbChars++; \ 02008 if (*ctxt->input->cur == 0) \ 02009 xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \ 02010 } 02011 02012 #define NEXTL(l) do { \ 02013 if (*(ctxt->input->cur) == '\n') { \ 02014 ctxt->input->line++; ctxt->input->col = 1; \ 02015 } else ctxt->input->col++; \ 02016 ctxt->input->cur += l; \ 02017 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ 02018 } while (0) 02019 02020 #define CUR_CHAR(l) xmlCurrentChar(ctxt, &l) 02021 #define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l) 02022 02023 #define COPY_BUF(l,b,i,v) \ 02024 if (l == 1) b[i++] = (xmlChar) v; \ 02025 else i += xmlCopyCharMultiByte(&b[i],v) 02026 02037 int 02038 xmlSkipBlankChars(xmlParserCtxtPtr ctxt) { 02039 int res = 0; 02040 02041 /* 02042 * It's Okay to use CUR/NEXT here since all the blanks are on 02043 * the ASCII range. 02044 */ 02045 if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) { 02046 const xmlChar *cur; 02047 /* 02048 * if we are in the document content, go really fast 02049 */ 02050 cur = ctxt->input->cur; 02051 while (IS_BLANK_CH(*cur)) { 02052 if (*cur == '\n') { 02053 ctxt->input->line++; ctxt->input->col = 1; 02054 } 02055 cur++; 02056 res++; 02057 if (*cur == 0) { 02058 ctxt->input->cur = cur; 02059 xmlParserInputGrow(ctxt->input, INPUT_CHUNK); 02060 cur = ctxt->input->cur; 02061 } 02062 } 02063 ctxt->input->cur = cur; 02064 } else { 02065 int cur; 02066 do { 02067 cur = CUR; 02068 while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */ 02069 NEXT; 02070 cur = CUR; 02071 res++; 02072 } 02073 while ((cur == 0) && (ctxt->inputNr > 1) && 02074 (ctxt->instate != XML_PARSER_COMMENT)) { 02075 xmlPopInput(ctxt); 02076 cur = CUR; 02077 } 02078 /* 02079 * Need to handle support of entities branching here 02080 */ 02081 if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); 02082 } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */ 02083 } 02084 return(res); 02085 } 02086 02087 /************************************************************************ 02088 * * 02089 * Commodity functions to handle entities * 02090 * * 02091 ************************************************************************/ 02092 02102 xmlChar 02103 xmlPopInput(xmlParserCtxtPtr ctxt) { 02104 if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0); 02105 if (xmlParserDebugEntities) 02106 xmlGenericError(xmlGenericErrorContext, 02107 "Popping input %d\n", ctxt->inputNr); 02108 xmlFreeInputStream(inputPop(ctxt)); 02109 if ((*ctxt->input->cur == 0) && 02110 (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) 02111 return(xmlPopInput(ctxt)); 02112 return(CUR); 02113 } 02114 02124 int 02125 xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) { 02126 int ret; 02127 if (input == NULL) return(-1); 02128 02129 if (xmlParserDebugEntities) { 02130 if ((ctxt->input != NULL) && (ctxt->input->filename)) 02131 xmlGenericError(xmlGenericErrorContext, 02132 "%s(%d): ", ctxt->input->filename, 02133 ctxt->input->line); 02134 xmlGenericError(xmlGenericErrorContext, 02135 "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur); 02136 } 02137 ret = inputPush(ctxt, input); 02138 GROW; 02139 return(ret); 02140 } 02141 02157 int 02158 xmlParseCharRef(xmlParserCtxtPtr ctxt) { 02159 unsigned int val = 0; 02160 int count = 0; 02161 unsigned int outofrange = 0; 02162 02163 /* 02164 * Using RAW/CUR/NEXT is okay since we are working on ASCII range here 02165 */ 02166 if ((RAW == '&') && (NXT(1) == '#') && 02167 (NXT(2) == 'x')) { 02168 SKIP(3); 02169 GROW; 02170 while (RAW != ';') { /* loop blocked by count */ 02171 if (count++ > 20) { 02172 count = 0; 02173 GROW; 02174 } 02175 if ((RAW >= '0') && (RAW <= '9')) 02176 val = val * 16 + (CUR - '0'); 02177 else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20)) 02178 val = val * 16 + (CUR - 'a') + 10; 02179 else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20)) 02180 val = val * 16 + (CUR - 'A') + 10; 02181 else { 02182 xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL); 02183 val = 0; 02184 break; 02185 } 02186 if (val > 0x10FFFF) 02187 outofrange = val; 02188 02189 NEXT; 02190 count++; 02191 } 02192 if (RAW == ';') { 02193 /* on purpose to avoid reentrancy problems with NEXT and SKIP */ 02194 ctxt->input->col++; 02195 ctxt->nbChars ++; 02196 ctxt->input->cur++; 02197 } 02198 } else if ((RAW == '&') && (NXT(1) == '#')) { 02199 SKIP(2); 02200 GROW; 02201 while (RAW != ';') { /* loop blocked by count */ 02202 if (count++ > 20) { 02203 count = 0; 02204 GROW; 02205 } 02206 if ((RAW >= '0') && (RAW <= '9')) 02207 val = val * 10 + (CUR - '0'); 02208 else { 02209 xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL); 02210 val = 0; 02211 break; 02212 } 02213 if (val > 0x10FFFF) 02214 outofrange = val; 02215 02216 NEXT; 02217 count++; 02218 } 02219 if (RAW == ';') { 02220 /* on purpose to avoid reentrancy problems with NEXT and SKIP */ 02221 ctxt->input->col++; 02222 ctxt->nbChars ++; 02223 ctxt->input->cur++; 02224 } 02225 } else { 02226 xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL); 02227 } 02228 02229 /* 02230 * [ WFC: Legal Character ] 02231 * Characters referred to using character references must match the 02232 * production for Char. 02233 */ 02234 if ((IS_CHAR(val) && (outofrange == 0))) { 02235 return(val); 02236 } else { 02237 xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, 02238 "xmlParseCharRef: invalid xmlChar value %d\n", 02239 val); 02240 } 02241 return(0); 02242 } 02243 02262 static int 02263 xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) { 02264 const xmlChar *ptr; 02265 xmlChar cur; 02266 unsigned int val = 0; 02267 unsigned int outofrange = 0; 02268 02269 if ((str == NULL) || (*str == NULL)) return(0); 02270 ptr = *str; 02271 cur = *ptr; 02272 if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) { 02273 ptr += 3; 02274 cur = *ptr; 02275 while (cur != ';') { /* Non input consuming loop */ 02276 if ((cur >= '0') && (cur <= '9')) 02277 val = val * 16 + (cur - '0'); 02278 else if ((cur >= 'a') && (cur <= 'f')) 02279 val = val * 16 + (cur - 'a') + 10; 02280 else if ((cur >= 'A') && (cur <= 'F')) 02281 val = val * 16 + (cur - 'A') + 10; 02282 else { 02283 xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL); 02284 val = 0; 02285 break; 02286 } 02287 if (val > 0x10FFFF) 02288 outofrange = val; 02289 02290 ptr++; 02291 cur = *ptr; 02292 } 02293 if (cur == ';') 02294 ptr++; 02295 } else if ((cur == '&') && (ptr[1] == '#')){ 02296 ptr += 2; 02297 cur = *ptr; 02298 while (cur != ';') { /* Non input consuming loops */ 02299 if ((cur >= '0') && (cur <= '9')) 02300 val = val * 10 + (cur - '0'); 02301 else { 02302 xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL); 02303 val = 0; 02304 break; 02305 } 02306 if (val > 0x10FFFF) 02307 outofrange = val; 02308 02309 ptr++; 02310 cur = *ptr; 02311 } 02312 if (cur == ';') 02313 ptr++; 02314 } else { 02315 xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL); 02316 return(0); 02317 } 02318 *str = ptr; 02319 02320 /* 02321 * [ WFC: Legal Character ] 02322 * Characters referred to using character references must match the 02323 * production for Char. 02324 */ 02325 if ((IS_CHAR(val) && (outofrange == 0))) { 02326 return(val); 02327 } else { 02328 xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, 02329 "xmlParseStringCharRef: invalid xmlChar value %d\n", 02330 val); 02331 } 02332 return(0); 02333 } 02334 02346 static void deallocblankswrapper (xmlChar *str) {xmlFree(str);} 02347 02348 static xmlParserInputPtr 02349 xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) { 02350 xmlParserInputPtr input; 02351 xmlChar *buffer; 02352 size_t length; 02353 if (entity == NULL) { 02354 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, 02355 "xmlNewBlanksWrapperInputStream entity\n"); 02356 return(NULL); 02357 } 02358 if (xmlParserDebugEntities) 02359 xmlGenericError(xmlGenericErrorContext, 02360 "new blanks wrapper for entity: %s\n", entity->name); 02361 input = xmlNewInputStream(ctxt); 02362 if (input == NULL) { 02363 return(NULL); 02364 } 02365 length = xmlStrlen(entity->name) + 5; 02366 buffer = xmlMallocAtomic(length); 02367 if (buffer == NULL) { 02368 xmlErrMemory(ctxt, NULL); 02369 xmlFree(input); 02370 return(NULL); 02371 } 02372 buffer [0] = ' '; 02373 buffer [1] = '%'; 02374 buffer [length-3] = ';'; 02375 buffer [length-2] = ' '; 02376 buffer [length-1] = 0; 02377 memcpy(buffer + 2, entity->name, length - 5); 02378 input->free = deallocblankswrapper; 02379 input->base = buffer; 02380 input->cur = buffer; 02381 input->length = length; 02382 input->end = &buffer[length]; 02383 return(input); 02384 } 02385 02418 void 02419 xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) { 02420 const xmlChar *name; 02421 xmlEntityPtr entity = NULL; 02422 xmlParserInputPtr input; 02423 02424 if (RAW != '%') return; 02425 switch(ctxt->instate) { 02426 case XML_PARSER_CDATA_SECTION: 02427 return; 02428 case XML_PARSER_COMMENT: 02429 return; 02430 case XML_PARSER_START_TAG: 02431 return; 02432 case XML_PARSER_END_TAG: 02433 return; 02434 case XML_PARSER_EOF: 02435 xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL); 02436 return; 02437 case XML_PARSER_PROLOG: 02438 case XML_PARSER_START: 02439 case XML_PARSER_MISC: 02440 xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL); 02441 return; 02442 case XML_PARSER_ENTITY_DECL: 02443 case XML_PARSER_CONTENT: 02444 case XML_PARSER_ATTRIBUTE_VALUE: 02445 case XML_PARSER_PI: 02446 case XML_PARSER_SYSTEM_LITERAL: 02447 case XML_PARSER_PUBLIC_LITERAL: 02448 /* we just ignore it there */ 02449 return; 02450 case XML_PARSER_EPILOG: 02451 xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL); 02452 return; 02453 case XML_PARSER_ENTITY_VALUE: 02454 /* 02455 * NOTE: in the case of entity values, we don't do the 02456 * substitution here since we need the literal 02457 * entity value to be able to save the internal 02458 * subset of the document. 02459 * This will be handled by xmlStringDecodeEntities 02460 */ 02461 return; 02462 case XML_PARSER_DTD: 02463 /* 02464 * [WFC: Well-Formedness Constraint: PEs in Internal Subset] 02465 * In the internal DTD subset, parameter-entity references 02466 * can occur only where markup declarations can occur, not 02467 * within markup declarations. 02468 * In that case this is handled in xmlParseMarkupDecl 02469 */ 02470 if ((ctxt->external == 0) && (ctxt->inputNr == 1)) 02471 return; 02472 if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0) 02473 return; 02474 break; 02475 case XML_PARSER_IGNORE: 02476 return; 02477 } 02478 02479 NEXT; 02480 name = xmlParseName(ctxt); 02481 if (xmlParserDebugEntities) 02482 xmlGenericError(xmlGenericErrorContext, 02483 "PEReference: %s\n", name); 02484 if (name == NULL) { 02485 xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL); 02486 } else { 02487 if (RAW == ';') { 02488 NEXT; 02489 if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL)) 02490 entity = ctxt->sax->getParameterEntity(ctxt->userData, name); 02491 if (entity == NULL) { 02492 02493 /* 02494 * [ WFC: Entity Declared ] 02495 * In a document without any DTD, a document with only an 02496 * internal DTD subset which contains no parameter entity 02497 * references, or a document with "standalone='yes'", ... 02498 * ... The declaration of a parameter entity must precede 02499 * any reference to it... 02500 */ 02501 if ((ctxt->standalone == 1) || 02502 ((ctxt->hasExternalSubset == 0) && 02503 (ctxt->hasPErefs == 0))) { 02504 xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY, 02505 "PEReference: %%%s; not found\n", name); 02506 } else { 02507 /* 02508 * [ VC: Entity Declared ] 02509 * In a document with an external subset or external 02510 * parameter entities with "standalone='no'", ... 02511 * ... The declaration of a parameter entity must precede 02512 * any reference to it... 02513 */ 02514 if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) { 02515 xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY, 02516 "PEReference: %%%s; not found\n", 02517 name, NULL); 02518 } else 02519 xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY, 02520 "PEReference: %%%s; not found\n", 02521 name, NULL); 02522 ctxt->valid = 0; 02523 } 02524 } else if (ctxt->input->free != deallocblankswrapper) { 02525 input = xmlNewBlanksWrapperInputStream(ctxt, entity); 02526 if (xmlPushInput(ctxt, input) < 0) 02527 return; 02528 } else { 02529 if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) || 02530 (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) { 02531 xmlChar start[4]; 02532 xmlCharEncoding enc; 02533 02534 /* 02535 * handle the extra spaces added before and after 02536 * c.f. http://www.w3.org/TR/REC-xml#as-PE 02537 * this is done independently. 02538 */ 02539 input = xmlNewEntityInputStream(ctxt, entity); 02540 if (xmlPushInput(ctxt, input) < 0) 02541 return; 02542 02543 /* 02544 * Get the 4 first bytes and decode the charset 02545 * if enc != XML_CHAR_ENCODING_NONE 02546 * plug some encoding conversion routines. 02547 * Note that, since we may have some non-UTF8 02548 * encoding (like UTF16, bug 135229), the 'length' 02549 * is not known, but we can calculate based upon 02550 * the amount of data in the buffer. 02551 */ 02552 GROW 02553 if ((ctxt->input->end - ctxt->input->cur)>=4) { 02554 start[0] = RAW; 02555 start[1] = NXT(1); 02556 start[2] = NXT(2); 02557 start[3] = NXT(3); 02558 enc = xmlDetectCharEncoding(start, 4); 02559 if (enc != XML_CHAR_ENCODING_NONE) { 02560 xmlSwitchEncoding(ctxt, enc); 02561 } 02562 } 02563 02564 if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) && 02565 (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) && 02566 (IS_BLANK_CH(NXT(5)))) { 02567 xmlParseTextDecl(ctxt); 02568 } 02569 } else { 02570 xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER, 02571 "PEReference: %s is not a parameter entity\n", 02572 name); 02573 } 02574 } 02575 } else { 02576 xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL); 02577 } 02578 } 02579 } 02580 02581 /* 02582 * Macro used to grow the current buffer. 02583 */ 02584 #define growBuffer(buffer, n) { \ 02585 xmlChar *tmp; \ 02586 buffer##_size *= 2; \ 02587 buffer##_size += n; \ 02588 tmp = (xmlChar *) \ 02589 xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \ 02590 if (tmp == NULL) goto mem_error; \ 02591 buffer = tmp; \ 02592 } 02593 02613 xmlChar * 02614 xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, 02615 int what, xmlChar end, xmlChar end2, xmlChar end3) { 02616 xmlChar *buffer = NULL; 02617 int buffer_size = 0; 02618 02619 xmlChar *current = NULL; 02620 xmlChar *rep = NULL; 02621 const xmlChar *last; 02622 xmlEntityPtr ent; 02623 int c,l; 02624 int nbchars = 0; 02625 02626 if ((ctxt == NULL) || (str == NULL) || (len < 0)) 02627 return(NULL); 02628 last = str + len; 02629 02630 if (((ctxt->depth > 40) && 02631 ((ctxt->options & XML_PARSE_HUGE) == 0)) || 02632 (ctxt->depth > 1024)) { 02633 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); 02634 return(NULL); 02635 } 02636 02637 /* 02638 * allocate a translation buffer. 02639 */ 02640 buffer_size = XML_PARSER_BIG_BUFFER_SIZE; 02641 buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar)); 02642 if (buffer == NULL) goto mem_error; 02643 02644 /* 02645 * OK loop until we reach one of the ending char or a size limit. 02646 * we are operating on already parsed values. 02647 */ 02648 if (str < last) 02649 c = CUR_SCHAR(str, l); 02650 else 02651 c = 0; 02652 while ((c != 0) && (c != end) && /* non input consuming loop */ 02653 (c != end2) && (c != end3)) { 02654 02655 if (c == 0) break; 02656 if ((c == '&') && (str[1] == '#')) { 02657 int val = xmlParseStringCharRef(ctxt, &str); 02658 if (val != 0) { 02659 COPY_BUF(0,buffer,nbchars,val); 02660 } 02661 if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { 02662 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 02663 } 02664 } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) { 02665 if (xmlParserDebugEntities) 02666 xmlGenericError(xmlGenericErrorContext, 02667 "String decoding Entity Reference: %.30s\n", 02668 str); 02669 ent = xmlParseStringEntityRef(ctxt, &str); 02670 if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) || 02671 (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR)) 02672 goto int_error; 02673 if (ent != NULL) 02674 ctxt->nbentities += ent->checked; 02675 if ((ent != NULL) && 02676 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { 02677 if (ent->content != NULL) { 02678 COPY_BUF(0,buffer,nbchars,ent->content[0]); 02679 if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { 02680 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 02681 } 02682 } else { 02683 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, 02684 "predefined entity has no content\n"); 02685 } 02686 } else if ((ent != NULL) && (ent->content != NULL)) { 02687 ctxt->depth++; 02688 rep = xmlStringDecodeEntities(ctxt, ent->content, what, 02689 0, 0, 0); 02690 ctxt->depth--; 02691 02692 if (rep != NULL) { 02693 current = rep; 02694 while (*current != 0) { /* non input consuming loop */ 02695 buffer[nbchars++] = *current++; 02696 if (nbchars > 02697 buffer_size - XML_PARSER_BUFFER_SIZE) { 02698 if (xmlParserEntityCheck(ctxt, nbchars, ent)) 02699 goto int_error; 02700 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 02701 } 02702 } 02703 xmlFree(rep); 02704 rep = NULL; 02705 } 02706 } else if (ent != NULL) { 02707 int i = xmlStrlen(ent->name); 02708 const xmlChar *cur = ent->name; 02709 02710 buffer[nbchars++] = '&'; 02711 if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) { 02712 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 02713 } 02714 for (;i > 0;i--) 02715 buffer[nbchars++] = *cur++; 02716 buffer[nbchars++] = ';'; 02717 } 02718 } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) { 02719 if (xmlParserDebugEntities) 02720 xmlGenericError(xmlGenericErrorContext, 02721 "String decoding PE Reference: %.30s\n", str); 02722 ent = xmlParseStringPEReference(ctxt, &str); 02723 if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) 02724 goto int_error; 02725 if (ent != NULL) 02726 ctxt->nbentities += ent->checked; 02727 if (ent != NULL) { 02728 if (ent->content == NULL) { 02729 xmlLoadEntityContent(ctxt, ent); 02730 } 02731 ctxt->depth++; 02732 rep = xmlStringDecodeEntities(ctxt, ent->content, what, 02733 0, 0, 0); 02734 ctxt->depth--; 02735 if (rep != NULL) { 02736 current = rep; 02737 while (*current != 0) { /* non input consuming loop */ 02738 buffer[nbchars++] = *current++; 02739 if (nbchars > 02740 buffer_size - XML_PARSER_BUFFER_SIZE) { 02741 if (xmlParserEntityCheck(ctxt, nbchars, ent)) 02742 goto int_error; 02743 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 02744 } 02745 } 02746 xmlFree(rep); 02747 rep = NULL; 02748 } 02749 } 02750 } else { 02751 COPY_BUF(l,buffer,nbchars,c); 02752 str += l; 02753 if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { 02754 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); 02755 } 02756 } 02757 if (str < last) 02758 c = CUR_SCHAR(str, l); 02759 else 02760 c = 0; 02761 } 02762 buffer[nbchars] = 0; 02763 return(buffer); 02764 02765 mem_error: 02766 xmlErrMemory(ctxt, NULL); 02767 int_error: 02768 if (rep != NULL) 02769 xmlFree(rep); 02770 if (buffer != NULL) 02771 xmlFree(buffer); 02772 return(NULL); 02773 } 02774 02793 xmlChar * 02794 xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what, 02795 xmlChar end, xmlChar end2, xmlChar end3) { 02796 if ((ctxt == NULL) || (str == NULL)) return(NULL); 02797 return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what, 02798 end, end2, end3)); 02799 } 02800 02801 /************************************************************************ 02802 * * 02803 * Commodity functions, cleanup needed ? * 02804 * * 02805 ************************************************************************/ 02806 02819 static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, 02820 int blank_chars) { 02821 int i, ret; 02822 xmlNodePtr lastChild; 02823 02824 /* 02825 * Don't spend time trying to differentiate them, the same callback is 02826 * used ! 02827 */ 02828 if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters) 02829 return(0); 02830 02831 /* 02832 * Check for xml:space value. 02833 */ 02834 if ((ctxt->space == NULL) || (*(ctxt->space) == 1) || 02835 (*(ctxt->space) == -2)) 02836 return(0); 02837 02838 /* 02839 * Check that the string is made of blanks 02840 */ 02841 if (blank_chars == 0) { 02842 for (i = 0;i < len;i++) 02843 if (!(IS_BLANK_CH(str[i]))) return(0); 02844 } 02845 02846 /* 02847 * Look if the element is mixed content in the DTD if available 02848 */ 02849 if (ctxt->node == NULL) return(0); 02850 if (ctxt->myDoc != NULL) { 02851 ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name); 02852 if (ret == 0) return(1); 02853 if (ret == 1) return(0); 02854 } 02855 02856 /* 02857 * Otherwise, heuristic :-\ 02858 */ 02859 if ((RAW != '<') && (RAW != 0xD)) return(0); 02860 if ((ctxt->node->children == NULL) && 02861 (RAW == '<') && (NXT(1) == '/')) return(0); 02862 02863 lastChild = xmlGetLastChild(ctxt->node); 02864 if (lastChild == NULL) { 02865 if ((ctxt->node->type != XML_ELEMENT_NODE) && 02866 (ctxt->node->content != NULL)) return(0); 02867 } else if (xmlNodeIsText(lastChild)) 02868 return(0); 02869 else if ((ctxt->node->children != NULL) && 02870 (xmlNodeIsText(ctxt->node->children))) 02871 return(0); 02872 return(1); 02873 } 02874 02875 /************************************************************************ 02876 * * 02877 * Extra stuff for namespace support * 02878 * Relates to http://www.w3.org/TR/WD-xml-names * 02879 * * 02880 ************************************************************************/ 02881 02900 xmlChar * 02901 xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { 02902 xmlChar buf[XML_MAX_NAMELEN + 5]; 02903 xmlChar *buffer = NULL; 02904 int len = 0; 02905 int max = XML_MAX_NAMELEN; 02906 xmlChar *ret = NULL; 02907 const xmlChar *cur = name; 02908 int c; 02909 02910 if (prefix == NULL) return(NULL); 02911 *prefix = NULL; 02912 02913 if (cur == NULL) return(NULL); 02914 02915 #ifndef XML_XML_NAMESPACE 02916 /* xml: prefix is not really a namespace */ 02917 if ((cur[0] == 'x') && (cur[1] == 'm') && 02918 (cur[2] == 'l') && (cur[3] == ':')) 02919 return(xmlStrdup(name)); 02920 #endif 02921 02922 /* nasty but well=formed */ 02923 if (cur[0] == ':') 02924 return(xmlStrdup(name)); 02925 02926 c = *cur++; 02927 while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */ 02928 buf[len++] = c; 02929 c = *cur++; 02930 } 02931 if (len >= max) { 02932 /* 02933 * Okay someone managed to make a huge name, so he's ready to pay 02934 * for the processing speed. 02935 */ 02936 max = len * 2; 02937 02938 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); 02939 if (buffer == NULL) { 02940 xmlErrMemory(ctxt, NULL); 02941 return(NULL); 02942 } 02943 memcpy(buffer, buf, len); 02944 while ((c != 0) && (c != ':')) { /* tested bigname.xml */ 02945 if (len + 10 > max) { 02946 xmlChar *tmp; 02947 02948 max *= 2; 02949 tmp = (xmlChar *) xmlRealloc(buffer, 02950 max * sizeof(xmlChar)); 02951 if (tmp == NULL) { 02952 xmlFree(buffer); 02953 xmlErrMemory(ctxt, NULL); 02954 return(NULL); 02955 } 02956 buffer = tmp; 02957 } 02958 buffer[len++] = c; 02959 c = *cur++; 02960 } 02961 buffer[len] = 0; 02962 } 02963 02964 if ((c == ':') && (*cur == 0)) { 02965 if (buffer != NULL) 02966 xmlFree(buffer); 02967 *prefix = NULL; 02968 return(xmlStrdup(name)); 02969 } 02970 02971 if (buffer == NULL) 02972 ret = xmlStrndup(buf, len); 02973 else { 02974 ret = buffer; 02975 buffer = NULL; 02976 max = XML_MAX_NAMELEN; 02977 } 02978 02979 02980 if (c == ':') { 02981 c = *cur; 02982 *prefix = ret; 02983 if (c == 0) { 02984 return(xmlStrndup(BAD_CAST "", 0)); 02985 } 02986 len = 0; 02987 02988 /* 02989 * Check that the first character is proper to start 02990 * a new name 02991 */ 02992 if (!(((c >= 0x61) && (c <= 0x7A)) || 02993 ((c >= 0x41) && (c <= 0x5A)) || 02994 (c == '_') || (c == ':'))) { 02995 int l; 02996 int first = CUR_SCHAR(cur, l); 02997 02998 if (!IS_LETTER(first) && (first != '_')) { 02999 xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME, 03000 "Name %s is not XML Namespace compliant\n", 03001 name); 03002 } 03003 } 03004 cur++; 03005 03006 while ((c != 0) && (len < max)) { /* tested bigname2.xml */ 03007 buf[len++] = c; 03008 c = *cur++; 03009 } 03010 if (len >= max) { 03011 /* 03012 * Okay someone managed to make a huge name, so he's ready to pay 03013 * for the processing speed. 03014 */ 03015 max = len * 2; 03016 03017 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); 03018 if (buffer == NULL) { 03019 xmlErrMemory(ctxt, NULL); 03020 return(NULL); 03021 } 03022 memcpy(buffer, buf, len); 03023 while (c != 0) { /* tested bigname2.xml */ 03024 if (len + 10 > max) { 03025 xmlChar *tmp; 03026 03027 max *= 2; 03028 tmp = (xmlChar *) xmlRealloc(buffer, 03029 max * sizeof(xmlChar)); 03030 if (tmp == NULL) { 03031 xmlErrMemory(ctxt, NULL); 03032 xmlFree(buffer); 03033 return(NULL); 03034 } 03035 buffer = tmp; 03036 } 03037 buffer[len++] = c; 03038 c = *cur++; 03039 } 03040 buffer[len] = 0; 03041 } 03042 03043 if (buffer == NULL) 03044 ret = xmlStrndup(buf, len); 03045 else { 03046 ret = buffer; 03047 } 03048 } 03049 03050 return(ret); 03051 } 03052 03053 /************************************************************************ 03054 * * 03055 * The parser itself * 03056 * Relates to http://www.w3.org/TR/REC-xml * 03057 * * 03058 ************************************************************************/ 03059 03060 /************************************************************************ 03061 * * 03062 * Routines to parse Name, NCName and NmToken * 03063 * * 03064 ************************************************************************/ 03065 #ifdef DEBUG 03066 static unsigned long nbParseName = 0; 03067 static unsigned long nbParseNmToken = 0; 03068 static unsigned long nbParseNCName = 0; 03069 static unsigned long nbParseNCNameComplex = 0; 03070 static unsigned long nbParseNameComplex = 0; 03071 static unsigned long nbParseStringName = 0; 03072 #endif 03073 03074 /* 03075 * The two following functions are related to the change of accepted 03076 * characters for Name and NmToken in the Revision 5 of XML-1.0 03077 * They correspond to the modified production [4] and the new production [4a] 03078 * changes in that revision. Also note that the macros used for the 03079 * productions Letter, Digit, CombiningChar and Extender are not needed 03080 * anymore. 03081 * We still keep compatibility to pre-revision5 parsing semantic if the 03082 * new XML_PARSE_OLD10 option is given to the parser. 03083 */ 03084 static int 03085 xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) { 03086 if ((ctxt->options & XML_PARSE_OLD10) == 0) { 03087 /* 03088 * Use the new checks of production [4] [4a] amd [5] of the 03089 * Update 5 of XML-1.0 03090 */ 03091 if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */ 03092 (((c >= 'a') && (c <= 'z')) || 03093 ((c >= 'A') && (c <= 'Z')) || 03094 (c == '_') || (c == ':') || 03095 ((c >= 0xC0) && (c <= 0xD6)) || 03096 ((c >= 0xD8) && (c <= 0xF6)) || 03097 ((c >= 0xF8) && (c <= 0x2FF)) || 03098 ((c >= 0x370) && (c <= 0x37D)) || 03099 ((c >= 0x37F) && (c <= 0x1FFF)) || 03100 ((c >= 0x200C) && (c <= 0x200D)) || 03101 ((c >= 0x2070) && (c <= 0x218F)) || 03102 ((c >= 0x2C00) && (c <= 0x2FEF)) || 03103 ((c >= 0x3001) && (c <= 0xD7FF)) || 03104 ((c >= 0xF900) && (c <= 0xFDCF)) || 03105 ((c >= 0xFDF0) && (c <= 0xFFFD)) || 03106 ((c >= 0x10000) && (c <= 0xEFFFF)))) 03107 return(1); 03108 } else { 03109 if (IS_LETTER(c) || (c == '_') || (c == ':')) 03110 return(1); 03111 } 03112 return(0); 03113 } 03114 03115 static int 03116 xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) { 03117 if ((ctxt->options & XML_PARSE_OLD10) == 0) { 03118 /* 03119 * Use the new checks of production [4] [4a] amd [5] of the 03120 * Update 5 of XML-1.0 03121 */ 03122 if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */ 03123 (((c >= 'a') && (c <= 'z')) || 03124 ((c >= 'A') && (c <= 'Z')) || 03125 ((c >= '0') && (c <= '9')) || /* !start */ 03126 (c == '_') || (c == ':') || 03127 (c == '-') || (c == '.') || (c == 0xB7) || /* !start */ 03128 ((c >= 0xC0) && (c <= 0xD6)) || 03129 ((c >= 0xD8) && (c <= 0xF6)) || 03130 ((c >= 0xF8) && (c <= 0x2FF)) || 03131 ((c >= 0x300) && (c <= 0x36F)) || /* !start */ 03132 ((c >= 0x370) && (c <= 0x37D)) || 03133 ((c >= 0x37F) && (c <= 0x1FFF)) || 03134 ((c >= 0x200C) && (c <= 0x200D)) || 03135 ((c >= 0x203F) && (c <= 0x2040)) || /* !start */ 03136 ((c >= 0x2070) && (c <= 0x218F)) || 03137 ((c >= 0x2C00) && (c <= 0x2FEF)) || 03138 ((c >= 0x3001) && (c <= 0xD7FF)) || 03139 ((c >= 0xF900) && (c <= 0xFDCF)) || 03140 ((c >= 0xFDF0) && (c <= 0xFFFD)) || 03141 ((c >= 0x10000) && (c <= 0xEFFFF)))) 03142 return(1); 03143 } else { 03144 if ((IS_LETTER(c)) || (IS_DIGIT(c)) || 03145 (c == '.') || (c == '-') || 03146 (c == '_') || (c == ':') || 03147 (IS_COMBINING(c)) || 03148 (IS_EXTENDER(c))) 03149 return(1); 03150 } 03151 return(0); 03152 } 03153 03154 static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, 03155 int *len, int *alloc, int normalize); 03156 03157 static const xmlChar * 03158 xmlParseNameComplex(xmlParserCtxtPtr ctxt) { 03159 int len = 0, l; 03160 int c; 03161 int count = 0; 03162 03163 #ifdef DEBUG 03164 nbParseNameComplex++; 03165 #endif 03166 03167 /* 03168 * Handler for more complex cases 03169 */ 03170 GROW; 03171 c = CUR_CHAR(l); 03172 if ((ctxt->options & XML_PARSE_OLD10) == 0) { 03173 /* 03174 * Use the new checks of production [4] [4a] amd [5] of the 03175 * Update 5 of XML-1.0 03176 */ 03177 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ 03178 (!(((c >= 'a') && (c <= 'z')) || 03179 ((c >= 'A') && (c <= 'Z')) || 03180 (c == '_') || (c == ':') || 03181 ((c >= 0xC0) && (c <= 0xD6)) || 03182 ((c >= 0xD8) && (c <= 0xF6)) || 03183 ((c >= 0xF8) && (c <= 0x2FF)) || 03184 ((c >= 0x370) && (c <= 0x37D)) || 03185 ((c >= 0x37F) && (c <= 0x1FFF)) || 03186 ((c >= 0x200C) && (c <= 0x200D)) || 03187 ((c >= 0x2070) && (c <= 0x218F)) || 03188 ((c >= 0x2C00) && (c <= 0x2FEF)) || 03189 ((c >= 0x3001) && (c <= 0xD7FF)) || 03190 ((c >= 0xF900) && (c <= 0xFDCF)) || 03191 ((c >= 0xFDF0) && (c <= 0xFFFD)) || 03192 ((c >= 0x10000) && (c <= 0xEFFFF))))) { 03193 return(NULL); 03194 } 03195 len += l; 03196 NEXTL(l); 03197 c = CUR_CHAR(l); 03198 while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */ 03199 (((c >= 'a') && (c <= 'z')) || 03200 ((c >= 'A') && (c <= 'Z')) || 03201 ((c >= '0') && (c <= '9')) || /* !start */ 03202 (c == '_') || (c == ':') || 03203 (c == '-') || (c == '.') || (c == 0xB7) || /* !start */ 03204 ((c >= 0xC0) && (c <= 0xD6)) || 03205 ((c >= 0xD8) && (c <= 0xF6)) || 03206 ((c >= 0xF8) && (c <= 0x2FF)) || 03207 ((c >= 0x300) && (c <= 0x36F)) || /* !start */ 03208 ((c >= 0x370) && (c <= 0x37D)) || 03209 ((c >= 0x37F) && (c <= 0x1FFF)) || 03210 ((c >= 0x200C) && (c <= 0x200D)) || 03211 ((c >= 0x203F) && (c <= 0x2040)) || /* !start */ 03212 ((c >= 0x2070) && (c <= 0x218F)) || 03213 ((c >= 0x2C00) && (c <= 0x2FEF)) || 03214 ((c >= 0x3001) && (c <= 0xD7FF)) || 03215 ((c >= 0xF900) && (c <= 0xFDCF)) || 03216 ((c >= 0xFDF0) && (c <= 0xFFFD)) || 03217 ((c >= 0x10000) && (c <= 0xEFFFF)) 03218 )) { 03219 if (count++ > 100) { 03220 count = 0; 03221 GROW; 03222 } 03223 len += l; 03224 NEXTL(l); 03225 c = CUR_CHAR(l); 03226 } 03227 } else { 03228 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ 03229 (!IS_LETTER(c) && (c != '_') && 03230 (c != ':'))) { 03231 return(NULL); 03232 } 03233 len += l; 03234 NEXTL(l); 03235 c = CUR_CHAR(l); 03236 03237 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ 03238 ((IS_LETTER(c)) || (IS_DIGIT(c)) || 03239 (c == '.') || (c == '-') || 03240 (c == '_') || (c == ':') || 03241 (IS_COMBINING(c)) || 03242 (IS_EXTENDER(c)))) { 03243 if (count++ > 100) { 03244 count = 0; 03245 GROW; 03246 } 03247 len += l; 03248 NEXTL(l); 03249 c = CUR_CHAR(l); 03250 } 03251 } 03252 if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r')) 03253 return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len)); 03254 return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len)); 03255 } 03256 03273 const xmlChar * 03274 xmlParseName(xmlParserCtxtPtr ctxt) { 03275 const xmlChar *in; 03276 const xmlChar *ret; 03277 int count = 0; 03278 03279 GROW; 03280 03281 #ifdef DEBUG 03282 nbParseName++; 03283 #endif 03284 03285 /* 03286 * Accelerator for simple ASCII names 03287 */ 03288 in = ctxt->input->cur; 03289 if (((*in >= 0x61) && (*in <= 0x7A)) || 03290 ((*in >= 0x41) && (*in <= 0x5A)) || 03291 (*in == '_') || (*in == ':')) { 03292 in++; 03293 while (((*in >= 0x61) && (*in <= 0x7A)) || 03294 ((*in >= 0x41) && (*in <= 0x5A)) || 03295 ((*in >= 0x30) && (*in <= 0x39)) || 03296 (*in == '_') || (*in == '-') || 03297 (*in == ':') || (*in == '.')) 03298 in++; 03299 if ((*in > 0) && (*in < 0x80)) { 03300 count = in - ctxt->input->cur; 03301 ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count); 03302 ctxt->input->cur = in; 03303 ctxt->nbChars += count; 03304 ctxt->input->col += count; 03305 if (ret == NULL) 03306 xmlErrMemory(ctxt, NULL); 03307 return(ret); 03308 } 03309 } 03310 /* accelerator for special cases */ 03311 return(xmlParseNameComplex(ctxt)); 03312 } 03313 03314 static const xmlChar * 03315 xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { 03316 int len = 0, l; 03317 int c; 03318 int count = 0; 03319 03320 #ifdef DEBUG 03321 nbParseNCNameComplex++; 03322 #endif 03323 03324 /* 03325 * Handler for more complex cases 03326 */ 03327 GROW; 03328 c = CUR_CHAR(l); 03329 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ 03330 (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) { 03331 return(NULL); 03332 } 03333 03334 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ 03335 (xmlIsNameChar(ctxt, c) && (c != ':'))) { 03336 if (count++ > 100) { 03337 count = 0; 03338 GROW; 03339 } 03340 len += l; 03341 NEXTL(l); 03342 c = CUR_CHAR(l); 03343 } 03344 return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len)); 03345 } 03346 03362 static const xmlChar * 03363 xmlParseNCName(xmlParserCtxtPtr ctxt) { 03364 const xmlChar *in; 03365 const xmlChar *ret; 03366 int count = 0; 03367 03368 #ifdef DEBUG 03369 nbParseNCName++; 03370 #endif 03371 03372 /* 03373 * Accelerator for simple ASCII names 03374 */ 03375 in = ctxt->input->cur; 03376 if (((*in >= 0x61) && (*in <= 0x7A)) || 03377 ((*in >= 0x41) && (*in <= 0x5A)) || 03378 (*in == '_')) { 03379 in++; 03380 while (((*in >= 0x61) && (*in <= 0x7A)) || 03381 ((*in >= 0x41) && (*in <= 0x5A)) || 03382 ((*in >= 0x30) && (*in <= 0x39)) || 03383 (*in == '_') || (*in == '-') || 03384 (*in == '.')) 03385 in++; 03386 if ((*in > 0) && (*in < 0x80)) { 03387 count = in - ctxt->input->cur; 03388 ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count); 03389 ctxt->input->cur = in; 03390 ctxt->nbChars += count; 03391 ctxt->input->col += count; 03392 if (ret == NULL) { 03393 xmlErrMemory(ctxt, NULL); 03394 } 03395 return(ret); 03396 } 03397 } 03398 return(xmlParseNCNameComplex(ctxt)); 03399 } 03400 03412 static const xmlChar * 03413 xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) { 03414 register const xmlChar *cmp = other; 03415 register const xmlChar *in; 03416 const xmlChar *ret; 03417 03418 GROW; 03419 03420 in = ctxt->input->cur; 03421 while (*in != 0 && *in == *cmp) { 03422 ++in; 03423 ++cmp; 03424 ctxt->input->col++; 03425 } 03426 if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) { 03427 /* success */ 03428 ctxt->input->cur = in; 03429 return (const xmlChar*) 1; 03430 } 03431 /* failure (or end of input buffer), check with full function */ 03432 ret = xmlParseName (ctxt); 03433 /* strings coming from the dictionnary direct compare possible */ 03434 if (ret == other) { 03435 return (const xmlChar*) 1; 03436 } 03437 return ret; 03438 } 03439 03458 static xmlChar * 03459 xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { 03460 xmlChar buf[XML_MAX_NAMELEN + 5]; 03461 const xmlChar *cur = *str; 03462 int len = 0, l; 03463 int c; 03464 03465 #ifdef DEBUG 03466 nbParseStringName++; 03467 #endif 03468 03469 c = CUR_SCHAR(cur, l); 03470 if (!xmlIsNameStartChar(ctxt, c)) { 03471 return(NULL); 03472 } 03473 03474 COPY_BUF(l,buf,len,c); 03475 cur += l; 03476 c = CUR_SCHAR(cur, l); 03477 while (xmlIsNameChar(ctxt, c)) { 03478 COPY_BUF(l,buf,len,c); 03479 cur += l; 03480 c = CUR_SCHAR(cur, l); 03481 if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */ 03482 /* 03483 * Okay someone managed to make a huge name, so he's ready to pay 03484 * for the processing speed. 03485 */ 03486 xmlChar *buffer; 03487 int max = len * 2; 03488 03489 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); 03490 if (buffer == NULL) { 03491 xmlErrMemory(ctxt, NULL); 03492 return(NULL); 03493 } 03494 memcpy(buffer, buf, len); 03495 while (xmlIsNameChar(ctxt, c)) { 03496 if (len + 10 > max) { 03497 xmlChar *tmp; 03498 max *= 2; 03499 tmp = (xmlChar *) xmlRealloc(buffer, 03500 max * sizeof(xmlChar)); 03501 if (tmp == NULL) { 03502 xmlErrMemory(ctxt, NULL); 03503 xmlFree(buffer); 03504 return(NULL); 03505 } 03506 buffer = tmp; 03507 } 03508 COPY_BUF(l,buffer,len,c); 03509 cur += l; 03510 c = CUR_SCHAR(cur, l); 03511 } 03512 buffer[len] = 0; 03513 *str = cur; 03514 return(buffer); 03515 } 03516 } 03517 *str = cur; 03518 return(xmlStrndup(buf, len)); 03519 } 03520 03534 xmlChar * 03535 xmlParseNmtoken(xmlParserCtxtPtr ctxt) { 03536 xmlChar buf[XML_MAX_NAMELEN + 5]; 03537 int len = 0, l; 03538 int c; 03539 int count = 0; 03540 03541 #ifdef DEBUG 03542 nbParseNmToken++; 03543 #endif 03544 03545 GROW; 03546 c = CUR_CHAR(l); 03547 03548 while (xmlIsNameChar(ctxt, c)) { 03549 if (count++ > 100) { 03550 count = 0; 03551 GROW; 03552 } 03553 COPY_BUF(l,buf,len,c); 03554 NEXTL(l); 03555 c = CUR_CHAR(l); 03556 if (len >= XML_MAX_NAMELEN) { 03557 /* 03558 * Okay someone managed to make a huge token, so he's ready to pay 03559 * for the processing speed. 03560 */ 03561 xmlChar *buffer; 03562 int max = len * 2; 03563 03564 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); 03565 if (buffer == NULL) { 03566 xmlErrMemory(ctxt, NULL); 03567 return(NULL); 03568 } 03569 memcpy(buffer, buf, len); 03570 while (xmlIsNameChar(ctxt, c)) { 03571 if (count++ > 100) { 03572 count = 0; 03573 GROW; 03574 } 03575 if (len + 10 > max) { 03576 xmlChar *tmp; 03577 03578 max *= 2; 03579 tmp = (xmlChar *) xmlRealloc(buffer, 03580 max * sizeof(xmlChar)); 03581 if (tmp == NULL) { 03582 xmlErrMemory(ctxt, NULL); 03583 xmlFree(buffer); 03584 return(NULL); 03585 } 03586 buffer = tmp; 03587 } 03588 COPY_BUF(l,buffer,len,c); 03589 NEXTL(l); 03590 c = CUR_CHAR(l); 03591 } 03592 buffer[len] = 0; 03593 return(buffer); 03594 } 03595 } 03596 if (len == 0) 03597 return(NULL); 03598 return(xmlStrndup(buf, len)); 03599 } 03600 03614 xmlChar * 03615 xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { 03616 xmlChar *buf = NULL; 03617 int len = 0; 03618 int size = XML_PARSER_BUFFER_SIZE; 03619 int c, l; 03620 xmlChar stop; 03621 xmlChar *ret = NULL; 03622 const xmlChar *cur = NULL; 03623 xmlParserInputPtr input; 03624 03625 if (RAW == '"') stop = '"'; 03626 else if (RAW == '\'') stop = '\''; 03627 else { 03628 xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL); 03629 return(NULL); 03630 } 03631 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 03632 if (buf == NULL) { 03633 xmlErrMemory(ctxt, NULL); 03634 return(NULL); 03635 } 03636 03637 /* 03638 * The content of the entity definition is copied in a buffer. 03639 */ 03640 03641 ctxt->instate = XML_PARSER_ENTITY_VALUE; 03642 input = ctxt->input; 03643 GROW; 03644 NEXT; 03645 c = CUR_CHAR(l); 03646 /* 03647 * NOTE: 4.4.5 Included in Literal 03648 * When a parameter entity reference appears in a literal entity 03649 * value, ... a single or double quote character in the replacement 03650 * text is always treated as a normal data character and will not 03651 * terminate the literal. 03652 * In practice it means we stop the loop only when back at parsing 03653 * the initial entity and the quote is found 03654 */ 03655 while ((IS_CHAR(c)) && ((c != stop) || /* checked */ 03656 (ctxt->input != input))) { 03657 if (len + 5 >= size) { 03658 xmlChar *tmp; 03659 03660 size *= 2; 03661 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); 03662 if (tmp == NULL) { 03663 xmlErrMemory(ctxt, NULL); 03664 xmlFree(buf); 03665 return(NULL); 03666 } 03667 buf = tmp; 03668 } 03669 COPY_BUF(l,buf,len,c); 03670 NEXTL(l); 03671 /* 03672 * Pop-up of finished entities. 03673 */ 03674 while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */ 03675 xmlPopInput(ctxt); 03676 03677 GROW; 03678 c = CUR_CHAR(l); 03679 if (c == 0) { 03680 GROW; 03681 c = CUR_CHAR(l); 03682 } 03683 } 03684 buf[len] = 0; 03685 03686 /* 03687 * Raise problem w.r.t. '&' and '%' being used in non-entities 03688 * reference constructs. Note Charref will be handled in 03689 * xmlStringDecodeEntities() 03690 */ 03691 cur = buf; 03692 while (*cur != 0) { /* non input consuming */ 03693 if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) { 03694 xmlChar *name; 03695 xmlChar tmp = *cur; 03696 03697 cur++; 03698 name = xmlParseStringName(ctxt, &cur); 03699 if ((name == NULL) || (*cur != ';')) { 03700 xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR, 03701 "EntityValue: '%c' forbidden except for entities references\n", 03702 tmp); 03703 } 03704 if ((tmp == '%') && (ctxt->inSubset == 1) && 03705 (ctxt->inputNr == 1)) { 03706 xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL); 03707 } 03708 if (name != NULL) 03709 xmlFree(name); 03710 if (*cur == 0) 03711 break; 03712 } 03713 cur++; 03714 } 03715 03716 /* 03717 * Then PEReference entities are substituted. 03718 */ 03719 if (c != stop) { 03720 xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL); 03721 xmlFree(buf); 03722 } else { 03723 NEXT; 03724 /* 03725 * NOTE: 4.4.7 Bypassed 03726 * When a general entity reference appears in the EntityValue in 03727 * an entity declaration, it is bypassed and left as is. 03728 * so XML_SUBSTITUTE_REF is not set here. 03729 */ 03730 ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF, 03731 0, 0, 0); 03732 if (orig != NULL) 03733 *orig = buf; 03734 else 03735 xmlFree(buf); 03736 } 03737 03738 return(ret); 03739 } 03740 03753 static xmlChar * 03754 xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { 03755 xmlChar limit = 0; 03756 xmlChar *buf = NULL; 03757 xmlChar *rep = NULL; 03758 int len = 0; 03759 int buf_size = 0; 03760 int c, l, in_space = 0; 03761 xmlChar *current = NULL; 03762 xmlEntityPtr ent; 03763 03764 if (NXT(0) == '"') { 03765 ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE; 03766 limit = '"'; 03767 NEXT; 03768 } else if (NXT(0) == '\'') { 03769 limit = '\''; 03770 ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE; 03771 NEXT; 03772 } else { 03773 xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL); 03774 return(NULL); 03775 } 03776 03777 /* 03778 * allocate a translation buffer. 03779 */ 03780 buf_size = XML_PARSER_BUFFER_SIZE; 03781 buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar)); 03782 if (buf == NULL) goto mem_error; 03783 03784 /* 03785 * OK loop until we reach one of the ending char or a size limit. 03786 */ 03787 c = CUR_CHAR(l); 03788 while ((NXT(0) != limit) && /* checked */ 03789 (IS_CHAR(c)) && (c != '<')) { 03790 if (c == 0) break; 03791 if (c == '&') { 03792 in_space = 0; 03793 if (NXT(1) == '#') { 03794 int val = xmlParseCharRef(ctxt); 03795 03796 if (val == '&') { 03797 if (ctxt->replaceEntities) { 03798 if (len > buf_size - 10) { 03799 growBuffer(buf, 10); 03800 } 03801 buf[len++] = '&'; 03802 } else { 03803 /* 03804 * The reparsing will be done in xmlStringGetNodeList() 03805 * called by the attribute() function in SAX.c 03806 */ 03807 if (len > buf_size - 10) { 03808 growBuffer(buf, 10); 03809 } 03810 buf[len++] = '&'; 03811 buf[len++] = '#'; 03812 buf[len++] = '3'; 03813 buf[len++] = '8'; 03814 buf[len++] = ';'; 03815 } 03816 } else if (val != 0) { 03817 if (len > buf_size - 10) { 03818 growBuffer(buf, 10); 03819 } 03820 len += xmlCopyChar(0, &buf[len], val); 03821 } 03822 } else { 03823 ent = xmlParseEntityRef(ctxt); 03824 ctxt->nbentities++; 03825 if (ent != NULL) 03826 ctxt->nbentities += ent->owner; 03827 if ((ent != NULL) && 03828 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { 03829 if (len > buf_size - 10) { 03830 growBuffer(buf, 10); 03831 } 03832 if ((ctxt->replaceEntities == 0) && 03833 (ent->content[0] == '&')) { 03834 buf[len++] = '&'; 03835 buf[len++] = '#'; 03836 buf[len++] = '3'; 03837 buf[len++] = '8'; 03838 buf[len++] = ';'; 03839 } else { 03840 buf[len++] = ent->content[0]; 03841 } 03842 } else if ((ent != NULL) && 03843 (ctxt->replaceEntities != 0)) { 03844 if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) { 03845 rep = xmlStringDecodeEntities(ctxt, ent->content, 03846 XML_SUBSTITUTE_REF, 03847 0, 0, 0); 03848 if (rep != NULL) { 03849 current = rep; 03850 while (*current != 0) { /* non input consuming */ 03851 if ((*current == 0xD) || (*current == 0xA) || 03852 (*current == 0x9)) { 03853 buf[len++] = 0x20; 03854 current++; 03855 } else 03856 buf[len++] = *current++; 03857 if (len > buf_size - 10) { 03858 growBuffer(buf, 10); 03859 } 03860 } 03861 xmlFree(rep); 03862 rep = NULL; 03863 } 03864 } else { 03865 if (len > buf_size - 10) { 03866 growBuffer(buf, 10); 03867 } 03868 if (ent->content != NULL) 03869 buf[len++] = ent->content[0]; 03870 } 03871 } else if (ent != NULL) { 03872 int i = xmlStrlen(ent->name); 03873 const xmlChar *cur = ent->name; 03874 03875 /* 03876 * This may look absurd but is needed to detect 03877 * entities problems 03878 */ 03879 if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) && 03880 (ent->content != NULL)) { 03881 rep = xmlStringDecodeEntities(ctxt, ent->content, 03882 XML_SUBSTITUTE_REF, 0, 0, 0); 03883 if (rep != NULL) { 03884 xmlFree(rep); 03885 rep = NULL; 03886 } 03887 } 03888 03889 /* 03890 * Just output the reference 03891 */ 03892 buf[len++] = '&'; 03893 while (len > buf_size - i - 10) { 03894 growBuffer(buf, i + 10); 03895 } 03896 for (;i > 0;i--) 03897 buf[len++] = *cur++; 03898 buf[len++] = ';'; 03899 } 03900 } 03901 } else { 03902 if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) { 03903 if ((len != 0) || (!normalize)) { 03904 if ((!normalize) || (!in_space)) { 03905 COPY_BUF(l,buf,len,0x20); 03906 while (len > buf_size - 10) { 03907 growBuffer(buf, 10); 03908 } 03909 } 03910 in_space = 1; 03911 } 03912 } else { 03913 in_space = 0; 03914 COPY_BUF(l,buf,len,c); 03915 if (len > buf_size - 10) { 03916 growBuffer(buf, 10); 03917 } 03918 } 03919 NEXTL(l); 03920 } 03921 GROW; 03922 c = CUR_CHAR(l); 03923 } 03924 if ((in_space) && (normalize)) { 03925 while (buf[len - 1] == 0x20) len--; 03926 } 03927 buf[len] = 0; 03928 if (RAW == '<') { 03929 xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL); 03930 } else if (RAW != limit) { 03931 if ((c != 0) && (!IS_CHAR(c))) { 03932 xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, 03933 "invalid character in attribute value\n"); 03934 } else { 03935 xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, 03936 "AttValue: ' expected\n"); 03937 } 03938 } else 03939 NEXT; 03940 if (attlen != NULL) *attlen = len; 03941 return(buf); 03942 03943 mem_error: 03944 xmlErrMemory(ctxt, NULL); 03945 if (buf != NULL) 03946 xmlFree(buf); 03947 if (rep != NULL) 03948 xmlFree(rep); 03949 return(NULL); 03950 } 03951 03986 xmlChar * 03987 xmlParseAttValue(xmlParserCtxtPtr ctxt) { 03988 if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL); 03989 return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0)); 03990 } 03991 04003 xmlChar * 04004 xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { 04005 xmlChar *buf = NULL; 04006 int len = 0; 04007 int size = XML_PARSER_BUFFER_SIZE; 04008 int cur, l; 04009 xmlChar stop; 04010 int state = ctxt->instate; 04011 int count = 0; 04012 04013 SHRINK; 04014 if (RAW == '"') { 04015 NEXT; 04016 stop = '"'; 04017 } else if (RAW == '\'') { 04018 NEXT; 04019 stop = '\''; 04020 } else { 04021 xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL); 04022 return(NULL); 04023 } 04024 04025 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 04026 if (buf == NULL) { 04027 xmlErrMemory(ctxt, NULL); 04028 return(NULL); 04029 } 04030 ctxt->instate = XML_PARSER_SYSTEM_LITERAL; 04031 cur = CUR_CHAR(l); 04032 while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */ 04033 if (len + 5 >= size) { 04034 xmlChar *tmp; 04035 04036 size *= 2; 04037 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); 04038 if (tmp == NULL) { 04039 xmlFree(buf); 04040 xmlErrMemory(ctxt, NULL); 04041 ctxt->instate = (xmlParserInputState) state; 04042 return(NULL); 04043 } 04044 buf = tmp; 04045 } 04046 count++; 04047 if (count > 50) { 04048 GROW; 04049 count = 0; 04050 } 04051 COPY_BUF(l,buf,len,cur); 04052 NEXTL(l); 04053 cur = CUR_CHAR(l); 04054 if (cur == 0) { 04055 GROW; 04056 SHRINK; 04057 cur = CUR_CHAR(l); 04058 } 04059 } 04060 buf[len] = 0; 04061 ctxt->instate = (xmlParserInputState) state; 04062 if (!IS_CHAR(cur)) { 04063 xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL); 04064 } else { 04065 NEXT; 04066 } 04067 return(buf); 04068 } 04069 04081 xmlChar * 04082 xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { 04083 xmlChar *buf = NULL; 04084 int len = 0; 04085 int size = XML_PARSER_BUFFER_SIZE; 04086 xmlChar cur; 04087 xmlChar stop; 04088 int count = 0; 04089 xmlParserInputState oldstate = ctxt->instate; 04090 04091 SHRINK; 04092 if (RAW == '"') { 04093 NEXT; 04094 stop = '"'; 04095 } else if (RAW == '\'') { 04096 NEXT; 04097 stop = '\''; 04098 } else { 04099 xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL); 04100 return(NULL); 04101 } 04102 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 04103 if (buf == NULL) { 04104 xmlErrMemory(ctxt, NULL); 04105 return(NULL); 04106 } 04107 ctxt->instate = XML_PARSER_PUBLIC_LITERAL; 04108 cur = CUR; 04109 while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */ 04110 if (len + 1 >= size) { 04111 xmlChar *tmp; 04112 04113 size *= 2; 04114 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); 04115 if (tmp == NULL) { 04116 xmlErrMemory(ctxt, NULL); 04117 xmlFree(buf); 04118 return(NULL); 04119 } 04120 buf = tmp; 04121 } 04122 buf[len++] = cur; 04123 count++; 04124 if (count > 50) { 04125 GROW; 04126 count = 0; 04127 } 04128 NEXT; 04129 cur = CUR; 04130 if (cur == 0) { 04131 GROW; 04132 SHRINK; 04133 cur = CUR; 04134 } 04135 } 04136 buf[len] = 0; 04137 if (cur != stop) { 04138 xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL); 04139 } else { 04140 NEXT; 04141 } 04142 ctxt->instate = oldstate; 04143 return(buf); 04144 } 04145 04146 static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata); 04147 04148 /* 04149 * used for the test in the inner loop of the char data testing 04150 */ 04151 static const unsigned char test_char_data[256] = { 04152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04153 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */ 04154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04156 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */ 04157 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 04158 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 04159 0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */ 04160 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 04161 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 04162 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 04163 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */ 04164 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 04165 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 04166 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 04167 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 04168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */ 04169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 04183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 04184 }; 04185 04202 void 04203 xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) { 04204 const xmlChar *in; 04205 int nbchar = 0; 04206 int line = ctxt->input->line; 04207 int col = ctxt->input->col; 04208 int ccol; 04209 04210 SHRINK; 04211 GROW; 04212 /* 04213 * Accelerated common case where input don't need to be 04214 * modified before passing it to the handler. 04215 */ 04216 if (!cdata) { 04217 in = ctxt->input->cur; 04218 do { 04219 get_more_space: 04220 while (*in == 0x20) { in++; ctxt->input->col++; } 04221 if (*in == 0xA) { 04222 do { 04223 ctxt->input->line++; ctxt->input->col = 1; 04224 in++; 04225 } while (*in == 0xA); 04226 goto get_more_space; 04227 } 04228 if (*in == '<') { 04229 nbchar = in - ctxt->input->cur; 04230 if (nbchar > 0) { 04231 const xmlChar *tmp = ctxt->input->cur; 04232 ctxt->input->cur = in; 04233 04234 if ((ctxt->sax != NULL) && 04235 (ctxt->sax->ignorableWhitespace != 04236 ctxt->sax->characters)) { 04237 if (areBlanks(ctxt, tmp, nbchar, 1)) { 04238 if (ctxt->sax->ignorableWhitespace != NULL) 04239 ctxt->sax->ignorableWhitespace(ctxt->userData, 04240 tmp, nbchar); 04241 } else { 04242 if (ctxt->sax->characters != NULL) 04243 ctxt->sax->characters(ctxt->userData, 04244 tmp, nbchar); 04245 if (*ctxt->space == -1) 04246 *ctxt->space = -2; 04247 } 04248 } else if ((ctxt->sax != NULL) && 04249 (ctxt->sax->characters != NULL)) { 04250 ctxt->sax->characters(ctxt->userData, 04251 tmp, nbchar); 04252 } 04253 } 04254 return; 04255 } 04256 04257 get_more: 04258 ccol = ctxt->input->col; 04259 while (test_char_data[*in]) { 04260 in++; 04261 ccol++; 04262 } 04263 ctxt->input->col = ccol; 04264 if (*in == 0xA) { 04265 do { 04266 ctxt->input->line++; ctxt->input->col = 1; 04267 in++; 04268 } while (*in == 0xA); 04269 goto get_more; 04270 } 04271 if (*in == ']') { 04272 if ((in[1] == ']') && (in[2] == '>')) { 04273 xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL); 04274 ctxt->input->cur = in; 04275 return; 04276 } 04277 in++; 04278 ctxt->input->col++; 04279 goto get_more; 04280 } 04281 nbchar = in - ctxt->input->cur; 04282 if (nbchar > 0) { 04283 if ((ctxt->sax != NULL) && 04284 (ctxt->sax->ignorableWhitespace != 04285 ctxt->sax->characters) && 04286 (IS_BLANK_CH(*ctxt->input->cur))) { 04287 const xmlChar *tmp = ctxt->input->cur; 04288 ctxt->input->cur = in; 04289 04290 if (areBlanks(ctxt, tmp, nbchar, 0)) { 04291 if (ctxt->sax->ignorableWhitespace != NULL) 04292 ctxt->sax->ignorableWhitespace(ctxt->userData, 04293 tmp, nbchar); 04294 } else { 04295 if (ctxt->sax->characters != NULL) 04296 ctxt->sax->characters(ctxt->userData, 04297 tmp, nbchar); 04298 if (*ctxt->space == -1) 04299 *ctxt->space = -2; 04300 } 04301 line = ctxt->input->line; 04302 col = ctxt->input->col; 04303 } else if (ctxt->sax != NULL) { 04304 if (ctxt->sax->characters != NULL) 04305 ctxt->sax->characters(ctxt->userData, 04306 ctxt->input->cur, nbchar); 04307 line = ctxt->input->line; 04308 col = ctxt->input->col; 04309 } 04310 /* something really bad happened in the SAX callback */ 04311 if (ctxt->instate != XML_PARSER_CONTENT) 04312 return; 04313 } 04314 ctxt->input->cur = in; 04315 if (*in == 0xD) { 04316 in++; 04317 if (*in == 0xA) { 04318 ctxt->input->cur = in; 04319 in++; 04320 ctxt->input->line++; ctxt->input->col = 1; 04321 continue; /* while */ 04322 } 04323 in--; 04324 } 04325 if (*in == '<') { 04326 return; 04327 } 04328 if (*in == '&') { 04329 return; 04330 } 04331 SHRINK; 04332 GROW; 04333 in = ctxt->input->cur; 04334 } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09)); 04335 nbchar = 0; 04336 } 04337 ctxt->input->line = line; 04338 ctxt->input->col = col; 04339 xmlParseCharDataComplex(ctxt, cdata); 04340 } 04341 04351 static void 04352 xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) { 04353 xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5]; 04354 int nbchar = 0; 04355 int cur, l; 04356 int count = 0; 04357 04358 SHRINK; 04359 GROW; 04360 cur = CUR_CHAR(l); 04361 while ((cur != '<') && /* checked */ 04362 (cur != '&') && 04363 (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ { 04364 if ((cur == ']') && (NXT(1) == ']') && 04365 (NXT(2) == '>')) { 04366 if (cdata) break; 04367 else { 04368 xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL); 04369 } 04370 } 04371 COPY_BUF(l,buf,nbchar,cur); 04372 if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) { 04373 buf[nbchar] = 0; 04374 04375 /* 04376 * OK the segment is to be consumed as chars. 04377 */ 04378 if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) { 04379 if (areBlanks(ctxt, buf, nbchar, 0)) { 04380 if (ctxt->sax->ignorableWhitespace != NULL) 04381 ctxt->sax->ignorableWhitespace(ctxt->userData, 04382 buf, nbchar); 04383 } else { 04384 if (ctxt->sax->characters != NULL) 04385 ctxt->sax->characters(ctxt->userData, buf, nbchar); 04386 if ((ctxt->sax->characters != 04387 ctxt->sax->ignorableWhitespace) && 04388 (*ctxt->space == -1)) 04389 *ctxt->space = -2; 04390 } 04391 } 04392 nbchar = 0; 04393 /* something really bad happened in the SAX callback */ 04394 if (ctxt->instate != XML_PARSER_CONTENT) 04395 return; 04396 } 04397 count++; 04398 if (count > 50) { 04399 GROW; 04400 count = 0; 04401 } 04402 NEXTL(l); 04403 cur = CUR_CHAR(l); 04404 } 04405 if (nbchar != 0) { 04406 buf[nbchar] = 0; 04407 /* 04408 * OK the segment is to be consumed as chars. 04409 */ 04410 if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) { 04411 if (areBlanks(ctxt, buf, nbchar, 0)) { 04412 if (ctxt->sax->ignorableWhitespace != NULL) 04413 ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar); 04414 } else { 04415 if (ctxt->sax->characters != NULL) 04416 ctxt->sax->characters(ctxt->userData, buf, nbchar); 04417 if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) && 04418 (*ctxt->space == -1)) 04419 *ctxt->space = -2; 04420 } 04421 } 04422 } 04423 if ((cur != 0) && (!IS_CHAR(cur))) { 04424 /* Generate the error and skip the offending character */ 04425 xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, 04426 "PCDATA invalid Char value %d\n", 04427 cur); 04428 NEXTL(l); 04429 } 04430 } 04431 04454 xmlChar * 04455 xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) { 04456 xmlChar *URI = NULL; 04457 04458 SHRINK; 04459 04460 *publicID = NULL; 04461 if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) { 04462 SKIP(6); 04463 if (!IS_BLANK_CH(CUR)) { 04464 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 04465 "Space required after 'SYSTEM'\n"); 04466 } 04467 SKIP_BLANKS; 04468 URI = xmlParseSystemLiteral(ctxt); 04469 if (URI == NULL) { 04470 xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL); 04471 } 04472 } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) { 04473 SKIP(6); 04474 if (!IS_BLANK_CH(CUR)) { 04475 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 04476 "Space required after 'PUBLIC'\n"); 04477 } 04478 SKIP_BLANKS; 04479 *publicID = xmlParsePubidLiteral(ctxt); 04480 if (*publicID == NULL) { 04481 xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL); 04482 } 04483 if (strict) { 04484 /* 04485 * We don't handle [83] so "S SystemLiteral" is required. 04486 */ 04487 if (!IS_BLANK_CH(CUR)) { 04488 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 04489 "Space required after the Public Identifier\n"); 04490 } 04491 } else { 04492 /* 04493 * We handle [83] so we return immediately, if 04494 * "S SystemLiteral" is not detected. From a purely parsing 04495 * point of view that's a nice mess. 04496 */ 04497 const xmlChar *ptr; 04498 GROW; 04499 04500 ptr = CUR_PTR; 04501 if (!IS_BLANK_CH(*ptr)) return(NULL); 04502 04503 while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */ 04504 if ((*ptr != '\'') && (*ptr != '"')) return(NULL); 04505 } 04506 SKIP_BLANKS; 04507 URI = xmlParseSystemLiteral(ctxt); 04508 if (URI == NULL) { 04509 xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL); 04510 } 04511 } 04512 return(URI); 04513 } 04514 04529 static void 04530 xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, int len, int size) { 04531 int q, ql; 04532 int r, rl; 04533 int cur, l; 04534 int count = 0; 04535 int inputid; 04536 04537 inputid = ctxt->input->id; 04538 04539 if (buf == NULL) { 04540 len = 0; 04541 size = XML_PARSER_BUFFER_SIZE; 04542 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 04543 if (buf == NULL) { 04544 xmlErrMemory(ctxt, NULL); 04545 return; 04546 } 04547 } 04548 GROW; /* Assure there's enough input data */ 04549 q = CUR_CHAR(ql); 04550 if (q == 0) 04551 goto not_terminated; 04552 if (!IS_CHAR(q)) { 04553 xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, 04554 "xmlParseComment: invalid xmlChar value %d\n", 04555 q); 04556 xmlFree (buf); 04557 return; 04558 } 04559 NEXTL(ql); 04560 r = CUR_CHAR(rl); 04561 if (r == 0) 04562 goto not_terminated; 04563 if (!IS_CHAR(r)) { 04564 xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, 04565 "xmlParseComment: invalid xmlChar value %d\n", 04566 q); 04567 xmlFree (buf); 04568 return; 04569 } 04570 NEXTL(rl); 04571 cur = CUR_CHAR(l); 04572 if (cur == 0) 04573 goto not_terminated; 04574 while (IS_CHAR(cur) && /* checked */ 04575 ((cur != '>') || 04576 (r != '-') || (q != '-'))) { 04577 if ((r == '-') && (q == '-')) { 04578 xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL); 04579 } 04580 if (len + 5 >= size) { 04581 xmlChar *new_buf; 04582 size *= 2; 04583 new_buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); 04584 if (new_buf == NULL) { 04585 xmlFree (buf); 04586 xmlErrMemory(ctxt, NULL); 04587 return; 04588 } 04589 buf = new_buf; 04590 } 04591 COPY_BUF(ql,buf,len,q); 04592 q = r; 04593 ql = rl; 04594 r = cur; 04595 rl = l; 04596 04597 count++; 04598 if (count > 50) { 04599 GROW; 04600 count = 0; 04601 } 04602 NEXTL(l); 04603 cur = CUR_CHAR(l); 04604 if (cur == 0) { 04605 SHRINK; 04606 GROW; 04607 cur = CUR_CHAR(l); 04608 } 04609 } 04610 buf[len] = 0; 04611 if (cur == 0) { 04612 xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, 04613 "Comment not terminated \n<!--%.50s\n", buf); 04614 } else if (!IS_CHAR(cur)) { 04615 xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, 04616 "xmlParseComment: invalid xmlChar value %d\n", 04617 cur); 04618 } else { 04619 if (inputid != ctxt->input->id) { 04620 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY, 04621 "Comment doesn't start and stop in the same entity\n"); 04622 } 04623 NEXT; 04624 if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) && 04625 (!ctxt->disableSAX)) 04626 ctxt->sax->comment(ctxt->userData, buf); 04627 } 04628 xmlFree(buf); 04629 return; 04630 not_terminated: 04631 xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, 04632 "Comment not terminated\n", NULL); 04633 xmlFree(buf); 04634 return; 04635 } 04636 04647 void 04648 xmlParseComment(xmlParserCtxtPtr ctxt) { 04649 xmlChar *buf = NULL; 04650 int size = XML_PARSER_BUFFER_SIZE; 04651 int len = 0; 04652 xmlParserInputState state; 04653 const xmlChar *in; 04654 int nbchar = 0, ccol; 04655 int inputid; 04656 04657 /* 04658 * Check that there is a comment right here. 04659 */ 04660 if ((RAW != '<') || (NXT(1) != '!') || 04661 (NXT(2) != '-') || (NXT(3) != '-')) return; 04662 state = ctxt->instate; 04663 ctxt->instate = XML_PARSER_COMMENT; 04664 inputid = ctxt->input->id; 04665 SKIP(4); 04666 SHRINK; 04667 GROW; 04668 04669 /* 04670 * Accelerated common case where input don't need to be 04671 * modified before passing it to the handler. 04672 */ 04673 in = ctxt->input->cur; 04674 do { 04675 if (*in == 0xA) { 04676 do { 04677 ctxt->input->line++; ctxt->input->col = 1; 04678 in++; 04679 } while (*in == 0xA); 04680 } 04681 get_more: 04682 ccol = ctxt->input->col; 04683 while (((*in > '-') && (*in <= 0x7F)) || 04684 ((*in >= 0x20) && (*in < '-')) || 04685 (*in == 0x09)) { 04686 in++; 04687 ccol++; 04688 } 04689 ctxt->input->col = ccol; 04690 if (*in == 0xA) { 04691 do { 04692 ctxt->input->line++; ctxt->input->col = 1; 04693 in++; 04694 } while (*in == 0xA); 04695 goto get_more; 04696 } 04697 nbchar = in - ctxt->input->cur; 04698 /* 04699 * save current set of data 04700 */ 04701 if (nbchar > 0) { 04702 if ((ctxt->sax != NULL) && 04703 (ctxt->sax->comment != NULL)) { 04704 if (buf == NULL) { 04705 if ((*in == '-') && (in[1] == '-')) 04706 size = nbchar + 1; 04707 else 04708 size = XML_PARSER_BUFFER_SIZE + nbchar; 04709 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 04710 if (buf == NULL) { 04711 xmlErrMemory(ctxt, NULL); 04712 ctxt->instate = state; 04713 return; 04714 } 04715 len = 0; 04716 } else if (len + nbchar + 1 >= size) { 04717 xmlChar *new_buf; 04718 size += len + nbchar + XML_PARSER_BUFFER_SIZE; 04719 new_buf = (xmlChar *) xmlRealloc(buf, 04720 size * sizeof(xmlChar)); 04721 if (new_buf == NULL) { 04722 xmlFree (buf); 04723 xmlErrMemory(ctxt, NULL); 04724 ctxt->instate = state; 04725 return; 04726 } 04727 buf = new_buf; 04728 } 04729 memcpy(&buf[len], ctxt->input->cur, nbchar); 04730 len += nbchar; 04731 buf[len] = 0; 04732 } 04733 } 04734 ctxt->input->cur = in; 04735 if (*in == 0xA) { 04736 in++; 04737 ctxt->input->line++; ctxt->input->col = 1; 04738 } 04739 if (*in == 0xD) { 04740 in++; 04741 if (*in == 0xA) { 04742 ctxt->input->cur = in; 04743 in++; 04744 ctxt->input->line++; ctxt->input->col = 1; 04745 continue; /* while */ 04746 } 04747 in--; 04748 } 04749 SHRINK; 04750 GROW; 04751 in = ctxt->input->cur; 04752 if (*in == '-') { 04753 if (in[1] == '-') { 04754 if (in[2] == '>') { 04755 if (ctxt->input->id != inputid) { 04756 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY, 04757 "comment doesn't start and stop in the same entity\n"); 04758 } 04759 SKIP(3); 04760 if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) && 04761 (!ctxt->disableSAX)) { 04762 if (buf != NULL) 04763 ctxt->sax->comment(ctxt->userData, buf); 04764 else 04765 ctxt->sax->comment(ctxt->userData, BAD_CAST ""); 04766 } 04767 if (buf != NULL) 04768 xmlFree(buf); 04769 ctxt->instate = state; 04770 return; 04771 } 04772 if (buf != NULL) 04773 xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, 04774 "Comment not terminated \n<!--%.50s\n", 04775 buf); 04776 else 04777 xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, 04778 "Comment not terminated \n", NULL); 04779 in++; 04780 ctxt->input->col++; 04781 } 04782 in++; 04783 ctxt->input->col++; 04784 goto get_more; 04785 } 04786 } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09)); 04787 xmlParseCommentComplex(ctxt, buf, len, size); 04788 ctxt->instate = state; 04789 return; 04790 } 04791 04792 04804 const xmlChar * 04805 xmlParsePITarget(xmlParserCtxtPtr ctxt) { 04806 const xmlChar *name; 04807 04808 name = xmlParseName(ctxt); 04809 if ((name != NULL) && 04810 ((name[0] == 'x') || (name[0] == 'X')) && 04811 ((name[1] == 'm') || (name[1] == 'M')) && 04812 ((name[2] == 'l') || (name[2] == 'L'))) { 04813 int i; 04814 if ((name[0] == 'x') && (name[1] == 'm') && 04815 (name[2] == 'l') && (name[3] == 0)) { 04816 xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME, 04817 "XML declaration allowed only at the start of the document\n"); 04818 return(name); 04819 } else if (name[3] == 0) { 04820 xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL); 04821 return(name); 04822 } 04823 for (i = 0;;i++) { 04824 if (xmlW3CPIs[i] == NULL) break; 04825 if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i])) 04826 return(name); 04827 } 04828 xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME, 04829 "xmlParsePITarget: invalid name prefix 'xml'\n", 04830 NULL, NULL); 04831 } 04832 if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) { 04833 xmlNsErr(ctxt, XML_NS_ERR_COLON, 04834 "colon are forbidden from PI names '%s'\n", name, NULL, NULL); 04835 } 04836 return(name); 04837 } 04838 04839 #ifdef LIBXML_CATALOG_ENABLED 04840 04855 static void 04856 xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) { 04857 xmlChar *URL = NULL; 04858 const xmlChar *tmp, *base; 04859 xmlChar marker; 04860 04861 tmp = catalog; 04862 while (IS_BLANK_CH(*tmp)) tmp++; 04863 if (xmlStrncmp(tmp, BAD_CAST"catalog", 7)) 04864 goto error; 04865 tmp += 7; 04866 while (IS_BLANK_CH(*tmp)) tmp++; 04867 if (*tmp != '=') { 04868 return; 04869 } 04870 tmp++; 04871 while (IS_BLANK_CH(*tmp)) tmp++; 04872 marker = *tmp; 04873 if ((marker != '\'') && (marker != '"')) 04874 goto error; 04875 tmp++; 04876 base = tmp; 04877 while ((*tmp != 0) && (*tmp != marker)) tmp++; 04878 if (*tmp == 0) 04879 goto error; 04880 URL = xmlStrndup(base, tmp - base); 04881 tmp++; 04882 while (IS_BLANK_CH(*tmp)) tmp++; 04883 if (*tmp != 0) 04884 goto error; 04885 04886 if (URL != NULL) { 04887 ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL); 04888 xmlFree(URL); 04889 } 04890 return; 04891 04892 error: 04893 xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI, 04894 "Catalog PI syntax error: %s\n", 04895 catalog, NULL); 04896 if (URL != NULL) 04897 xmlFree(URL); 04898 } 04899 #endif 04900 04912 void 04913 xmlParsePI(xmlParserCtxtPtr ctxt) { 04914 xmlChar *buf = NULL; 04915 int len = 0; 04916 int size = XML_PARSER_BUFFER_SIZE; 04917 int cur, l; 04918 const xmlChar *target; 04919 xmlParserInputState state; 04920 int count = 0; 04921 04922 if ((RAW == '<') && (NXT(1) == '?')) { 04923 xmlParserInputPtr input = ctxt->input; 04924 state = ctxt->instate; 04925 ctxt->instate = XML_PARSER_PI; 04926 /* 04927 * this is a Processing Instruction. 04928 */ 04929 SKIP(2); 04930 SHRINK; 04931 04932 /* 04933 * Parse the target name and check for special support like 04934 * namespace. 04935 */ 04936 target = xmlParsePITarget(ctxt); 04937 if (target != NULL) { 04938 if ((RAW == '?') && (NXT(1) == '>')) { 04939 if (input != ctxt->input) { 04940 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY, 04941 "PI declaration doesn't start and stop in the same entity\n"); 04942 } 04943 SKIP(2); 04944 04945 /* 04946 * SAX: PI detected. 04947 */ 04948 if ((ctxt->sax) && (!ctxt->disableSAX) && 04949 (ctxt->sax->processingInstruction != NULL)) 04950 ctxt->sax->processingInstruction(ctxt->userData, 04951 target, NULL); 04952 ctxt->instate = state; 04953 return; 04954 } 04955 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 04956 if (buf == NULL) { 04957 xmlErrMemory(ctxt, NULL); 04958 ctxt->instate = state; 04959 return; 04960 } 04961 cur = CUR; 04962 if (!IS_BLANK(cur)) { 04963 xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED, 04964 "ParsePI: PI %s space expected\n", target); 04965 } 04966 SKIP_BLANKS; 04967 cur = CUR_CHAR(l); 04968 while (IS_CHAR(cur) && /* checked */ 04969 ((cur != '?') || (NXT(1) != '>'))) { 04970 if (len + 5 >= size) { 04971 xmlChar *tmp; 04972 04973 size *= 2; 04974 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); 04975 if (tmp == NULL) { 04976 xmlErrMemory(ctxt, NULL); 04977 xmlFree(buf); 04978 ctxt->instate = state; 04979 return; 04980 } 04981 buf = tmp; 04982 } 04983 count++; 04984 if (count > 50) { 04985 GROW; 04986 count = 0; 04987 } 04988 COPY_BUF(l,buf,len,cur); 04989 NEXTL(l); 04990 cur = CUR_CHAR(l); 04991 if (cur == 0) { 04992 SHRINK; 04993 GROW; 04994 cur = CUR_CHAR(l); 04995 } 04996 } 04997 buf[len] = 0; 04998 if (cur != '?') { 04999 xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED, 05000 "ParsePI: PI %s never end ...\n", target); 05001 } else { 05002 if (input != ctxt->input) { 05003 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05004 "PI declaration doesn't start and stop in the same entity\n"); 05005 } 05006 SKIP(2); 05007 05008 #ifdef LIBXML_CATALOG_ENABLED 05009 if (((state == XML_PARSER_MISC) || 05010 (state == XML_PARSER_START)) && 05011 (xmlStrEqual(target, XML_CATALOG_PI))) { 05012 xmlCatalogAllow allow = xmlCatalogGetDefaults(); 05013 if ((allow == XML_CATA_ALLOW_DOCUMENT) || 05014 (allow == XML_CATA_ALLOW_ALL)) 05015 xmlParseCatalogPI(ctxt, buf); 05016 } 05017 #endif 05018 05019 05020 /* 05021 * SAX: PI detected. 05022 */ 05023 if ((ctxt->sax) && (!ctxt->disableSAX) && 05024 (ctxt->sax->processingInstruction != NULL)) 05025 ctxt->sax->processingInstruction(ctxt->userData, 05026 target, buf); 05027 } 05028 xmlFree(buf); 05029 } else { 05030 xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL); 05031 } 05032 ctxt->instate = state; 05033 } 05034 } 05035 05052 void 05053 xmlParseNotationDecl(xmlParserCtxtPtr ctxt) { 05054 const xmlChar *name; 05055 xmlChar *Pubid; 05056 xmlChar *Systemid; 05057 05058 if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) { 05059 xmlParserInputPtr input = ctxt->input; 05060 SHRINK; 05061 SKIP(10); 05062 if (!IS_BLANK_CH(CUR)) { 05063 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05064 "Space required after '<!NOTATION'\n"); 05065 return; 05066 } 05067 SKIP_BLANKS; 05068 05069 name = xmlParseName(ctxt); 05070 if (name == NULL) { 05071 xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL); 05072 return; 05073 } 05074 if (!IS_BLANK_CH(CUR)) { 05075 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05076 "Space required after the NOTATION name'\n"); 05077 return; 05078 } 05079 if (xmlStrchr(name, ':') != NULL) { 05080 xmlNsErr(ctxt, XML_NS_ERR_COLON, 05081 "colon are forbidden from notation names '%s'\n", 05082 name, NULL, NULL); 05083 } 05084 SKIP_BLANKS; 05085 05086 /* 05087 * Parse the IDs. 05088 */ 05089 Systemid = xmlParseExternalID(ctxt, &Pubid, 0); 05090 SKIP_BLANKS; 05091 05092 if (RAW == '>') { 05093 if (input != ctxt->input) { 05094 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05095 "Notation declaration doesn't start and stop in the same entity\n"); 05096 } 05097 NEXT; 05098 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && 05099 (ctxt->sax->notationDecl != NULL)) 05100 ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid); 05101 } else { 05102 xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL); 05103 } 05104 if (Systemid != NULL) xmlFree(Systemid); 05105 if (Pubid != NULL) xmlFree(Pubid); 05106 } 05107 } 05108 05131 void 05132 xmlParseEntityDecl(xmlParserCtxtPtr ctxt) { 05133 const xmlChar *name = NULL; 05134 xmlChar *value = NULL; 05135 xmlChar *URI = NULL, *literal = NULL; 05136 const xmlChar *ndata = NULL; 05137 int isParameter = 0; 05138 xmlChar *orig = NULL; 05139 int skipped; 05140 05141 /* GROW; done in the caller */ 05142 if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) { 05143 xmlParserInputPtr input = ctxt->input; 05144 SHRINK; 05145 SKIP(8); 05146 skipped = SKIP_BLANKS; 05147 if (skipped == 0) { 05148 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05149 "Space required after '<!ENTITY'\n"); 05150 } 05151 05152 if (RAW == '%') { 05153 NEXT; 05154 skipped = SKIP_BLANKS; 05155 if (skipped == 0) { 05156 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05157 "Space required after '%'\n"); 05158 } 05159 isParameter = 1; 05160 } 05161 05162 name = xmlParseName(ctxt); 05163 if (name == NULL) { 05164 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 05165 "xmlParseEntityDecl: no name\n"); 05166 return; 05167 } 05168 if (xmlStrchr(name, ':') != NULL) { 05169 xmlNsErr(ctxt, XML_NS_ERR_COLON, 05170 "colon are forbidden from entities names '%s'\n", 05171 name, NULL, NULL); 05172 } 05173 skipped = SKIP_BLANKS; 05174 if (skipped == 0) { 05175 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05176 "Space required after the entity name\n"); 05177 } 05178 05179 ctxt->instate = XML_PARSER_ENTITY_DECL; 05180 /* 05181 * handle the various case of definitions... 05182 */ 05183 if (isParameter) { 05184 if ((RAW == '"') || (RAW == '\'')) { 05185 value = xmlParseEntityValue(ctxt, &orig); 05186 if (value) { 05187 if ((ctxt->sax != NULL) && 05188 (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL)) 05189 ctxt->sax->entityDecl(ctxt->userData, name, 05190 XML_INTERNAL_PARAMETER_ENTITY, 05191 NULL, NULL, value); 05192 } 05193 } else { 05194 URI = xmlParseExternalID(ctxt, &literal, 1); 05195 if ((URI == NULL) && (literal == NULL)) { 05196 xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL); 05197 } 05198 if (URI) { 05199 xmlURIPtr uri; 05200 05201 uri = xmlParseURI((const char *) URI); 05202 if (uri == NULL) { 05203 xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI, 05204 "Invalid URI: %s\n", URI); 05205 /* 05206 * This really ought to be a well formedness error 05207 * but the XML Core WG decided otherwise c.f. issue 05208 * E26 of the XML erratas. 05209 */ 05210 } else { 05211 if (uri->fragment != NULL) { 05212 /* 05213 * Okay this is foolish to block those but not 05214 * invalid URIs. 05215 */ 05216 xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL); 05217 } else { 05218 if ((ctxt->sax != NULL) && 05219 (!ctxt->disableSAX) && 05220 (ctxt->sax->entityDecl != NULL)) 05221 ctxt->sax->entityDecl(ctxt->userData, name, 05222 XML_EXTERNAL_PARAMETER_ENTITY, 05223 literal, URI, NULL); 05224 } 05225 xmlFreeURI(uri); 05226 } 05227 } 05228 } 05229 } else { 05230 if ((RAW == '"') || (RAW == '\'')) { 05231 value = xmlParseEntityValue(ctxt, &orig); 05232 if ((ctxt->sax != NULL) && 05233 (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL)) 05234 ctxt->sax->entityDecl(ctxt->userData, name, 05235 XML_INTERNAL_GENERAL_ENTITY, 05236 NULL, NULL, value); 05237 /* 05238 * For expat compatibility in SAX mode. 05239 */ 05240 if ((ctxt->myDoc == NULL) || 05241 (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) { 05242 if (ctxt->myDoc == NULL) { 05243 ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE); 05244 if (ctxt->myDoc == NULL) { 05245 xmlErrMemory(ctxt, "New Doc failed"); 05246 return; 05247 } 05248 ctxt->myDoc->properties = XML_DOC_INTERNAL; 05249 } 05250 if (ctxt->myDoc->intSubset == NULL) 05251 ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc, 05252 BAD_CAST "fake", NULL, NULL); 05253 05254 xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY, 05255 NULL, NULL, value); 05256 } 05257 } else { 05258 URI = xmlParseExternalID(ctxt, &literal, 1); 05259 if ((URI == NULL) && (literal == NULL)) { 05260 xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL); 05261 } 05262 if (URI) { 05263 xmlURIPtr uri; 05264 05265 uri = xmlParseURI((const char *)URI); 05266 if (uri == NULL) { 05267 xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI, 05268 "Invalid URI: %s\n", URI); 05269 /* 05270 * This really ought to be a well formedness error 05271 * but the XML Core WG decided otherwise c.f. issue 05272 * E26 of the XML erratas. 05273 */ 05274 } else { 05275 if (uri->fragment != NULL) { 05276 /* 05277 * Okay this is foolish to block those but not 05278 * invalid URIs. 05279 */ 05280 xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL); 05281 } 05282 xmlFreeURI(uri); 05283 } 05284 } 05285 if ((RAW != '>') && (!IS_BLANK_CH(CUR))) { 05286 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05287 "Space required before 'NDATA'\n"); 05288 } 05289 SKIP_BLANKS; 05290 if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) { 05291 SKIP(5); 05292 if (!IS_BLANK_CH(CUR)) { 05293 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05294 "Space required after 'NDATA'\n"); 05295 } 05296 SKIP_BLANKS; 05297 ndata = xmlParseName(ctxt); 05298 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && 05299 (ctxt->sax->unparsedEntityDecl != NULL)) 05300 ctxt->sax->unparsedEntityDecl(ctxt->userData, name, 05301 literal, URI, ndata); 05302 } else { 05303 if ((ctxt->sax != NULL) && 05304 (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL)) 05305 ctxt->sax->entityDecl(ctxt->userData, name, 05306 XML_EXTERNAL_GENERAL_PARSED_ENTITY, 05307 literal, URI, NULL); 05308 /* 05309 * For expat compatibility in SAX mode. 05310 * assuming the entity repalcement was asked for 05311 */ 05312 if ((ctxt->replaceEntities != 0) && 05313 ((ctxt->myDoc == NULL) || 05314 (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) { 05315 if (ctxt->myDoc == NULL) { 05316 ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE); 05317 if (ctxt->myDoc == NULL) { 05318 xmlErrMemory(ctxt, "New Doc failed"); 05319 return; 05320 } 05321 ctxt->myDoc->properties = XML_DOC_INTERNAL; 05322 } 05323 05324 if (ctxt->myDoc->intSubset == NULL) 05325 ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc, 05326 BAD_CAST "fake", NULL, NULL); 05327 xmlSAX2EntityDecl(ctxt, name, 05328 XML_EXTERNAL_GENERAL_PARSED_ENTITY, 05329 literal, URI, NULL); 05330 } 05331 } 05332 } 05333 } 05334 SKIP_BLANKS; 05335 if (RAW != '>') { 05336 xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, 05337 "xmlParseEntityDecl: entity %s not terminated\n", name); 05338 } else { 05339 if (input != ctxt->input) { 05340 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY, 05341 "Entity declaration doesn't start and stop in the same entity\n"); 05342 } 05343 NEXT; 05344 } 05345 if (orig != NULL) { 05346 /* 05347 * Ugly mechanism to save the raw entity value. 05348 */ 05349 xmlEntityPtr cur = NULL; 05350 05351 if (isParameter) { 05352 if ((ctxt->sax != NULL) && 05353 (ctxt->sax->getParameterEntity != NULL)) 05354 cur = ctxt->sax->getParameterEntity(ctxt->userData, name); 05355 } else { 05356 if ((ctxt->sax != NULL) && 05357 (ctxt->sax->getEntity != NULL)) 05358 cur = ctxt->sax->getEntity(ctxt->userData, name); 05359 if ((cur == NULL) && (ctxt->userData==ctxt)) { 05360 cur = xmlSAX2GetEntity(ctxt, name); 05361 } 05362 } 05363 if (cur != NULL) { 05364 if (cur->orig != NULL) 05365 xmlFree(orig); 05366 else 05367 cur->orig = orig; 05368 } else 05369 xmlFree(orig); 05370 } 05371 if (value != NULL) xmlFree(value); 05372 if (URI != NULL) xmlFree(URI); 05373 if (literal != NULL) xmlFree(literal); 05374 } 05375 } 05376 05406 int 05407 xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) { 05408 int val; 05409 xmlChar *ret; 05410 05411 *value = NULL; 05412 if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) { 05413 SKIP(9); 05414 return(XML_ATTRIBUTE_REQUIRED); 05415 } 05416 if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) { 05417 SKIP(8); 05418 return(XML_ATTRIBUTE_IMPLIED); 05419 } 05420 val = XML_ATTRIBUTE_NONE; 05421 if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) { 05422 SKIP(6); 05423 val = XML_ATTRIBUTE_FIXED; 05424 if (!IS_BLANK_CH(CUR)) { 05425 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05426 "Space required after '#FIXED'\n"); 05427 } 05428 SKIP_BLANKS; 05429 } 05430 ret = xmlParseAttValue(ctxt); 05431 ctxt->instate = XML_PARSER_DTD; 05432 if (ret == NULL) { 05433 xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo, 05434 "Attribute default value declaration error\n"); 05435 } else 05436 *value = ret; 05437 return(val); 05438 } 05439 05457 xmlEnumerationPtr 05458 xmlParseNotationType(xmlParserCtxtPtr ctxt) { 05459 const xmlChar *name; 05460 xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp; 05461 05462 if (RAW != '(') { 05463 xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL); 05464 return(NULL); 05465 } 05466 SHRINK; 05467 do { 05468 NEXT; 05469 SKIP_BLANKS; 05470 name = xmlParseName(ctxt); 05471 if (name == NULL) { 05472 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 05473 "Name expected in NOTATION declaration\n"); 05474 xmlFreeEnumeration(ret); 05475 return(NULL); 05476 } 05477 tmp = ret; 05478 while (tmp != NULL) { 05479 if (xmlStrEqual(name, tmp->name)) { 05480 xmlValidityError(ctxt, XML_DTD_DUP_TOKEN, 05481 "standalone: attribute notation value token %s duplicated\n", 05482 name, NULL); 05483 if (!xmlDictOwns(ctxt->dict, name)) 05484 xmlFree((xmlChar *) name); 05485 break; 05486 } 05487 tmp = tmp->next; 05488 } 05489 if (tmp == NULL) { 05490 cur = xmlCreateEnumeration(name); 05491 if (cur == NULL) { 05492 xmlFreeEnumeration(ret); 05493 return(NULL); 05494 } 05495 if (last == NULL) ret = last = cur; 05496 else { 05497 last->next = cur; 05498 last = cur; 05499 } 05500 } 05501 SKIP_BLANKS; 05502 } while (RAW == '|'); 05503 if (RAW != ')') { 05504 xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL); 05505 xmlFreeEnumeration(ret); 05506 return(NULL); 05507 } 05508 NEXT; 05509 return(ret); 05510 } 05511 05527 xmlEnumerationPtr 05528 xmlParseEnumerationType(xmlParserCtxtPtr ctxt) { 05529 xmlChar *name; 05530 xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp; 05531 05532 if (RAW != '(') { 05533 xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL); 05534 return(NULL); 05535 } 05536 SHRINK; 05537 do { 05538 NEXT; 05539 SKIP_BLANKS; 05540 name = xmlParseNmtoken(ctxt); 05541 if (name == NULL) { 05542 xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL); 05543 return(ret); 05544 } 05545 tmp = ret; 05546 while (tmp != NULL) { 05547 if (xmlStrEqual(name, tmp->name)) { 05548 xmlValidityError(ctxt, XML_DTD_DUP_TOKEN, 05549 "standalone: attribute enumeration value token %s duplicated\n", 05550 name, NULL); 05551 if (!xmlDictOwns(ctxt->dict, name)) 05552 xmlFree(name); 05553 break; 05554 } 05555 tmp = tmp->next; 05556 } 05557 if (tmp == NULL) { 05558 cur = xmlCreateEnumeration(name); 05559 if (!xmlDictOwns(ctxt->dict, name)) 05560 xmlFree(name); 05561 if (cur == NULL) { 05562 xmlFreeEnumeration(ret); 05563 return(NULL); 05564 } 05565 if (last == NULL) ret = last = cur; 05566 else { 05567 last->next = cur; 05568 last = cur; 05569 } 05570 } 05571 SKIP_BLANKS; 05572 } while (RAW == '|'); 05573 if (RAW != ')') { 05574 xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL); 05575 return(ret); 05576 } 05577 NEXT; 05578 return(ret); 05579 } 05580 05596 int 05597 xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) { 05598 if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) { 05599 SKIP(8); 05600 if (!IS_BLANK_CH(CUR)) { 05601 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05602 "Space required after 'NOTATION'\n"); 05603 return(0); 05604 } 05605 SKIP_BLANKS; 05606 *tree = xmlParseNotationType(ctxt); 05607 if (*tree == NULL) return(0); 05608 return(XML_ATTRIBUTE_NOTATION); 05609 } 05610 *tree = xmlParseEnumerationType(ctxt); 05611 if (*tree == NULL) return(0); 05612 return(XML_ATTRIBUTE_ENUMERATION); 05613 } 05614 05660 int 05661 xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) { 05662 SHRINK; 05663 if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) { 05664 SKIP(5); 05665 return(XML_ATTRIBUTE_CDATA); 05666 } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) { 05667 SKIP(6); 05668 return(XML_ATTRIBUTE_IDREFS); 05669 } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) { 05670 SKIP(5); 05671 return(XML_ATTRIBUTE_IDREF); 05672 } else if ((RAW == 'I') && (NXT(1) == 'D')) { 05673 SKIP(2); 05674 return(XML_ATTRIBUTE_ID); 05675 } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) { 05676 SKIP(6); 05677 return(XML_ATTRIBUTE_ENTITY); 05678 } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) { 05679 SKIP(8); 05680 return(XML_ATTRIBUTE_ENTITIES); 05681 } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) { 05682 SKIP(8); 05683 return(XML_ATTRIBUTE_NMTOKENS); 05684 } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) { 05685 SKIP(7); 05686 return(XML_ATTRIBUTE_NMTOKEN); 05687 } 05688 return(xmlParseEnumeratedType(ctxt, tree)); 05689 } 05690 05702 void 05703 xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) { 05704 const xmlChar *elemName; 05705 const xmlChar *attrName; 05706 xmlEnumerationPtr tree; 05707 05708 if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) { 05709 xmlParserInputPtr input = ctxt->input; 05710 05711 SKIP(9); 05712 if (!IS_BLANK_CH(CUR)) { 05713 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05714 "Space required after '<!ATTLIST'\n"); 05715 } 05716 SKIP_BLANKS; 05717 elemName = xmlParseName(ctxt); 05718 if (elemName == NULL) { 05719 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 05720 "ATTLIST: no name for Element\n"); 05721 return; 05722 } 05723 SKIP_BLANKS; 05724 GROW; 05725 while (RAW != '>') { 05726 const xmlChar *check = CUR_PTR; 05727 int type; 05728 int def; 05729 xmlChar *defaultValue = NULL; 05730 05731 GROW; 05732 tree = NULL; 05733 attrName = xmlParseName(ctxt); 05734 if (attrName == NULL) { 05735 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 05736 "ATTLIST: no name for Attribute\n"); 05737 break; 05738 } 05739 GROW; 05740 if (!IS_BLANK_CH(CUR)) { 05741 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05742 "Space required after the attribute name\n"); 05743 break; 05744 } 05745 SKIP_BLANKS; 05746 05747 type = xmlParseAttributeType(ctxt, &tree); 05748 if (type <= 0) { 05749 break; 05750 } 05751 05752 GROW; 05753 if (!IS_BLANK_CH(CUR)) { 05754 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05755 "Space required after the attribute type\n"); 05756 if (tree != NULL) 05757 xmlFreeEnumeration(tree); 05758 break; 05759 } 05760 SKIP_BLANKS; 05761 05762 def = xmlParseDefaultDecl(ctxt, &defaultValue); 05763 if (def <= 0) { 05764 if (defaultValue != NULL) 05765 xmlFree(defaultValue); 05766 if (tree != NULL) 05767 xmlFreeEnumeration(tree); 05768 break; 05769 } 05770 if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL)) 05771 xmlAttrNormalizeSpace(defaultValue, defaultValue); 05772 05773 GROW; 05774 if (RAW != '>') { 05775 if (!IS_BLANK_CH(CUR)) { 05776 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 05777 "Space required after the attribute default value\n"); 05778 if (defaultValue != NULL) 05779 xmlFree(defaultValue); 05780 if (tree != NULL) 05781 xmlFreeEnumeration(tree); 05782 break; 05783 } 05784 SKIP_BLANKS; 05785 } 05786 if (check == CUR_PTR) { 05787 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, 05788 "in xmlParseAttributeListDecl\n"); 05789 if (defaultValue != NULL) 05790 xmlFree(defaultValue); 05791 if (tree != NULL) 05792 xmlFreeEnumeration(tree); 05793 break; 05794 } 05795 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && 05796 (ctxt->sax->attributeDecl != NULL)) 05797 ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName, 05798 type, def, defaultValue, tree); 05799 else if (tree != NULL) 05800 xmlFreeEnumeration(tree); 05801 05802 if ((ctxt->sax2) && (defaultValue != NULL) && 05803 (def != XML_ATTRIBUTE_IMPLIED) && 05804 (def != XML_ATTRIBUTE_REQUIRED)) { 05805 xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue); 05806 } 05807 if (ctxt->sax2) { 05808 xmlAddSpecialAttr(ctxt, elemName, attrName, type); 05809 } 05810 if (defaultValue != NULL) 05811 xmlFree(defaultValue); 05812 GROW; 05813 } 05814 if (RAW == '>') { 05815 if (input != ctxt->input) { 05816 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY, 05817 "Attribute list declaration doesn't start and stop in the same entity\n", 05818 NULL, NULL); 05819 } 05820 NEXT; 05821 } 05822 } 05823 } 05824 05844 xmlElementContentPtr 05845 xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) { 05846 xmlElementContentPtr ret = NULL, cur = NULL, n; 05847 const xmlChar *elem = NULL; 05848 05849 GROW; 05850 if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) { 05851 SKIP(7); 05852 SKIP_BLANKS; 05853 SHRINK; 05854 if (RAW == ')') { 05855 if ((ctxt->validate) && (ctxt->input->id != inputchk)) { 05856 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY, 05857 "Element content declaration doesn't start and stop in the same entity\n", 05858 NULL, NULL); 05859 } 05860 NEXT; 05861 ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA); 05862 if (ret == NULL) 05863 return(NULL); 05864 if (RAW == '*') { 05865 ret->ocur = XML_ELEMENT_CONTENT_MULT; 05866 NEXT; 05867 } 05868 return(ret); 05869 } 05870 if ((RAW == '(') || (RAW == '|')) { 05871 ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA); 05872 if (ret == NULL) return(NULL); 05873 } 05874 while (RAW == '|') { 05875 NEXT; 05876 if (elem == NULL) { 05877 ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR); 05878 if (ret == NULL) return(NULL); 05879 ret->c1 = cur; 05880 if (cur != NULL) 05881 cur->parent = ret; 05882 cur = ret; 05883 } else { 05884 n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR); 05885 if (n == NULL) return(NULL); 05886 n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT); 05887 if (n->c1 != NULL) 05888 n->c1->parent = n; 05889 cur->c2 = n; 05890 if (n != NULL) 05891 n->parent = cur; 05892 cur = n; 05893 } 05894 SKIP_BLANKS; 05895 elem = xmlParseName(ctxt); 05896 if (elem == NULL) { 05897 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 05898 "xmlParseElementMixedContentDecl : Name expected\n"); 05899 xmlFreeDocElementContent(ctxt->myDoc, cur); 05900 return(NULL); 05901 } 05902 SKIP_BLANKS; 05903 GROW; 05904 } 05905 if ((RAW == ')') && (NXT(1) == '*')) { 05906 if (elem != NULL) { 05907 cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem, 05908 XML_ELEMENT_CONTENT_ELEMENT); 05909 if (cur->c2 != NULL) 05910 cur->c2->parent = cur; 05911 } 05912 if (ret != NULL) 05913 ret->ocur = XML_ELEMENT_CONTENT_MULT; 05914 if ((ctxt->validate) && (ctxt->input->id != inputchk)) { 05915 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY, 05916 "Element content declaration doesn't start and stop in the same entity\n", 05917 NULL, NULL); 05918 } 05919 SKIP(2); 05920 } else { 05921 xmlFreeDocElementContent(ctxt->myDoc, ret); 05922 xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL); 05923 return(NULL); 05924 } 05925 05926 } else { 05927 xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL); 05928 } 05929 return(ret); 05930 } 05931 05964 static xmlElementContentPtr 05965 xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk, 05966 int depth) { 05967 xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL; 05968 const xmlChar *elem; 05969 xmlChar type = 0; 05970 05971 if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) || 05972 (depth > 2048)) { 05973 xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, 05974 "xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n", 05975 depth); 05976 return(NULL); 05977 } 05978 SKIP_BLANKS; 05979 GROW; 05980 if (RAW == '(') { 05981 int inputid = ctxt->input->id; 05982 05983 /* Recurse on first child */ 05984 NEXT; 05985 SKIP_BLANKS; 05986 cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 05987 depth + 1); 05988 SKIP_BLANKS; 05989 GROW; 05990 } else { 05991 elem = xmlParseName(ctxt); 05992 if (elem == NULL) { 05993 xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL); 05994 return(NULL); 05995 } 05996 cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT); 05997 if (cur == NULL) { 05998 xmlErrMemory(ctxt, NULL); 05999 return(NULL); 06000 } 06001 GROW; 06002 if (RAW == '?') { 06003 cur->ocur = XML_ELEMENT_CONTENT_OPT; 06004 NEXT; 06005 } else if (RAW == '*') { 06006 cur->ocur = XML_ELEMENT_CONTENT_MULT; 06007 NEXT; 06008 } else if (RAW == '+') { 06009 cur->ocur = XML_ELEMENT_CONTENT_PLUS; 06010 NEXT; 06011 } else { 06012 cur->ocur = XML_ELEMENT_CONTENT_ONCE; 06013 } 06014 GROW; 06015 } 06016 SKIP_BLANKS; 06017 SHRINK; 06018 while (RAW != ')') { 06019 /* 06020 * Each loop we parse one separator and one element. 06021 */ 06022 if (RAW == ',') { 06023 if (type == 0) type = CUR; 06024 06025 /* 06026 * Detect "Name | Name , Name" error 06027 */ 06028 else if (type != CUR) { 06029 xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED, 06030 "xmlParseElementChildrenContentDecl : '%c' expected\n", 06031 type); 06032 if ((last != NULL) && (last != ret)) 06033 xmlFreeDocElementContent(ctxt->myDoc, last); 06034 if (ret != NULL) 06035 xmlFreeDocElementContent(ctxt->myDoc, ret); 06036 return(NULL); 06037 } 06038 NEXT; 06039 06040 op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ); 06041 if (op == NULL) { 06042 if ((last != NULL) && (last != ret)) 06043 xmlFreeDocElementContent(ctxt->myDoc, last); 06044 xmlFreeDocElementContent(ctxt->myDoc, ret); 06045 return(NULL); 06046 } 06047 if (last == NULL) { 06048 op->c1 = ret; 06049 if (ret != NULL) 06050 ret->parent = op; 06051 ret = cur = op; 06052 } else { 06053 cur->c2 = op; 06054 if (op != NULL) 06055 op->parent = cur; 06056 op->c1 = last; 06057 if (last != NULL) 06058 last->parent = op; 06059 cur =op; 06060 last = NULL; 06061 } 06062 } else if (RAW == '|') { 06063 if (type == 0) type = CUR; 06064 06065 /* 06066 * Detect "Name , Name | Name" error 06067 */ 06068 else if (type != CUR) { 06069 xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED, 06070 "xmlParseElementChildrenContentDecl : '%c' expected\n", 06071 type); 06072 if ((last != NULL) && (last != ret)) 06073 xmlFreeDocElementContent(ctxt->myDoc, last); 06074 if (ret != NULL) 06075 xmlFreeDocElementContent(ctxt->myDoc, ret); 06076 return(NULL); 06077 } 06078 NEXT; 06079 06080 op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR); 06081 if (op == NULL) { 06082 if ((last != NULL) && (last != ret)) 06083 xmlFreeDocElementContent(ctxt->myDoc, last); 06084 if (ret != NULL) 06085 xmlFreeDocElementContent(ctxt->myDoc, ret); 06086 return(NULL); 06087 } 06088 if (last == NULL) { 06089 op->c1 = ret; 06090 if (ret != NULL) 06091 ret->parent = op; 06092 ret = cur = op; 06093 } else { 06094 cur->c2 = op; 06095 if (op != NULL) 06096 op->parent = cur; 06097 op->c1 = last; 06098 if (last != NULL) 06099 last->parent = op; 06100 cur =op; 06101 last = NULL; 06102 } 06103 } else { 06104 xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL); 06105 if ((last != NULL) && (last != ret)) 06106 xmlFreeDocElementContent(ctxt->myDoc, last); 06107 if (ret != NULL) 06108 xmlFreeDocElementContent(ctxt->myDoc, ret); 06109 return(NULL); 06110 } 06111 GROW; 06112 SKIP_BLANKS; 06113 GROW; 06114 if (RAW == '(') { 06115 int inputid = ctxt->input->id; 06116 /* Recurse on second child */ 06117 NEXT; 06118 SKIP_BLANKS; 06119 last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 06120 depth + 1); 06121 SKIP_BLANKS; 06122 } else { 06123 elem = xmlParseName(ctxt); 06124 if (elem == NULL) { 06125 xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL); 06126 if (ret != NULL) 06127 xmlFreeDocElementContent(ctxt->myDoc, ret); 06128 return(NULL); 06129 } 06130 last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT); 06131 if (last == NULL) { 06132 if (ret != NULL) 06133 xmlFreeDocElementContent(ctxt->myDoc, ret); 06134 return(NULL); 06135 } 06136 if (RAW == '?') { 06137 last->ocur = XML_ELEMENT_CONTENT_OPT; 06138 NEXT; 06139 } else if (RAW == '*') { 06140 last->ocur = XML_ELEMENT_CONTENT_MULT; 06141 NEXT; 06142 } else if (RAW == '+') { 06143 last->ocur = XML_ELEMENT_CONTENT_PLUS; 06144 NEXT; 06145 } else { 06146 last->ocur = XML_ELEMENT_CONTENT_ONCE; 06147 } 06148 } 06149 SKIP_BLANKS; 06150 GROW; 06151 } 06152 if ((cur != NULL) && (last != NULL)) { 06153 cur->c2 = last; 06154 if (last != NULL) 06155 last->parent = cur; 06156 } 06157 if ((ctxt->validate) && (ctxt->input->id != inputchk)) { 06158 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY, 06159 "Element content declaration doesn't start and stop in the same entity\n", 06160 NULL, NULL); 06161 } 06162 NEXT; 06163 if (RAW == '?') { 06164 if (ret != NULL) { 06165 if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) || 06166 (ret->ocur == XML_ELEMENT_CONTENT_MULT)) 06167 ret->ocur = XML_ELEMENT_CONTENT_MULT; 06168 else 06169 ret->ocur = XML_ELEMENT_CONTENT_OPT; 06170 } 06171 NEXT; 06172 } else if (RAW == '*') { 06173 if (ret != NULL) { 06174 ret->ocur = XML_ELEMENT_CONTENT_MULT; 06175 cur = ret; 06176 /* 06177 * Some normalization: 06178 * (a | b* | c?)* == (a | b | c)* 06179 */ 06180 while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) { 06181 if ((cur->c1 != NULL) && 06182 ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) || 06183 (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) 06184 cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE; 06185 if ((cur->c2 != NULL) && 06186 ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) || 06187 (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) 06188 cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE; 06189 cur = cur->c2; 06190 } 06191 } 06192 NEXT; 06193 } else if (RAW == '+') { 06194 if (ret != NULL) { 06195 int found = 0; 06196 06197 if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) || 06198 (ret->ocur == XML_ELEMENT_CONTENT_MULT)) 06199 ret->ocur = XML_ELEMENT_CONTENT_MULT; 06200 else 06201 ret->ocur = XML_ELEMENT_CONTENT_PLUS; 06202 /* 06203 * Some normalization: 06204 * (a | b*)+ == (a | b)* 06205 * (a | b?)+ == (a | b)* 06206 */ 06207 while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) { 06208 if ((cur->c1 != NULL) && 06209 ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) || 06210 (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) { 06211 cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE; 06212 found = 1; 06213 } 06214 if ((cur->c2 != NULL) && 06215 ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) || 06216 (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) { 06217 cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE; 06218 found = 1; 06219 } 06220 cur = cur->c2; 06221 } 06222 if (found) 06223 ret->ocur = XML_ELEMENT_CONTENT_MULT; 06224 } 06225 NEXT; 06226 } 06227 return(ret); 06228 } 06229 06260 xmlElementContentPtr 06261 xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) { 06262 /* stub left for API/ABI compat */ 06263 return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1)); 06264 } 06265 06280 int 06281 xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name, 06282 xmlElementContentPtr *result) { 06283 06284 xmlElementContentPtr tree = NULL; 06285 int inputid = ctxt->input->id; 06286 int res; 06287 06288 *result = NULL; 06289 06290 if (RAW != '(') { 06291 xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, 06292 "xmlParseElementContentDecl : %s '(' expected\n", name); 06293 return(-1); 06294 } 06295 NEXT; 06296 GROW; 06297 SKIP_BLANKS; 06298 if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) { 06299 tree = xmlParseElementMixedContentDecl(ctxt, inputid); 06300 res = XML_ELEMENT_TYPE_MIXED; 06301 } else { 06302 tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1); 06303 res = XML_ELEMENT_TYPE_ELEMENT; 06304 } 06305 SKIP_BLANKS; 06306 *result = tree; 06307 return(res); 06308 } 06309 06323 int 06324 xmlParseElementDecl(xmlParserCtxtPtr ctxt) { 06325 const xmlChar *name; 06326 int ret = -1; 06327 xmlElementContentPtr content = NULL; 06328 06329 /* GROW; done in the caller */ 06330 if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) { 06331 xmlParserInputPtr input = ctxt->input; 06332 06333 SKIP(9); 06334 if (!IS_BLANK_CH(CUR)) { 06335 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 06336 "Space required after 'ELEMENT'\n"); 06337 } 06338 SKIP_BLANKS; 06339 name = xmlParseName(ctxt); 06340 if (name == NULL) { 06341 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 06342 "xmlParseElementDecl: no name for Element\n"); 06343 return(-1); 06344 } 06345 while ((RAW == 0) && (ctxt->inputNr > 1)) 06346 xmlPopInput(ctxt); 06347 if (!IS_BLANK_CH(CUR)) { 06348 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 06349 "Space required after the element name\n"); 06350 } 06351 SKIP_BLANKS; 06352 if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) { 06353 SKIP(5); 06354 /* 06355 * Element must always be empty. 06356 */ 06357 ret = XML_ELEMENT_TYPE_EMPTY; 06358 } else if ((RAW == 'A') && (NXT(1) == 'N') && 06359 (NXT(2) == 'Y')) { 06360 SKIP(3); 06361 /* 06362 * Element is a generic container. 06363 */ 06364 ret = XML_ELEMENT_TYPE_ANY; 06365 } else if (RAW == '(') { 06366 ret = xmlParseElementContentDecl(ctxt, name, &content); 06367 } else { 06368 /* 06369 * [ WFC: PEs in Internal Subset ] error handling. 06370 */ 06371 if ((RAW == '%') && (ctxt->external == 0) && 06372 (ctxt->inputNr == 1)) { 06373 xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET, 06374 "PEReference: forbidden within markup decl in internal subset\n"); 06375 } else { 06376 xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, 06377 "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n"); 06378 } 06379 return(-1); 06380 } 06381 06382 SKIP_BLANKS; 06383 /* 06384 * Pop-up of finished entities. 06385 */ 06386 while ((RAW == 0) && (ctxt->inputNr > 1)) 06387 xmlPopInput(ctxt); 06388 SKIP_BLANKS; 06389 06390 if (RAW != '>') { 06391 xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL); 06392 if (content != NULL) { 06393 xmlFreeDocElementContent(ctxt->myDoc, content); 06394 } 06395 } else { 06396 if (input != ctxt->input) { 06397 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY, 06398 "Element declaration doesn't start and stop in the same entity\n"); 06399 } 06400 06401 NEXT; 06402 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && 06403 (ctxt->sax->elementDecl != NULL)) { 06404 if (content != NULL) 06405 content->parent = NULL; 06406 ctxt->sax->elementDecl(ctxt->userData, name, ret, 06407 content); 06408 if ((content != NULL) && (content->parent == NULL)) { 06409 /* 06410 * this is a trick: if xmlAddElementDecl is called, 06411 * instead of copying the full tree it is plugged directly 06412 * if called from the parser. Avoid duplicating the 06413 * interfaces or change the API/ABI 06414 */ 06415 xmlFreeDocElementContent(ctxt->myDoc, content); 06416 } 06417 } else if (content != NULL) { 06418 xmlFreeDocElementContent(ctxt->myDoc, content); 06419 } 06420 } 06421 } 06422 return(ret); 06423 } 06424 06436 static void 06437 xmlParseConditionalSections(xmlParserCtxtPtr ctxt) { 06438 int id = ctxt->input->id; 06439 06440 SKIP(3); 06441 SKIP_BLANKS; 06442 if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) { 06443 SKIP(7); 06444 SKIP_BLANKS; 06445 if (RAW != '[') { 06446 xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL); 06447 } else { 06448 if (ctxt->input->id != id) { 06449 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY, 06450 "All markup of the conditional section is not in the same entity\n", 06451 NULL, NULL); 06452 } 06453 NEXT; 06454 } 06455 if (xmlParserDebugEntities) { 06456 if ((ctxt->input != NULL) && (ctxt->input->filename)) 06457 xmlGenericError(xmlGenericErrorContext, 06458 "%s(%d): ", ctxt->input->filename, 06459 ctxt->input->line); 06460 xmlGenericError(xmlGenericErrorContext, 06461 "Entering INCLUDE Conditional Section\n"); 06462 } 06463 06464 while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') || 06465 (NXT(2) != '>'))) { 06466 const xmlChar *check = CUR_PTR; 06467 unsigned int cons = ctxt->input->consumed; 06468 06469 if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) { 06470 xmlParseConditionalSections(ctxt); 06471 } else if (IS_BLANK_CH(CUR)) { 06472 NEXT; 06473 } else if (RAW == '%') { 06474 xmlParsePEReference(ctxt); 06475 } else 06476 xmlParseMarkupDecl(ctxt); 06477 06478 /* 06479 * Pop-up of finished entities. 06480 */ 06481 while ((RAW == 0) && (ctxt->inputNr > 1)) 06482 xmlPopInput(ctxt); 06483 06484 if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) { 06485 xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL); 06486 break; 06487 } 06488 } 06489 if (xmlParserDebugEntities) { 06490 if ((ctxt->input != NULL) && (ctxt->input->filename)) 06491 xmlGenericError(xmlGenericErrorContext, 06492 "%s(%d): ", ctxt->input->filename, 06493 ctxt->input->line); 06494 xmlGenericError(xmlGenericErrorContext, 06495 "Leaving INCLUDE Conditional Section\n"); 06496 } 06497 06498 } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) { 06499 int state; 06500 xmlParserInputState instate; 06501 int depth = 0; 06502 06503 SKIP(6); 06504 SKIP_BLANKS; 06505 if (RAW != '[') { 06506 xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL); 06507 } else { 06508 if (ctxt->input->id != id) { 06509 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY, 06510 "All markup of the conditional section is not in the same entity\n", 06511 NULL, NULL); 06512 } 06513 NEXT; 06514 } 06515 if (xmlParserDebugEntities) { 06516 if ((ctxt->input != NULL) && (ctxt->input->filename)) 06517 xmlGenericError(xmlGenericErrorContext, 06518 "%s(%d): ", ctxt->input->filename, 06519 ctxt->input->line); 06520 xmlGenericError(xmlGenericErrorContext, 06521 "Entering IGNORE Conditional Section\n"); 06522 } 06523 06524 /* 06525 * Parse up to the end of the conditional section 06526 * But disable SAX event generating DTD building in the meantime 06527 */ 06528 state = ctxt->disableSAX; 06529 instate = ctxt->instate; 06530 if (ctxt->recovery == 0) ctxt->disableSAX = 1; 06531 ctxt->instate = XML_PARSER_IGNORE; 06532 06533 while ((depth >= 0) && (RAW != 0)) { 06534 if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) { 06535 depth++; 06536 SKIP(3); 06537 continue; 06538 } 06539 if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) { 06540 if (--depth >= 0) SKIP(3); 06541 continue; 06542 } 06543 NEXT; 06544 continue; 06545 } 06546 06547 ctxt->disableSAX = state; 06548 ctxt->instate = instate; 06549 06550 if (xmlParserDebugEntities) { 06551 if ((ctxt->input != NULL) && (ctxt->input->filename)) 06552 xmlGenericError(xmlGenericErrorContext, 06553 "%s(%d): ", ctxt->input->filename, 06554 ctxt->input->line); 06555 xmlGenericError(xmlGenericErrorContext, 06556 "Leaving IGNORE Conditional Section\n"); 06557 } 06558 06559 } else { 06560 xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL); 06561 } 06562 06563 if (RAW == 0) 06564 SHRINK; 06565 06566 if (RAW == 0) { 06567 xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL); 06568 } else { 06569 if (ctxt->input->id != id) { 06570 xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY, 06571 "All markup of the conditional section is not in the same entity\n", 06572 NULL, NULL); 06573 } 06574 SKIP(3); 06575 } 06576 } 06577 06600 void 06601 xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) { 06602 GROW; 06603 if (CUR == '<') { 06604 if (NXT(1) == '!') { 06605 switch (NXT(2)) { 06606 case 'E': 06607 if (NXT(3) == 'L') 06608 xmlParseElementDecl(ctxt); 06609 else if (NXT(3) == 'N') 06610 xmlParseEntityDecl(ctxt); 06611 break; 06612 case 'A': 06613 xmlParseAttributeListDecl(ctxt); 06614 break; 06615 case 'N': 06616 xmlParseNotationDecl(ctxt); 06617 break; 06618 case '-': 06619 xmlParseComment(ctxt); 06620 break; 06621 default: 06622 /* there is an error but it will be detected later */ 06623 break; 06624 } 06625 } else if (NXT(1) == '?') { 06626 xmlParsePI(ctxt); 06627 } 06628 } 06629 /* 06630 * This is only for internal subset. On external entities, 06631 * the replacement is done before parsing stage 06632 */ 06633 if ((ctxt->external == 0) && (ctxt->inputNr == 1)) 06634 xmlParsePEReference(ctxt); 06635 06636 /* 06637 * Conditional sections are allowed from entities included 06638 * by PE References in the internal subset. 06639 */ 06640 if ((ctxt->external == 0) && (ctxt->inputNr > 1)) { 06641 if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) { 06642 xmlParseConditionalSections(ctxt); 06643 } 06644 } 06645 06646 ctxt->instate = XML_PARSER_DTD; 06647 } 06648 06658 void 06659 xmlParseTextDecl(xmlParserCtxtPtr ctxt) { 06660 xmlChar *version; 06661 const xmlChar *encoding; 06662 06663 /* 06664 * We know that '<?xml' is here. 06665 */ 06666 if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) { 06667 SKIP(5); 06668 } else { 06669 xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL); 06670 return; 06671 } 06672 06673 if (!IS_BLANK_CH(CUR)) { 06674 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 06675 "Space needed after '<?xml'\n"); 06676 } 06677 SKIP_BLANKS; 06678 06679 /* 06680 * We may have the VersionInfo here. 06681 */ 06682 version = xmlParseVersionInfo(ctxt); 06683 if (version == NULL) 06684 version = xmlCharStrdup(XML_DEFAULT_VERSION); 06685 else { 06686 if (!IS_BLANK_CH(CUR)) { 06687 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 06688 "Space needed here\n"); 06689 } 06690 } 06691 ctxt->input->version = version; 06692 06693 /* 06694 * We must have the encoding declaration 06695 */ 06696 encoding = xmlParseEncodingDecl(ctxt); 06697 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) { 06698 /* 06699 * The XML REC instructs us to stop parsing right here 06700 */ 06701 return; 06702 } 06703 if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) { 06704 xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING, 06705 "Missing encoding in text declaration\n"); 06706 } 06707 06708 SKIP_BLANKS; 06709 if ((RAW == '?') && (NXT(1) == '>')) { 06710 SKIP(2); 06711 } else if (RAW == '>') { 06712 /* Deprecated old WD ... */ 06713 xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL); 06714 NEXT; 06715 } else { 06716 xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL); 06717 MOVETO_ENDTAG(CUR_PTR); 06718 NEXT; 06719 } 06720 } 06721 06734 void 06735 xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID, 06736 const xmlChar *SystemID) { 06737 xmlDetectSAX2(ctxt); 06738 GROW; 06739 06740 if ((ctxt->encoding == NULL) && 06741 (ctxt->input->end - ctxt->input->cur >= 4)) { 06742 xmlChar start[4]; 06743 xmlCharEncoding enc; 06744 06745 start[0] = RAW; 06746 start[1] = NXT(1); 06747 start[2] = NXT(2); 06748 start[3] = NXT(3); 06749 enc = xmlDetectCharEncoding(start, 4); 06750 if (enc != XML_CHAR_ENCODING_NONE) 06751 xmlSwitchEncoding(ctxt, enc); 06752 } 06753 06754 if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) { 06755 xmlParseTextDecl(ctxt); 06756 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) { 06757 /* 06758 * The XML REC instructs us to stop parsing right here 06759 */ 06760 ctxt->instate = XML_PARSER_EOF; 06761 return; 06762 } 06763 } 06764 if (ctxt->myDoc == NULL) { 06765 ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0"); 06766 if (ctxt->myDoc == NULL) { 06767 xmlErrMemory(ctxt, "New Doc failed"); 06768 return; 06769 } 06770 ctxt->myDoc->properties = XML_DOC_INTERNAL; 06771 } 06772 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL)) 06773 xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID); 06774 06775 ctxt->instate = XML_PARSER_DTD; 06776 ctxt->external = 1; 06777 while (((RAW == '<') && (NXT(1) == '?')) || 06778 ((RAW == '<') && (NXT(1) == '!')) || 06779 (RAW == '%') || IS_BLANK_CH(CUR)) { 06780 const xmlChar *check = CUR_PTR; 06781 unsigned int cons = ctxt->input->consumed; 06782 06783 GROW; 06784 if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) { 06785 xmlParseConditionalSections(ctxt); 06786 } else if (IS_BLANK_CH(CUR)) { 06787 NEXT; 06788 } else if (RAW == '%') { 06789 xmlParsePEReference(ctxt); 06790 } else 06791 xmlParseMarkupDecl(ctxt); 06792 06793 /* 06794 * Pop-up of finished entities. 06795 */ 06796 while ((RAW == 0) && (ctxt->inputNr > 1)) 06797 xmlPopInput(ctxt); 06798 06799 if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) { 06800 xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL); 06801 break; 06802 } 06803 } 06804 06805 if (RAW != 0) { 06806 xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL); 06807 } 06808 06809 } 06810 06822 void 06823 xmlParseReference(xmlParserCtxtPtr ctxt) { 06824 xmlEntityPtr ent; 06825 xmlChar *val; 06826 int was_checked; 06827 xmlNodePtr list = NULL; 06828 xmlParserErrors ret = XML_ERR_OK; 06829 06830 06831 if (RAW != '&') 06832 return; 06833 06834 /* 06835 * Simple case of a CharRef 06836 */ 06837 if (NXT(1) == '#') { 06838 int i = 0; 06839 xmlChar out[10]; 06840 int hex = NXT(2); 06841 int value = xmlParseCharRef(ctxt); 06842 06843 if (value == 0) 06844 return; 06845 if (ctxt->charset != XML_CHAR_ENCODING_UTF8) { 06846 /* 06847 * So we are using non-UTF-8 buffers 06848 * Check that the char fit on 8bits, if not 06849 * generate a CharRef. 06850 */ 06851 if (value <= 0xFF) { 06852 out[0] = value; 06853 out[1] = 0; 06854 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) && 06855 (!ctxt->disableSAX)) 06856 ctxt->sax->characters(ctxt->userData, out, 1); 06857 } else { 06858 if ((hex == 'x') || (hex == 'X')) 06859 snprintf((char *)out, sizeof(out), "#x%X", value); 06860 else 06861 snprintf((char *)out, sizeof(out), "#%d", value); 06862 if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) && 06863 (!ctxt->disableSAX)) 06864 ctxt->sax->reference(ctxt->userData, out); 06865 } 06866 } else { 06867 /* 06868 * Just encode the value in UTF-8 06869 */ 06870 COPY_BUF(0 ,out, i, value); 06871 out[i] = 0; 06872 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) && 06873 (!ctxt->disableSAX)) 06874 ctxt->sax->characters(ctxt->userData, out, i); 06875 } 06876 return; 06877 } 06878 06879 /* 06880 * We are seeing an entity reference 06881 */ 06882 ent = xmlParseEntityRef(ctxt); 06883 if (ent == NULL) return; 06884 if (!ctxt->wellFormed) 06885 return; 06886 was_checked = ent->checked; 06887 06888 /* special case of predefined entities */ 06889 if ((ent->name == NULL) || 06890 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { 06891 val = ent->content; 06892 if (val == NULL) return; 06893 /* 06894 * inline the entity. 06895 */ 06896 if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) && 06897 (!ctxt->disableSAX)) 06898 ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val)); 06899 return; 06900 } 06901 06902 /* 06903 * The first reference to the entity trigger a parsing phase 06904 * where the ent->children is filled with the result from 06905 * the parsing. 06906 */ 06907 if (ent->checked == 0) { 06908 unsigned long oldnbent = ctxt->nbentities; 06909 06910 /* 06911 * This is a bit hackish but this seems the best 06912 * way to make sure both SAX and DOM entity support 06913 * behaves okay. 06914 */ 06915 void *user_data; 06916 if (ctxt->userData == ctxt) 06917 user_data = NULL; 06918 else 06919 user_data = ctxt->userData; 06920 06921 /* 06922 * Check that this entity is well formed 06923 * 4.3.2: An internal general parsed entity is well-formed 06924 * if its replacement text matches the production labeled 06925 * content. 06926 */ 06927 if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) { 06928 ctxt->depth++; 06929 ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content, 06930 user_data, &list); 06931 ctxt->depth--; 06932 06933 } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) { 06934 ctxt->depth++; 06935 ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax, 06936 user_data, ctxt->depth, ent->URI, 06937 ent->ExternalID, &list); 06938 ctxt->depth--; 06939 } else { 06940 ret = XML_ERR_ENTITY_PE_INTERNAL; 06941 xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR, 06942 "invalid entity type found\n", NULL); 06943 } 06944 06945 /* 06946 * Store the number of entities needing parsing for this entity 06947 * content and do checkings 06948 */ 06949 ent->checked = ctxt->nbentities - oldnbent; 06950 if (ret == XML_ERR_ENTITY_LOOP) { 06951 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); 06952 xmlFreeNodeList(list); 06953 return; 06954 } 06955 if (xmlParserEntityCheck(ctxt, 0, ent)) { 06956 xmlFreeNodeList(list); 06957 return; 06958 } 06959 06960 if ((ret == XML_ERR_OK) && (list != NULL)) { 06961 if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) || 06962 (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&& 06963 (ent->children == NULL)) { 06964 ent->children = list; 06965 if (ctxt->replaceEntities) { 06966 /* 06967 * Prune it directly in the generated document 06968 * except for single text nodes. 06969 */ 06970 if (((list->type == XML_TEXT_NODE) && 06971 (list->next == NULL)) || 06972 (ctxt->parseMode == XML_PARSE_READER)) { 06973 list->parent = (xmlNodePtr) ent; 06974 list = NULL; 06975 ent->owner = 1; 06976 } else { 06977 ent->owner = 0; 06978 while (list != NULL) { 06979 list->parent = (xmlNodePtr) ctxt->node; 06980 list->doc = ctxt->myDoc; 06981 if (list->next == NULL) 06982 ent->last = list; 06983 list = list->next; 06984 } 06985 list = ent->children; 06986 #ifdef LIBXML_LEGACY_ENABLED 06987 if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) 06988 xmlAddEntityReference(ent, list, NULL); 06989 #endif /* LIBXML_LEGACY_ENABLED */ 06990 } 06991 } else { 06992 ent->owner = 1; 06993 while (list != NULL) { 06994 list->parent = (xmlNodePtr) ent; 06995 if (list->next == NULL) 06996 ent->last = list; 06997 list = list->next; 06998 } 06999 } 07000 } else { 07001 xmlFreeNodeList(list); 07002 list = NULL; 07003 } 07004 } else if ((ret != XML_ERR_OK) && 07005 (ret != XML_WAR_UNDECLARED_ENTITY)) { 07006 xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY, 07007 "Entity '%s' failed to parse\n", ent->name); 07008 } else if (list != NULL) { 07009 xmlFreeNodeList(list); 07010 list = NULL; 07011 } 07012 if (ent->checked == 0) 07013 ent->checked = 1; 07014 } else if (ent->checked != 1) { 07015 ctxt->nbentities += ent->checked; 07016 } 07017 07018 /* 07019 * Now that the entity content has been gathered 07020 * provide it to the application, this can take different forms based 07021 * on the parsing modes. 07022 */ 07023 if (ent->children == NULL) { 07024 /* 07025 * Probably running in SAX mode and the callbacks don't 07026 * build the entity content. So unless we already went 07027 * though parsing for first checking go though the entity 07028 * content to generate callbacks associated to the entity 07029 */ 07030 if (was_checked != 0) { 07031 void *user_data; 07032 /* 07033 * This is a bit hackish but this seems the best 07034 * way to make sure both SAX and DOM entity support 07035 * behaves okay. 07036 */ 07037 if (ctxt->userData == ctxt) 07038 user_data = NULL; 07039 else 07040 user_data = ctxt->userData; 07041 07042 if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) { 07043 ctxt->depth++; 07044 ret = xmlParseBalancedChunkMemoryInternal(ctxt, 07045 ent->content, user_data, NULL); 07046 ctxt->depth--; 07047 } else if (ent->etype == 07048 XML_EXTERNAL_GENERAL_PARSED_ENTITY) { 07049 ctxt->depth++; 07050 ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, 07051 ctxt->sax, user_data, ctxt->depth, 07052 ent->URI, ent->ExternalID, NULL); 07053 ctxt->depth--; 07054 } else { 07055 ret = XML_ERR_ENTITY_PE_INTERNAL; 07056 xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR, 07057 "invalid entity type found\n", NULL); 07058 } 07059 if (ret == XML_ERR_ENTITY_LOOP) { 07060 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); 07061 return; 07062 } 07063 } 07064 if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) && 07065 (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) { 07066 /* 07067 * Entity reference callback comes second, it's somewhat 07068 * superfluous but a compatibility to historical behaviour 07069 */ 07070 ctxt->sax->reference(ctxt->userData, ent->name); 07071 } 07072 return; 07073 } 07074 07075 /* 07076 * If we didn't get any children for the entity being built 07077 */ 07078 if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) && 07079 (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) { 07080 /* 07081 * Create a node. 07082 */ 07083 ctxt->sax->reference(ctxt->userData, ent->name); 07084 return; 07085 } 07086 07087 if ((ctxt->replaceEntities) || (ent->children == NULL)) { 07088 /* 07089 * There is a problem on the handling of _private for entities 07090 * (bug 155816): Should we copy the content of the field from 07091 * the entity (possibly overwriting some value set by the user 07092 * when a copy is created), should we leave it alone, or should 07093 * we try to take care of different situations? The problem 07094 * is exacerbated by the usage of this field by the xmlReader. 07095 * To fix this bug, we look at _private on the created node 07096 * and, if it's NULL, we copy in whatever was in the entity. 07097 * If it's not NULL we leave it alone. This is somewhat of a 07098 * hack - maybe we should have further tests to determine 07099 * what to do. 07100 */ 07101 if ((ctxt->node != NULL) && (ent->children != NULL)) { 07102 /* 07103 * Seems we are generating the DOM content, do 07104 * a simple tree copy for all references except the first 07105 * In the first occurrence list contains the replacement. 07106 * progressive == 2 means we are operating on the Reader 07107 * and since nodes are discarded we must copy all the time. 07108 */ 07109 if (((list == NULL) && (ent->owner == 0)) || 07110 (ctxt->parseMode == XML_PARSE_READER)) { 07111 xmlNodePtr nw = NULL, cur, firstChild = NULL; 07112 07113 /* 07114 * when operating on a reader, the entities definitions 07115 * are always owning the entities subtree. 07116 if (ctxt->parseMode == XML_PARSE_READER) 07117 ent->owner = 1; 07118 */ 07119 07120 cur = ent->children; 07121 while (cur != NULL) { 07122 nw = xmlDocCopyNode(cur, ctxt->myDoc, 1); 07123 if (nw != NULL) { 07124 if (nw->_private == NULL) 07125 nw->_private = cur->_private; 07126 if (firstChild == NULL){ 07127 firstChild = nw; 07128 } 07129 nw = xmlAddChild(ctxt->node, nw); 07130 } 07131 if (cur == ent->last) { 07132 /* 07133 * needed to detect some strange empty 07134 * node cases in the reader tests 07135 */ 07136 if ((ctxt->parseMode == XML_PARSE_READER) && 07137 (nw != NULL) && 07138 (nw->type == XML_ELEMENT_NODE) && 07139 (nw->children == NULL)) 07140 nw->extra = 1; 07141 07142 break; 07143 } 07144 cur = cur->next; 07145 } 07146 #ifdef LIBXML_LEGACY_ENABLED 07147 if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) 07148 xmlAddEntityReference(ent, firstChild, nw); 07149 #endif /* LIBXML_LEGACY_ENABLED */ 07150 } else if (list == NULL) { 07151 xmlNodePtr nw = NULL, cur, next, last, 07152 firstChild = NULL; 07153 /* 07154 * Copy the entity child list and make it the new 07155 * entity child list. The goal is to make sure any 07156 * ID or REF referenced will be the one from the 07157 * document content and not the entity copy. 07158 */ 07159 cur = ent->children; 07160 ent->children = NULL; 07161 last = ent->last; 07162 ent->last = NULL; 07163 while (cur != NULL) { 07164 next = cur->next; 07165 cur->next = NULL; 07166 cur->parent = NULL; 07167 nw = xmlDocCopyNode(cur, ctxt->myDoc, 1); 07168 if (nw != NULL) { 07169 if (nw->_private == NULL) 07170 nw->_private = cur->_private; 07171 if (firstChild == NULL){ 07172 firstChild = cur; 07173 } 07174 xmlAddChild((xmlNodePtr) ent, nw); 07175 xmlAddChild(ctxt->node, cur); 07176 } 07177 if (cur == last) 07178 break; 07179 cur = next; 07180 } 07181 if (ent->owner == 0) 07182 ent->owner = 1; 07183 #ifdef LIBXML_LEGACY_ENABLED 07184 if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) 07185 xmlAddEntityReference(ent, firstChild, nw); 07186 #endif /* LIBXML_LEGACY_ENABLED */ 07187 } else { 07188 const xmlChar *nbktext; 07189 07190 /* 07191 * the name change is to avoid coalescing of the 07192 * node with a possible previous text one which 07193 * would make ent->children a dangling pointer 07194 */ 07195 nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext", 07196 -1); 07197 if (ent->children->type == XML_TEXT_NODE) 07198 ent->children->name = nbktext; 07199 if ((ent->last != ent->children) && 07200 (ent->last->type == XML_TEXT_NODE)) 07201 ent->last->name = nbktext; 07202 xmlAddChildList(ctxt->node, ent->children); 07203 } 07204 07205 /* 07206 * This is to avoid a nasty side effect, see 07207 * characters() in SAX.c 07208 */ 07209 ctxt->nodemem = 0; 07210 ctxt->nodelen = 0; 07211 return; 07212 } 07213 } 07214 } 07215 07244 xmlEntityPtr 07245 xmlParseEntityRef(xmlParserCtxtPtr ctxt) { 07246 const xmlChar *name; 07247 xmlEntityPtr ent = NULL; 07248 07249 GROW; 07250 07251 if (RAW != '&') 07252 return(NULL); 07253 NEXT; 07254 name = xmlParseName(ctxt); 07255 if (name == NULL) { 07256 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 07257 "xmlParseEntityRef: no name\n"); 07258 return(NULL); 07259 } 07260 if (RAW != ';') { 07261 xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL); 07262 return(NULL); 07263 } 07264 NEXT; 07265 07266 /* 07267 * Predefined entites override any extra definition 07268 */ 07269 if ((ctxt->options & XML_PARSE_OLDSAX) == 0) { 07270 ent = xmlGetPredefinedEntity(name); 07271 if (ent != NULL) 07272 return(ent); 07273 } 07274 07275 /* 07276 * Increate the number of entity references parsed 07277 */ 07278 ctxt->nbentities++; 07279 07280 /* 07281 * Ask first SAX for entity resolution, otherwise try the 07282 * entities which may have stored in the parser context. 07283 */ 07284 if (ctxt->sax != NULL) { 07285 if (ctxt->sax->getEntity != NULL) 07286 ent = ctxt->sax->getEntity(ctxt->userData, name); 07287 if ((ctxt->wellFormed == 1 ) && (ent == NULL) && 07288 (ctxt->options & XML_PARSE_OLDSAX)) 07289 ent = xmlGetPredefinedEntity(name); 07290 if ((ctxt->wellFormed == 1 ) && (ent == NULL) && 07291 (ctxt->userData==ctxt)) { 07292 ent = xmlSAX2GetEntity(ctxt, name); 07293 } 07294 } 07295 /* 07296 * [ WFC: Entity Declared ] 07297 * In a document without any DTD, a document with only an 07298 * internal DTD subset which contains no parameter entity 07299 * references, or a document with "standalone='yes'", the 07300 * Name given in the entity reference must match that in an 07301 * entity declaration, except that well-formed documents 07302 * need not declare any of the following entities: amp, lt, 07303 * gt, apos, quot. 07304 * The declaration of a parameter entity must precede any 07305 * reference to it. 07306 * Similarly, the declaration of a general entity must 07307 * precede any reference to it which appears in a default 07308 * value in an attribute-list declaration. Note that if 07309 * entities are declared in the external subset or in 07310 * external parameter entities, a non-validating processor 07311 * is not obligated to read and process their declarations; 07312 * for such documents, the rule that an entity must be 07313 * declared is a well-formedness constraint only if 07314 * standalone='yes'. 07315 */ 07316 if (ent == NULL) { 07317 if ((ctxt->standalone == 1) || 07318 ((ctxt->hasExternalSubset == 0) && 07319 (ctxt->hasPErefs == 0))) { 07320 xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY, 07321 "Entity '%s' not defined\n", name); 07322 } else { 07323 xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY, 07324 "Entity '%s' not defined\n", name); 07325 if ((ctxt->inSubset == 0) && 07326 (ctxt->sax != NULL) && 07327 (ctxt->sax->reference != NULL)) { 07328 ctxt->sax->reference(ctxt->userData, name); 07329 } 07330 } 07331 ctxt->valid = 0; 07332 } 07333 07334 /* 07335 * [ WFC: Parsed Entity ] 07336 * An entity reference must not contain the name of an 07337 * unparsed entity 07338 */ 07339 else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) { 07340 xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY, 07341 "Entity reference to unparsed entity %s\n", name); 07342 } 07343 07344 /* 07345 * [ WFC: No External Entity References ] 07346 * Attribute values cannot contain direct or indirect 07347 * entity references to external entities. 07348 */ 07349 else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) && 07350 (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) { 07351 xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL, 07352 "Attribute references external entity '%s'\n", name); 07353 } 07354 /* 07355 * [ WFC: No < in Attribute Values ] 07356 * The replacement text of any entity referred to directly or 07357 * indirectly in an attribute value (other than "<") must 07358 * not contain a <. 07359 */ 07360 else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) && 07361 (ent != NULL) && (ent->content != NULL) && 07362 (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) && 07363 (xmlStrchr(ent->content, '<'))) { 07364 xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, 07365 "'<' in entity '%s' is not allowed in attributes values\n", name); 07366 } 07367 07368 /* 07369 * Internal check, no parameter entities here ... 07370 */ 07371 else { 07372 switch (ent->etype) { 07373 case XML_INTERNAL_PARAMETER_ENTITY: 07374 case XML_EXTERNAL_PARAMETER_ENTITY: 07375 xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER, 07376 "Attempt to reference the parameter entity '%s'\n", 07377 name); 07378 break; 07379 default: 07380 break; 07381 } 07382 } 07383 07384 /* 07385 * [ WFC: No Recursion ] 07386 * A parsed entity must not contain a recursive reference 07387 * to itself, either directly or indirectly. 07388 * Done somewhere else 07389 */ 07390 return(ent); 07391 } 07392 07424 static xmlEntityPtr 07425 xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) { 07426 xmlChar *name; 07427 const xmlChar *ptr; 07428 xmlChar cur; 07429 xmlEntityPtr ent = NULL; 07430 07431 if ((str == NULL) || (*str == NULL)) 07432 return(NULL); 07433 ptr = *str; 07434 cur = *ptr; 07435 if (cur != '&') 07436 return(NULL); 07437 07438 ptr++; 07439 name = xmlParseStringName(ctxt, &ptr); 07440 if (name == NULL) { 07441 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 07442 "xmlParseStringEntityRef: no name\n"); 07443 *str = ptr; 07444 return(NULL); 07445 } 07446 if (*ptr != ';') { 07447 xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL); 07448 xmlFree(name); 07449 *str = ptr; 07450 return(NULL); 07451 } 07452 ptr++; 07453 07454 07455 /* 07456 * Predefined entites override any extra definition 07457 */ 07458 if ((ctxt->options & XML_PARSE_OLDSAX) == 0) { 07459 ent = xmlGetPredefinedEntity(name); 07460 if (ent != NULL) { 07461 xmlFree(name); 07462 *str = ptr; 07463 return(ent); 07464 } 07465 } 07466 07467 /* 07468 * Increate the number of entity references parsed 07469 */ 07470 ctxt->nbentities++; 07471 07472 /* 07473 * Ask first SAX for entity resolution, otherwise try the 07474 * entities which may have stored in the parser context. 07475 */ 07476 if (ctxt->sax != NULL) { 07477 if (ctxt->sax->getEntity != NULL) 07478 ent = ctxt->sax->getEntity(ctxt->userData, name); 07479 if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX)) 07480 ent = xmlGetPredefinedEntity(name); 07481 if ((ent == NULL) && (ctxt->userData==ctxt)) { 07482 ent = xmlSAX2GetEntity(ctxt, name); 07483 } 07484 } 07485 07486 /* 07487 * [ WFC: Entity Declared ] 07488 * In a document without any DTD, a document with only an 07489 * internal DTD subset which contains no parameter entity 07490 * references, or a document with "standalone='yes'", the 07491 * Name given in the entity reference must match that in an 07492 * entity declaration, except that well-formed documents 07493 * need not declare any of the following entities: amp, lt, 07494 * gt, apos, quot. 07495 * The declaration of a parameter entity must precede any 07496 * reference to it. 07497 * Similarly, the declaration of a general entity must 07498 * precede any reference to it which appears in a default 07499 * value in an attribute-list declaration. Note that if 07500 * entities are declared in the external subset or in 07501 * external parameter entities, a non-validating processor 07502 * is not obligated to read and process their declarations; 07503 * for such documents, the rule that an entity must be 07504 * declared is a well-formedness constraint only if 07505 * standalone='yes'. 07506 */ 07507 if (ent == NULL) { 07508 if ((ctxt->standalone == 1) || 07509 ((ctxt->hasExternalSubset == 0) && 07510 (ctxt->hasPErefs == 0))) { 07511 xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY, 07512 "Entity '%s' not defined\n", name); 07513 } else { 07514 xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY, 07515 "Entity '%s' not defined\n", 07516 name); 07517 } 07518 /* TODO ? check regressions ctxt->valid = 0; */ 07519 } 07520 07521 /* 07522 * [ WFC: Parsed Entity ] 07523 * An entity reference must not contain the name of an 07524 * unparsed entity 07525 */ 07526 else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) { 07527 xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY, 07528 "Entity reference to unparsed entity %s\n", name); 07529 } 07530 07531 /* 07532 * [ WFC: No External Entity References ] 07533 * Attribute values cannot contain direct or indirect 07534 * entity references to external entities. 07535 */ 07536 else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) && 07537 (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) { 07538 xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL, 07539 "Attribute references external entity '%s'\n", name); 07540 } 07541 /* 07542 * [ WFC: No < in Attribute Values ] 07543 * The replacement text of any entity referred to directly or 07544 * indirectly in an attribute value (other than "<") must 07545 * not contain a <. 07546 */ 07547 else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) && 07548 (ent != NULL) && (ent->content != NULL) && 07549 (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) && 07550 (xmlStrchr(ent->content, '<'))) { 07551 xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, 07552 "'<' in entity '%s' is not allowed in attributes values\n", 07553 name); 07554 } 07555 07556 /* 07557 * Internal check, no parameter entities here ... 07558 */ 07559 else { 07560 switch (ent->etype) { 07561 case XML_INTERNAL_PARAMETER_ENTITY: 07562 case XML_EXTERNAL_PARAMETER_ENTITY: 07563 xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER, 07564 "Attempt to reference the parameter entity '%s'\n", 07565 name); 07566 break; 07567 default: 07568 break; 07569 } 07570 } 07571 07572 /* 07573 * [ WFC: No Recursion ] 07574 * A parsed entity must not contain a recursive reference 07575 * to itself, either directly or indirectly. 07576 * Done somewhere else 07577 */ 07578 07579 xmlFree(name); 07580 *str = ptr; 07581 return(ent); 07582 } 07583 07613 void 07614 xmlParsePEReference(xmlParserCtxtPtr ctxt) 07615 { 07616 const xmlChar *name; 07617 xmlEntityPtr entity = NULL; 07618 xmlParserInputPtr input; 07619 07620 if (RAW != '%') 07621 return; 07622 NEXT; 07623 name = xmlParseName(ctxt); 07624 if (name == NULL) { 07625 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 07626 "xmlParsePEReference: no name\n"); 07627 return; 07628 } 07629 if (RAW != ';') { 07630 xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL); 07631 return; 07632 } 07633 07634 NEXT; 07635 07636 /* 07637 * Increate the number of entity references parsed 07638 */ 07639 ctxt->nbentities++; 07640 07641 /* 07642 * Request the entity from SAX 07643 */ 07644 if ((ctxt->sax != NULL) && 07645 (ctxt->sax->getParameterEntity != NULL)) 07646 entity = ctxt->sax->getParameterEntity(ctxt->userData, 07647 name); 07648 if (entity == NULL) { 07649 /* 07650 * [ WFC: Entity Declared ] 07651 * In a document without any DTD, a document with only an 07652 * internal DTD subset which contains no parameter entity 07653 * references, or a document with "standalone='yes'", ... 07654 * ... The declaration of a parameter entity must precede 07655 * any reference to it... 07656 */ 07657 if ((ctxt->standalone == 1) || 07658 ((ctxt->hasExternalSubset == 0) && 07659 (ctxt->hasPErefs == 0))) { 07660 xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY, 07661 "PEReference: %%%s; not found\n", 07662 name); 07663 } else { 07664 /* 07665 * [ VC: Entity Declared ] 07666 * In a document with an external subset or external 07667 * parameter entities with "standalone='no'", ... 07668 * ... The declaration of a parameter entity must 07669 * precede any reference to it... 07670 */ 07671 xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY, 07672 "PEReference: %%%s; not found\n", 07673 name, NULL); 07674 ctxt->valid = 0; 07675 } 07676 } else { 07677 /* 07678 * Internal checking in case the entity quest barfed 07679 */ 07680 if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) && 07681 (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) { 07682 xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY, 07683 "Internal: %%%s; is not a parameter entity\n", 07684 name, NULL); 07685 } else if (ctxt->input->free != deallocblankswrapper) { 07686 input = xmlNewBlanksWrapperInputStream(ctxt, entity); 07687 if (xmlPushInput(ctxt, input) < 0) 07688 return; 07689 } else { 07690 /* 07691 * TODO !!! 07692 * handle the extra spaces added before and after 07693 * c.f. http://www.w3.org/TR/REC-xml#as-PE 07694 */ 07695 input = xmlNewEntityInputStream(ctxt, entity); 07696 if (xmlPushInput(ctxt, input) < 0) 07697 return; 07698 if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) && 07699 (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && 07700 (IS_BLANK_CH(NXT(5)))) { 07701 xmlParseTextDecl(ctxt); 07702 if (ctxt->errNo == 07703 XML_ERR_UNSUPPORTED_ENCODING) { 07704 /* 07705 * The XML REC instructs us to stop parsing 07706 * right here 07707 */ 07708 ctxt->instate = XML_PARSER_EOF; 07709 return; 07710 } 07711 } 07712 } 07713 } 07714 ctxt->hasPErefs = 1; 07715 } 07716 07728 static int 07729 xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) { 07730 xmlParserInputPtr input; 07731 xmlBufferPtr buf; 07732 int l, c; 07733 int count = 0; 07734 07735 if ((ctxt == NULL) || (entity == NULL) || 07736 ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) && 07737 (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) || 07738 (entity->content != NULL)) { 07739 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, 07740 "xmlLoadEntityContent parameter error"); 07741 return(-1); 07742 } 07743 07744 if (xmlParserDebugEntities) 07745 xmlGenericError(xmlGenericErrorContext, 07746 "Reading %s entity content input\n", entity->name); 07747 07748 buf = xmlBufferCreate(); 07749 if (buf == NULL) { 07750 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, 07751 "xmlLoadEntityContent parameter error"); 07752 return(-1); 07753 } 07754 07755 input = xmlNewEntityInputStream(ctxt, entity); 07756 if (input == NULL) { 07757 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, 07758 "xmlLoadEntityContent input error"); 07759 xmlBufferFree(buf); 07760 return(-1); 07761 } 07762 07763 /* 07764 * Push the entity as the current input, read char by char 07765 * saving to the buffer until the end of the entity or an error 07766 */ 07767 if (xmlPushInput(ctxt, input) < 0) { 07768 xmlBufferFree(buf); 07769 return(-1); 07770 } 07771 07772 GROW; 07773 c = CUR_CHAR(l); 07774 while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) && 07775 (IS_CHAR(c))) { 07776 xmlBufferAdd(buf, ctxt->input->cur, l); 07777 if (count++ > 100) { 07778 count = 0; 07779 GROW; 07780 } 07781 NEXTL(l); 07782 c = CUR_CHAR(l); 07783 } 07784 07785 if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) { 07786 xmlPopInput(ctxt); 07787 } else if (!IS_CHAR(c)) { 07788 xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, 07789 "xmlLoadEntityContent: invalid char value %d\n", 07790 c); 07791 xmlBufferFree(buf); 07792 return(-1); 07793 } 07794 entity->content = buf->content; 07795 buf->content = NULL; 07796 xmlBufferFree(buf); 07797 07798 return(0); 07799 } 07800 07832 static xmlEntityPtr 07833 xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) { 07834 const xmlChar *ptr; 07835 xmlChar cur; 07836 xmlChar *name; 07837 xmlEntityPtr entity = NULL; 07838 07839 if ((str == NULL) || (*str == NULL)) return(NULL); 07840 ptr = *str; 07841 cur = *ptr; 07842 if (cur != '%') 07843 return(NULL); 07844 ptr++; 07845 name = xmlParseStringName(ctxt, &ptr); 07846 if (name == NULL) { 07847 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 07848 "xmlParseStringPEReference: no name\n"); 07849 *str = ptr; 07850 return(NULL); 07851 } 07852 cur = *ptr; 07853 if (cur != ';') { 07854 xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL); 07855 xmlFree(name); 07856 *str = ptr; 07857 return(NULL); 07858 } 07859 ptr++; 07860 07861 /* 07862 * Increate the number of entity references parsed 07863 */ 07864 ctxt->nbentities++; 07865 07866 /* 07867 * Request the entity from SAX 07868 */ 07869 if ((ctxt->sax != NULL) && 07870 (ctxt->sax->getParameterEntity != NULL)) 07871 entity = ctxt->sax->getParameterEntity(ctxt->userData, 07872 name); 07873 if (entity == NULL) { 07874 /* 07875 * [ WFC: Entity Declared ] 07876 * In a document without any DTD, a document with only an 07877 * internal DTD subset which contains no parameter entity 07878 * references, or a document with "standalone='yes'", ... 07879 * ... The declaration of a parameter entity must precede 07880 * any reference to it... 07881 */ 07882 if ((ctxt->standalone == 1) || 07883 ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) { 07884 xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY, 07885 "PEReference: %%%s; not found\n", name); 07886 } else { 07887 /* 07888 * [ VC: Entity Declared ] 07889 * In a document with an external subset or external 07890 * parameter entities with "standalone='no'", ... 07891 * ... The declaration of a parameter entity must 07892 * precede any reference to it... 07893 */ 07894 xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY, 07895 "PEReference: %%%s; not found\n", 07896 name, NULL); 07897 ctxt->valid = 0; 07898 } 07899 } else { 07900 /* 07901 * Internal checking in case the entity quest barfed 07902 */ 07903 if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) && 07904 (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) { 07905 xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY, 07906 "%%%s; is not a parameter entity\n", 07907 name, NULL); 07908 } 07909 } 07910 ctxt->hasPErefs = 1; 07911 xmlFree(name); 07912 *str = ptr; 07913 return(entity); 07914 } 07915 07930 void 07931 xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) { 07932 const xmlChar *name = NULL; 07933 xmlChar *ExternalID = NULL; 07934 xmlChar *URI = NULL; 07935 07936 /* 07937 * We know that '<!DOCTYPE' has been detected. 07938 */ 07939 SKIP(9); 07940 07941 SKIP_BLANKS; 07942 07943 /* 07944 * Parse the DOCTYPE name. 07945 */ 07946 name = xmlParseName(ctxt); 07947 if (name == NULL) { 07948 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 07949 "xmlParseDocTypeDecl : no DOCTYPE name !\n"); 07950 } 07951 ctxt->intSubName = name; 07952 07953 SKIP_BLANKS; 07954 07955 /* 07956 * Check for SystemID and ExternalID 07957 */ 07958 URI = xmlParseExternalID(ctxt, &ExternalID, 1); 07959 07960 if ((URI != NULL) || (ExternalID != NULL)) { 07961 ctxt->hasExternalSubset = 1; 07962 } 07963 ctxt->extSubURI = URI; 07964 ctxt->extSubSystem = ExternalID; 07965 07966 SKIP_BLANKS; 07967 07968 /* 07969 * Create and update the internal subset. 07970 */ 07971 if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) && 07972 (!ctxt->disableSAX)) 07973 ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI); 07974 07975 /* 07976 * Is there any internal subset declarations ? 07977 * they are handled separately in xmlParseInternalSubset() 07978 */ 07979 if (RAW == '[') 07980 return; 07981 07982 /* 07983 * We should be at the end of the DOCTYPE declaration. 07984 */ 07985 if (RAW != '>') { 07986 xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL); 07987 } 07988 NEXT; 07989 } 07990 08000 static void 08001 xmlParseInternalSubset(xmlParserCtxtPtr ctxt) { 08002 /* 08003 * Is there any DTD definition ? 08004 */ 08005 if (RAW == '[') { 08006 ctxt->instate = XML_PARSER_DTD; 08007 NEXT; 08008 /* 08009 * Parse the succession of Markup declarations and 08010 * PEReferences. 08011 * Subsequence (markupdecl | PEReference | S)* 08012 */ 08013 while (RAW != ']') { 08014 const xmlChar *check = CUR_PTR; 08015 unsigned int cons = ctxt->input->consumed; 08016 08017 SKIP_BLANKS; 08018 xmlParseMarkupDecl(ctxt); 08019 xmlParsePEReference(ctxt); 08020 08021 /* 08022 * Pop-up of finished entities. 08023 */ 08024 while ((RAW == 0) && (ctxt->inputNr > 1)) 08025 xmlPopInput(ctxt); 08026 08027 if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) { 08028 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, 08029 "xmlParseInternalSubset: error detected in Markup declaration\n"); 08030 break; 08031 } 08032 } 08033 if (RAW == ']') { 08034 NEXT; 08035 SKIP_BLANKS; 08036 } 08037 } 08038 08039 /* 08040 * We should be at the end of the DOCTYPE declaration. 08041 */ 08042 if (RAW != '>') { 08043 xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL); 08044 } 08045 NEXT; 08046 } 08047 08048 #ifdef LIBXML_SAX1_ENABLED 08049 08082 const xmlChar * 08083 xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) { 08084 const xmlChar *name; 08085 xmlChar *val; 08086 08087 *value = NULL; 08088 GROW; 08089 name = xmlParseName(ctxt); 08090 if (name == NULL) { 08091 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 08092 "error parsing attribute name\n"); 08093 return(NULL); 08094 } 08095 08096 /* 08097 * read the value 08098 */ 08099 SKIP_BLANKS; 08100 if (RAW == '=') { 08101 NEXT; 08102 SKIP_BLANKS; 08103 val = xmlParseAttValue(ctxt); 08104 ctxt->instate = XML_PARSER_CONTENT; 08105 } else { 08106 xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE, 08107 "Specification mandate value for attribute %s\n", name); 08108 return(NULL); 08109 } 08110 08111 /* 08112 * Check that xml:lang conforms to the specification 08113 * No more registered as an error, just generate a warning now 08114 * since this was deprecated in XML second edition 08115 */ 08116 if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) { 08117 if (!xmlCheckLanguageID(val)) { 08118 xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE, 08119 "Malformed value for xml:lang : %s\n", 08120 val, NULL); 08121 } 08122 } 08123 08124 /* 08125 * Check that xml:space conforms to the specification 08126 */ 08127 if (xmlStrEqual(name, BAD_CAST "xml:space")) { 08128 if (xmlStrEqual(val, BAD_CAST "default")) 08129 *(ctxt->space) = 0; 08130 else if (xmlStrEqual(val, BAD_CAST "preserve")) 08131 *(ctxt->space) = 1; 08132 else { 08133 xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE, 08134 "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n", 08135 val, NULL); 08136 } 08137 } 08138 08139 *value = val; 08140 return(name); 08141 } 08142 08171 const xmlChar * 08172 xmlParseStartTag(xmlParserCtxtPtr ctxt) { 08173 const xmlChar *name; 08174 const xmlChar *attname; 08175 xmlChar *attvalue; 08176 const xmlChar **atts = ctxt->atts; 08177 int nbatts = 0; 08178 int maxatts = ctxt->maxatts; 08179 int i; 08180 08181 if (RAW != '<') return(NULL); 08182 NEXT1; 08183 08184 name = xmlParseName(ctxt); 08185 if (name == NULL) { 08186 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 08187 "xmlParseStartTag: invalid element name\n"); 08188 return(NULL); 08189 } 08190 08191 /* 08192 * Now parse the attributes, it ends up with the ending 08193 * 08194 * (S Attribute)* S? 08195 */ 08196 SKIP_BLANKS; 08197 GROW; 08198 08199 while ((RAW != '>') && 08200 ((RAW != '/') || (NXT(1) != '>')) && 08201 (IS_BYTE_CHAR(RAW))) { 08202 const xmlChar *q = CUR_PTR; 08203 unsigned int cons = ctxt->input->consumed; 08204 08205 attname = xmlParseAttribute(ctxt, &attvalue); 08206 if ((attname != NULL) && (attvalue != NULL)) { 08207 /* 08208 * [ WFC: Unique Att Spec ] 08209 * No attribute name may appear more than once in the same 08210 * start-tag or empty-element tag. 08211 */ 08212 for (i = 0; i < nbatts;i += 2) { 08213 if (xmlStrEqual(atts[i], attname)) { 08214 xmlErrAttributeDup(ctxt, NULL, attname); 08215 xmlFree(attvalue); 08216 goto failed; 08217 } 08218 } 08219 /* 08220 * Add the pair to atts 08221 */ 08222 if (atts == NULL) { 08223 maxatts = 22; /* allow for 10 attrs by default */ 08224 atts = (const xmlChar **) 08225 xmlMalloc(maxatts * sizeof(xmlChar *)); 08226 if (atts == NULL) { 08227 xmlErrMemory(ctxt, NULL); 08228 if (attvalue != NULL) 08229 xmlFree(attvalue); 08230 goto failed; 08231 } 08232 ctxt->atts = atts; 08233 ctxt->maxatts = maxatts; 08234 } else if (nbatts + 4 > maxatts) { 08235 const xmlChar **n; 08236 08237 maxatts *= 2; 08238 n = (const xmlChar **) xmlRealloc((void *) atts, 08239 maxatts * sizeof(const xmlChar *)); 08240 if (n == NULL) { 08241 xmlErrMemory(ctxt, NULL); 08242 if (attvalue != NULL) 08243 xmlFree(attvalue); 08244 goto failed; 08245 } 08246 atts = n; 08247 ctxt->atts = atts; 08248 ctxt->maxatts = maxatts; 08249 } 08250 atts[nbatts++] = attname; 08251 atts[nbatts++] = attvalue; 08252 atts[nbatts] = NULL; 08253 atts[nbatts + 1] = NULL; 08254 } else { 08255 if (attvalue != NULL) 08256 xmlFree(attvalue); 08257 } 08258 08259 failed: 08260 08261 GROW 08262 if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>')))) 08263 break; 08264 if (!IS_BLANK_CH(RAW)) { 08265 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 08266 "attributes construct error\n"); 08267 } 08268 SKIP_BLANKS; 08269 if ((cons == ctxt->input->consumed) && (q == CUR_PTR) && 08270 (attname == NULL) && (attvalue == NULL)) { 08271 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, 08272 "xmlParseStartTag: problem parsing attributes\n"); 08273 break; 08274 } 08275 SHRINK; 08276 GROW; 08277 } 08278 08279 /* 08280 * SAX: Start of Element ! 08281 */ 08282 if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) && 08283 (!ctxt->disableSAX)) { 08284 if (nbatts > 0) 08285 ctxt->sax->startElement(ctxt->userData, name, atts); 08286 else 08287 ctxt->sax->startElement(ctxt->userData, name, NULL); 08288 } 08289 08290 if (atts != NULL) { 08291 /* Free only the content strings */ 08292 for (i = 1;i < nbatts;i+=2) 08293 if (atts[i] != NULL) 08294 xmlFree((xmlChar *) atts[i]); 08295 } 08296 return(name); 08297 } 08298 08314 static void 08315 xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) { 08316 const xmlChar *name; 08317 08318 GROW; 08319 if ((RAW != '<') || (NXT(1) != '/')) { 08320 xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED, 08321 "xmlParseEndTag: '</' not found\n"); 08322 return; 08323 } 08324 SKIP(2); 08325 08326 name = xmlParseNameAndCompare(ctxt,ctxt->name); 08327 08328 /* 08329 * We should definitely be at the ending "S? '>'" part 08330 */ 08331 GROW; 08332 SKIP_BLANKS; 08333 if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) { 08334 xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL); 08335 } else 08336 NEXT1; 08337 08338 /* 08339 * [ WFC: Element Type Match ] 08340 * The Name in an element's end-tag must match the element type in the 08341 * start-tag. 08342 * 08343 */ 08344 if (name != (xmlChar*)1) { 08345 if (name == NULL) name = BAD_CAST "unparseable"; 08346 xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH, 08347 "Opening and ending tag mismatch: %s line %d and %s\n", 08348 ctxt->name, line, name); 08349 } 08350 08351 /* 08352 * SAX: End of Tag 08353 */ 08354 if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) && 08355 (!ctxt->disableSAX)) 08356 ctxt->sax->endElement(ctxt->userData, ctxt->name); 08357 08358 namePop(ctxt); 08359 spacePop(ctxt); 08360 return; 08361 } 08362 08376 void 08377 xmlParseEndTag(xmlParserCtxtPtr ctxt) { 08378 xmlParseEndTag1(ctxt, 0); 08379 } 08380 #endif /* LIBXML_SAX1_ENABLED */ 08381 08382 /************************************************************************ 08383 * * 08384 * SAX 2 specific operations * 08385 * * 08386 ************************************************************************/ 08387 08388 /* 08389 * xmlGetNamespace: 08390 * @ctxt: an XML parser context 08391 * @prefix: the prefix to lookup 08392 * 08393 * Lookup the namespace name for the @prefix (which ca be NULL) 08394 * The prefix must come from the @ctxt->dict dictionnary 08395 * 08396 * Returns the namespace name or NULL if not bound 08397 */ 08398 static const xmlChar * 08399 xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) { 08400 int i; 08401 08402 if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns); 08403 for (i = ctxt->nsNr - 2;i >= 0;i-=2) 08404 if (ctxt->nsTab[i] == prefix) { 08405 if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0)) 08406 return(NULL); 08407 return(ctxt->nsTab[i + 1]); 08408 } 08409 return(NULL); 08410 } 08411 08426 static const xmlChar * 08427 xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) { 08428 const xmlChar *l, *p; 08429 08430 GROW; 08431 08432 l = xmlParseNCName(ctxt); 08433 if (l == NULL) { 08434 if (CUR == ':') { 08435 l = xmlParseName(ctxt); 08436 if (l != NULL) { 08437 xmlNsErr(ctxt, XML_NS_ERR_QNAME, 08438 "Failed to parse QName '%s'\n", l, NULL, NULL); 08439 *prefix = NULL; 08440 return(l); 08441 } 08442 } 08443 return(NULL); 08444 } 08445 if (CUR == ':') { 08446 NEXT; 08447 p = l; 08448 l = xmlParseNCName(ctxt); 08449 if (l == NULL) { 08450 xmlChar *tmp; 08451 08452 xmlNsErr(ctxt, XML_NS_ERR_QNAME, 08453 "Failed to parse QName '%s:'\n", p, NULL, NULL); 08454 l = xmlParseNmtoken(ctxt); 08455 if (l == NULL) 08456 tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0); 08457 else { 08458 tmp = xmlBuildQName(l, p, NULL, 0); 08459 xmlFree((char *)l); 08460 } 08461 p = xmlDictLookup(ctxt->dict, tmp, -1); 08462 if (tmp != NULL) xmlFree(tmp); 08463 *prefix = NULL; 08464 return(p); 08465 } 08466 if (CUR == ':') { 08467 xmlChar *tmp; 08468 08469 xmlNsErr(ctxt, XML_NS_ERR_QNAME, 08470 "Failed to parse QName '%s:%s:'\n", p, l, NULL); 08471 NEXT; 08472 tmp = (xmlChar *) xmlParseName(ctxt); 08473 if (tmp != NULL) { 08474 tmp = xmlBuildQName(tmp, l, NULL, 0); 08475 l = xmlDictLookup(ctxt->dict, tmp, -1); 08476 if (tmp != NULL) xmlFree(tmp); 08477 *prefix = p; 08478 return(l); 08479 } 08480 tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0); 08481 l = xmlDictLookup(ctxt->dict, tmp, -1); 08482 if (tmp != NULL) xmlFree(tmp); 08483 *prefix = p; 08484 return(l); 08485 } 08486 *prefix = p; 08487 } else 08488 *prefix = NULL; 08489 return(l); 08490 } 08491 08505 static const xmlChar * 08506 xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name, 08507 xmlChar const *prefix) { 08508 const xmlChar *cmp; 08509 const xmlChar *in; 08510 const xmlChar *ret; 08511 const xmlChar *prefix2; 08512 08513 if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name)); 08514 08515 GROW; 08516 in = ctxt->input->cur; 08517 08518 cmp = prefix; 08519 while (*in != 0 && *in == *cmp) { 08520 ++in; 08521 ++cmp; 08522 } 08523 if ((*cmp == 0) && (*in == ':')) { 08524 in++; 08525 cmp = name; 08526 while (*in != 0 && *in == *cmp) { 08527 ++in; 08528 ++cmp; 08529 } 08530 if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) { 08531 /* success */ 08532 ctxt->input->cur = in; 08533 return((const xmlChar*) 1); 08534 } 08535 } 08536 /* 08537 * all strings coms from the dictionary, equality can be done directly 08538 */ 08539 ret = xmlParseQName (ctxt, &prefix2); 08540 if ((ret == name) && (prefix == prefix2)) 08541 return((const xmlChar*) 1); 08542 return ret; 08543 } 08544 08579 static xmlChar * 08580 xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, 08581 int normalize) 08582 { 08583 xmlChar limit = 0; 08584 const xmlChar *in = NULL, *start, *end, *last; 08585 xmlChar *ret = NULL; 08586 08587 GROW; 08588 in = (xmlChar *) CUR_PTR; 08589 if (*in != '"' && *in != '\'') { 08590 xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL); 08591 return (NULL); 08592 } 08593 ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE; 08594 08595 /* 08596 * try to handle in this routine the most common case where no 08597 * allocation of a new string is required and where content is 08598 * pure ASCII. 08599 */ 08600 limit = *in++; 08601 end = ctxt->input->end; 08602 start = in; 08603 if (in >= end) { 08604 const xmlChar *oldbase = ctxt->input->base; 08605 GROW; 08606 if (oldbase != ctxt->input->base) { 08607 long delta = ctxt->input->base - oldbase; 08608 start = start + delta; 08609 in = in + delta; 08610 } 08611 end = ctxt->input->end; 08612 } 08613 if (normalize) { 08614 /* 08615 * Skip any leading spaces 08616 */ 08617 while ((in < end) && (*in != limit) && 08618 ((*in == 0x20) || (*in == 0x9) || 08619 (*in == 0xA) || (*in == 0xD))) { 08620 in++; 08621 start = in; 08622 if (in >= end) { 08623 const xmlChar *oldbase = ctxt->input->base; 08624 GROW; 08625 if (oldbase != ctxt->input->base) { 08626 long delta = ctxt->input->base - oldbase; 08627 start = start + delta; 08628 in = in + delta; 08629 } 08630 end = ctxt->input->end; 08631 } 08632 } 08633 while ((in < end) && (*in != limit) && (*in >= 0x20) && 08634 (*in <= 0x7f) && (*in != '&') && (*in != '<')) { 08635 if ((*in++ == 0x20) && (*in == 0x20)) break; 08636 if (in >= end) { 08637 const xmlChar *oldbase = ctxt->input->base; 08638 GROW; 08639 if (oldbase != ctxt->input->base) { 08640 long delta = ctxt->input->base - oldbase; 08641 start = start + delta; 08642 in = in + delta; 08643 } 08644 end = ctxt->input->end; 08645 } 08646 } 08647 last = in; 08648 /* 08649 * skip the trailing blanks 08650 */ 08651 while ((last[-1] == 0x20) && (last > start)) last--; 08652 while ((in < end) && (*in != limit) && 08653 ((*in == 0x20) || (*in == 0x9) || 08654 (*in == 0xA) || (*in == 0xD))) { 08655 in++; 08656 if (in >= end) { 08657 const xmlChar *oldbase = ctxt->input->base; 08658 GROW; 08659 if (oldbase != ctxt->input->base) { 08660 long delta = ctxt->input->base - oldbase; 08661 start = start + delta; 08662 in = in + delta; 08663 last = last + delta; 08664 } 08665 end = ctxt->input->end; 08666 } 08667 } 08668 if (*in != limit) goto need_complex; 08669 } else { 08670 while ((in < end) && (*in != limit) && (*in >= 0x20) && 08671 (*in <= 0x7f) && (*in != '&') && (*in != '<')) { 08672 in++; 08673 if (in >= end) { 08674 const xmlChar *oldbase = ctxt->input->base; 08675 GROW; 08676 if (oldbase != ctxt->input->base) { 08677 long delta = ctxt->input->base - oldbase; 08678 start = start + delta; 08679 in = in + delta; 08680 } 08681 end = ctxt->input->end; 08682 } 08683 } 08684 last = in; 08685 if (*in != limit) goto need_complex; 08686 } 08687 in++; 08688 if (len != NULL) { 08689 *len = last - start; 08690 ret = (xmlChar *) start; 08691 } else { 08692 if (alloc) *alloc = 1; 08693 ret = xmlStrndup(start, last - start); 08694 } 08695 CUR_PTR = in; 08696 if (alloc) *alloc = 0; 08697 return ret; 08698 need_complex: 08699 if (alloc) *alloc = 1; 08700 return xmlParseAttValueComplex(ctxt, len, normalize); 08701 } 08702 08718 static const xmlChar * 08719 xmlParseAttribute2(xmlParserCtxtPtr ctxt, 08720 const xmlChar * pref, const xmlChar * elem, 08721 const xmlChar ** prefix, xmlChar ** value, 08722 int *len, int *alloc) 08723 { 08724 const xmlChar *name; 08725 xmlChar *val, *internal_val = NULL; 08726 int normalize = 0; 08727 08728 *value = NULL; 08729 GROW; 08730 name = xmlParseQName(ctxt, prefix); 08731 if (name == NULL) { 08732 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 08733 "error parsing attribute name\n"); 08734 return (NULL); 08735 } 08736 08737 /* 08738 * get the type if needed 08739 */ 08740 if (ctxt->attsSpecial != NULL) { 08741 int type; 08742 08743 type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial, 08744 pref, elem, *prefix, name); 08745 if (type != 0) 08746 normalize = 1; 08747 } 08748 08749 /* 08750 * read the value 08751 */ 08752 SKIP_BLANKS; 08753 if (RAW == '=') { 08754 NEXT; 08755 SKIP_BLANKS; 08756 val = xmlParseAttValueInternal(ctxt, len, alloc, normalize); 08757 if (normalize) { 08758 /* 08759 * Sometimes a second normalisation pass for spaces is needed 08760 * but that only happens if charrefs or entities refernces 08761 * have been used in the attribute value, i.e. the attribute 08762 * value have been extracted in an allocated string already. 08763 */ 08764 if (*alloc) { 08765 const xmlChar *val2; 08766 08767 val2 = xmlAttrNormalizeSpace2(ctxt, val, len); 08768 if ((val2 != NULL) && (val2 != val)) { 08769 xmlFree(val); 08770 val = (xmlChar *) val2; 08771 } 08772 } 08773 } 08774 ctxt->instate = XML_PARSER_CONTENT; 08775 } else { 08776 xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE, 08777 "Specification mandate value for attribute %s\n", 08778 name); 08779 return (NULL); 08780 } 08781 08782 if (*prefix == ctxt->str_xml) { 08783 /* 08784 * Check that xml:lang conforms to the specification 08785 * No more registered as an error, just generate a warning now 08786 * since this was deprecated in XML second edition 08787 */ 08788 if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) { 08789 internal_val = xmlStrndup(val, *len); 08790 if (!xmlCheckLanguageID(internal_val)) { 08791 xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE, 08792 "Malformed value for xml:lang : %s\n", 08793 internal_val, NULL); 08794 } 08795 } 08796 08797 /* 08798 * Check that xml:space conforms to the specification 08799 */ 08800 if (xmlStrEqual(name, BAD_CAST "space")) { 08801 internal_val = xmlStrndup(val, *len); 08802 if (xmlStrEqual(internal_val, BAD_CAST "default")) 08803 *(ctxt->space) = 0; 08804 else if (xmlStrEqual(internal_val, BAD_CAST "preserve")) 08805 *(ctxt->space) = 1; 08806 else { 08807 xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE, 08808 "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n", 08809 internal_val, NULL); 08810 } 08811 } 08812 if (internal_val) { 08813 xmlFree(internal_val); 08814 } 08815 } 08816 08817 *value = val; 08818 return (name); 08819 } 08849 static const xmlChar * 08850 xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref, 08851 const xmlChar **URI, int *tlen) { 08852 const xmlChar *localname; 08853 const xmlChar *prefix; 08854 const xmlChar *attname; 08855 const xmlChar *aprefix; 08856 const xmlChar *nsname; 08857 xmlChar *attvalue; 08858 const xmlChar **atts = ctxt->atts; 08859 int maxatts = ctxt->maxatts; 08860 int nratts, nbatts, nbdef; 08861 int i, j, nbNs, attval, oldline, oldcol; 08862 const xmlChar *base; 08863 unsigned long cur; 08864 int nsNr = ctxt->nsNr; 08865 08866 if (RAW != '<') return(NULL); 08867 NEXT1; 08868 08869 /* 08870 * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that 08871 * point since the attribute values may be stored as pointers to 08872 * the buffer and calling SHRINK would destroy them ! 08873 * The Shrinking is only possible once the full set of attribute 08874 * callbacks have been done. 08875 */ 08876 reparse: 08877 SHRINK; 08878 base = ctxt->input->base; 08879 cur = ctxt->input->cur - ctxt->input->base; 08880 oldline = ctxt->input->line; 08881 oldcol = ctxt->input->col; 08882 nbatts = 0; 08883 nratts = 0; 08884 nbdef = 0; 08885 nbNs = 0; 08886 attval = 0; 08887 /* Forget any namespaces added during an earlier parse of this element. */ 08888 ctxt->nsNr = nsNr; 08889 08890 localname = xmlParseQName(ctxt, &prefix); 08891 if (localname == NULL) { 08892 xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, 08893 "StartTag: invalid element name\n"); 08894 return(NULL); 08895 } 08896 *tlen = ctxt->input->cur - ctxt->input->base - cur; 08897 08898 /* 08899 * Now parse the attributes, it ends up with the ending 08900 * 08901 * (S Attribute)* S? 08902 */ 08903 SKIP_BLANKS; 08904 GROW; 08905 if (ctxt->input->base != base) goto base_changed; 08906 08907 while ((RAW != '>') && 08908 ((RAW != '/') || (NXT(1) != '>')) && 08909 (IS_BYTE_CHAR(RAW))) { 08910 const xmlChar *q = CUR_PTR; 08911 unsigned int cons = ctxt->input->consumed; 08912 int len = -1, alloc = 0; 08913 08914 attname = xmlParseAttribute2(ctxt, prefix, localname, 08915 &aprefix, &attvalue, &len, &alloc); 08916 if (ctxt->input->base != base) { 08917 if ((attvalue != NULL) && (alloc != 0)) 08918 xmlFree(attvalue); 08919 attvalue = NULL; 08920 goto base_changed; 08921 } 08922 if ((attname != NULL) && (attvalue != NULL)) { 08923 if (len < 0) len = xmlStrlen(attvalue); 08924 if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) { 08925 const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len); 08926 xmlURIPtr uri; 08927 08928 if (*URL != 0) { 08929 uri = xmlParseURI((const char *) URL); 08930 if (uri == NULL) { 08931 xmlNsErr(ctxt, XML_WAR_NS_URI, 08932 "xmlns: '%s' is not a valid URI\n", 08933 URL, NULL, NULL); 08934 } else { 08935 if (uri->scheme == NULL) { 08936 xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE, 08937 "xmlns: URI %s is not absolute\n", 08938 URL, NULL, NULL); 08939 } 08940 xmlFreeURI(uri); 08941 } 08942 if (URL == ctxt->str_xml_ns) { 08943 if (attname != ctxt->str_xml) { 08944 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, 08945 "xml namespace URI cannot be the default namespace\n", 08946 NULL, NULL, NULL); 08947 } 08948 goto skip_default_ns; 08949 } 08950 if ((len == 29) && 08951 (xmlStrEqual(URL, 08952 BAD_CAST "http://www.w3.org/2000/xmlns/"))) { 08953 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, 08954 "reuse of the xmlns namespace name is forbidden\n", 08955 NULL, NULL, NULL); 08956 goto skip_default_ns; 08957 } 08958 } 08959 /* 08960 * check that it's not a defined namespace 08961 */ 08962 for (j = 1;j <= nbNs;j++) 08963 if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL) 08964 break; 08965 if (j <= nbNs) 08966 xmlErrAttributeDup(ctxt, NULL, attname); 08967 else 08968 if (nsPush(ctxt, NULL, URL) > 0) nbNs++; 08969 skip_default_ns: 08970 if (alloc != 0) xmlFree(attvalue); 08971 SKIP_BLANKS; 08972 continue; 08973 } 08974 if (aprefix == ctxt->str_xmlns) { 08975 const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len); 08976 xmlURIPtr uri; 08977 08978 if (attname == ctxt->str_xml) { 08979 if (URL != ctxt->str_xml_ns) { 08980 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, 08981 "xml namespace prefix mapped to wrong URI\n", 08982 NULL, NULL, NULL); 08983 } 08984 /* 08985 * Do not keep a namespace definition node 08986 */ 08987 goto skip_ns; 08988 } 08989 if (URL == ctxt->str_xml_ns) { 08990 if (attname != ctxt->str_xml) { 08991 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, 08992 "xml namespace URI mapped to wrong prefix\n", 08993 NULL, NULL, NULL); 08994 } 08995 goto skip_ns; 08996 } 08997 if (attname == ctxt->str_xmlns) { 08998 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, 08999 "redefinition of the xmlns prefix is forbidden\n", 09000 NULL, NULL, NULL); 09001 goto skip_ns; 09002 } 09003 if ((len == 29) && 09004 (xmlStrEqual(URL, 09005 BAD_CAST "http://www.w3.org/2000/xmlns/"))) { 09006 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, 09007 "reuse of the xmlns namespace name is forbidden\n", 09008 NULL, NULL, NULL); 09009 goto skip_ns; 09010 } 09011 if ((URL == NULL) || (URL[0] == 0)) { 09012 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, 09013 "xmlns:%s: Empty XML namespace is not allowed\n", 09014 attname, NULL, NULL); 09015 goto skip_ns; 09016 } else { 09017 uri = xmlParseURI((const char *) URL); 09018 if (uri == NULL) { 09019 xmlNsErr(ctxt, XML_WAR_NS_URI, 09020 "xmlns:%s: '%s' is not a valid URI\n", 09021 attname, URL, NULL); 09022 } else { 09023 if ((ctxt->pedantic) && (uri->scheme == NULL)) { 09024 xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE, 09025 "xmlns:%s: URI %s is not absolute\n", 09026 attname, URL, NULL); 09027 } 09028 xmlFreeURI(uri); 09029 } 09030 } 09031 09032 /* 09033 * check that it's not a defined namespace 09034 */ 09035 for (j = 1;j <= nbNs;j++) 09036 if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname) 09037 break; 09038 if (j <= nbNs) 09039 xmlErrAttributeDup(ctxt, aprefix, attname); 09040 else 09041 if (nsPush(ctxt, attname, URL) > 0) nbNs++; 09042 skip_ns: 09043 if (alloc != 0) xmlFree(attvalue); 09044 SKIP_BLANKS; 09045 if (ctxt->input->base != base) goto base_changed; 09046 continue; 09047 } 09048 09049 /* 09050 * Add the pair to atts 09051 */ 09052 if ((atts == NULL) || (nbatts + 5 > maxatts)) { 09053 if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) { 09054 if (attvalue[len] == 0) 09055 xmlFree(attvalue); 09056 goto failed; 09057 } 09058 maxatts = ctxt->maxatts; 09059 atts = ctxt->atts; 09060 } 09061 ctxt->attallocs[nratts++] = alloc; 09062 atts[nbatts++] = attname; 09063 atts[nbatts++] = aprefix; 09064 atts[nbatts++] = NULL; /* the URI will be fetched later */ 09065 atts[nbatts++] = attvalue; 09066 attvalue += len; 09067 atts[nbatts++] = attvalue; 09068 /* 09069 * tag if some deallocation is needed 09070 */ 09071 if (alloc != 0) attval = 1; 09072 } else { 09073 if ((attvalue != NULL) && (attvalue[len] == 0)) 09074 xmlFree(attvalue); 09075 } 09076 09077 failed: 09078 09079 GROW 09080 if (ctxt->input->base != base) goto base_changed; 09081 if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>')))) 09082 break; 09083 if (!IS_BLANK_CH(RAW)) { 09084 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 09085 "attributes construct error\n"); 09086 break; 09087 } 09088 SKIP_BLANKS; 09089 if ((cons == ctxt->input->consumed) && (q == CUR_PTR) && 09090 (attname == NULL) && (attvalue == NULL)) { 09091 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, 09092 "xmlParseStartTag: problem parsing attributes\n"); 09093 break; 09094 } 09095 GROW; 09096 if (ctxt->input->base != base) goto base_changed; 09097 } 09098 09099 /* 09100 * The attributes defaulting 09101 */ 09102 if (ctxt->attsDefault != NULL) { 09103 xmlDefAttrsPtr defaults; 09104 09105 defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix); 09106 if (defaults != NULL) { 09107 for (i = 0;i < defaults->nbAttrs;i++) { 09108 attname = defaults->values[5 * i]; 09109 aprefix = defaults->values[5 * i + 1]; 09110 09111 /* 09112 * special work for namespaces defaulted defs 09113 */ 09114 if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) { 09115 /* 09116 * check that it's not a defined namespace 09117 */ 09118 for (j = 1;j <= nbNs;j++) 09119 if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL) 09120 break; 09121 if (j <= nbNs) continue; 09122 09123 nsname = xmlGetNamespace(ctxt, NULL); 09124 if (nsname != defaults->values[5 * i + 2]) { 09125 if (nsPush(ctxt, NULL, 09126 defaults->values[5 * i + 2]) > 0) 09127 nbNs++; 09128 } 09129 } else if (aprefix == ctxt->str_xmlns) { 09130 /* 09131 * check that it's not a defined namespace 09132 */ 09133 for (j = 1;j <= nbNs;j++) 09134 if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname) 09135 break; 09136 if (j <= nbNs) continue; 09137 09138 nsname = xmlGetNamespace(ctxt, attname); 09139 if (nsname != defaults->values[2]) { 09140 if (nsPush(ctxt, attname, 09141 defaults->values[5 * i + 2]) > 0) 09142 nbNs++; 09143 } 09144 } else { 09145 /* 09146 * check that it's not a defined attribute 09147 */ 09148 for (j = 0;j < nbatts;j+=5) { 09149 if ((attname == atts[j]) && (aprefix == atts[j+1])) 09150 break; 09151 } 09152 if (j < nbatts) continue; 09153 09154 if ((atts == NULL) || (nbatts + 5 > maxatts)) { 09155 if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) { 09156 return(NULL); 09157 } 09158 maxatts = ctxt->maxatts; 09159 atts = ctxt->atts; 09160 } 09161 atts[nbatts++] = attname; 09162 atts[nbatts++] = aprefix; 09163 if (aprefix == NULL) 09164 atts[nbatts++] = NULL; 09165 else 09166 atts[nbatts++] = xmlGetNamespace(ctxt, aprefix); 09167 atts[nbatts++] = defaults->values[5 * i + 2]; 09168 atts[nbatts++] = defaults->values[5 * i + 3]; 09169 if ((ctxt->standalone == 1) && 09170 (defaults->values[5 * i + 4] != NULL)) { 09171 xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED, 09172 "standalone: attribute %s on %s defaulted from external subset\n", 09173 attname, localname); 09174 } 09175 nbdef++; 09176 } 09177 } 09178 } 09179 } 09180 09181 /* 09182 * The attributes checkings 09183 */ 09184 for (i = 0; i < nbatts;i += 5) { 09185 /* 09186 * The default namespace does not apply to attribute names. 09187 */ 09188 if (atts[i + 1] != NULL) { 09189 nsname = xmlGetNamespace(ctxt, atts[i + 1]); 09190 if (nsname == NULL) { 09191 xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, 09192 "Namespace prefix %s for %s on %s is not defined\n", 09193 atts[i + 1], atts[i], localname); 09194 } 09195 atts[i + 2] = nsname; 09196 } else 09197 nsname = NULL; 09198 /* 09199 * [ WFC: Unique Att Spec ] 09200 * No attribute name may appear more than once in the same 09201 * start-tag or empty-element tag. 09202 * As extended by the Namespace in XML REC. 09203 */ 09204 for (j = 0; j < i;j += 5) { 09205 if (atts[i] == atts[j]) { 09206 if (atts[i+1] == atts[j+1]) { 09207 xmlErrAttributeDup(ctxt, atts[i+1], atts[i]); 09208 break; 09209 } 09210 if ((nsname != NULL) && (atts[j + 2] == nsname)) { 09211 xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED, 09212 "Namespaced Attribute %s in '%s' redefined\n", 09213 atts[i], nsname, NULL); 09214 break; 09215 } 09216 } 09217 } 09218 } 09219 09220 nsname = xmlGetNamespace(ctxt, prefix); 09221 if ((prefix != NULL) && (nsname == NULL)) { 09222 xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, 09223 "Namespace prefix %s on %s is not defined\n", 09224 prefix, localname, NULL); 09225 } 09226 *pref = prefix; 09227 *URI = nsname; 09228 09229 /* 09230 * SAX: Start of Element ! 09231 */ 09232 if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) && 09233 (!ctxt->disableSAX)) { 09234 if (nbNs > 0) 09235 ctxt->sax->startElementNs(ctxt->userData, localname, prefix, 09236 nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs], 09237 nbatts / 5, nbdef, atts); 09238 else 09239 ctxt->sax->startElementNs(ctxt->userData, localname, prefix, 09240 nsname, 0, NULL, nbatts / 5, nbdef, atts); 09241 } 09242 09243 /* 09244 * Free up attribute allocated strings if needed 09245 */ 09246 if (attval != 0) { 09247 for (i = 3,j = 0; j < nratts;i += 5,j++) 09248 if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL)) 09249 xmlFree((xmlChar *) atts[i]); 09250 } 09251 09252 return(localname); 09253 09254 base_changed: 09255 /* 09256 * the attribute strings are valid iif the base didn't changed 09257 */ 09258 if (attval != 0) { 09259 for (i = 3,j = 0; j < nratts;i += 5,j++) 09260 if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL)) 09261 xmlFree((xmlChar *) atts[i]); 09262 } 09263 ctxt->input->cur = ctxt->input->base + cur; 09264 ctxt->input->line = oldline; 09265 ctxt->input->col = oldcol; 09266 if (ctxt->wellFormed == 1) { 09267 goto reparse; 09268 } 09269 return(NULL); 09270 } 09271 09287 static void 09288 xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix, 09289 const xmlChar *URI, int line, int nsNr, int tlen) { 09290 const xmlChar *name; 09291 09292 GROW; 09293 if ((RAW != '<') || (NXT(1) != '/')) { 09294 xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL); 09295 return; 09296 } 09297 SKIP(2); 09298 09299 if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) { 09300 if (ctxt->input->cur[tlen] == '>') { 09301 ctxt->input->cur += tlen + 1; 09302 goto done; 09303 } 09304 ctxt->input->cur += tlen; 09305 name = (xmlChar*)1; 09306 } else { 09307 if (prefix == NULL) 09308 name = xmlParseNameAndCompare(ctxt, ctxt->name); 09309 else 09310 name = xmlParseQNameAndCompare(ctxt, ctxt->name, prefix); 09311 } 09312 09313 /* 09314 * We should definitely be at the ending "S? '>'" part 09315 */ 09316 GROW; 09317 SKIP_BLANKS; 09318 if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) { 09319 xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL); 09320 } else 09321 NEXT1; 09322 09323 /* 09324 * [ WFC: Element Type Match ] 09325 * The Name in an element's end-tag must match the element type in the 09326 * start-tag. 09327 * 09328 */ 09329 if (name != (xmlChar*)1) { 09330 if (name == NULL) name = BAD_CAST "unparseable"; 09331 if ((line == 0) && (ctxt->node != NULL)) 09332 line = ctxt->node->line; 09333 xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH, 09334 "Opening and ending tag mismatch: %s line %d and %s\n", 09335 ctxt->name, line, name); 09336 } 09337 09338 /* 09339 * SAX: End of Tag 09340 */ 09341 done: 09342 if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) && 09343 (!ctxt->disableSAX)) 09344 ctxt->sax->endElementNs(ctxt->userData, ctxt->name, prefix, URI); 09345 09346 spacePop(ctxt); 09347 if (nsNr != 0) 09348 nsPop(ctxt, nsNr); 09349 return; 09350 } 09351 09366 void 09367 xmlParseCDSect(xmlParserCtxtPtr ctxt) { 09368 xmlChar *buf = NULL; 09369 int len = 0; 09370 int size = XML_PARSER_BUFFER_SIZE; 09371 int r, rl; 09372 int s, sl; 09373 int cur, l; 09374 int count = 0; 09375 09376 /* Check 2.6.0 was NXT(0) not RAW */ 09377 if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) { 09378 SKIP(9); 09379 } else 09380 return; 09381 09382 ctxt->instate = XML_PARSER_CDATA_SECTION; 09383 r = CUR_CHAR(rl); 09384 if (!IS_CHAR(r)) { 09385 xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL); 09386 ctxt->instate = XML_PARSER_CONTENT; 09387 return; 09388 } 09389 NEXTL(rl); 09390 s = CUR_CHAR(sl); 09391 if (!IS_CHAR(s)) { 09392 xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL); 09393 ctxt->instate = XML_PARSER_CONTENT; 09394 return; 09395 } 09396 NEXTL(sl); 09397 cur = CUR_CHAR(l); 09398 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 09399 if (buf == NULL) { 09400 xmlErrMemory(ctxt, NULL); 09401 return; 09402 } 09403 while (IS_CHAR(cur) && 09404 ((r != ']') || (s != ']') || (cur != '>'))) { 09405 if (len + 5 >= size) { 09406 xmlChar *tmp; 09407 09408 size *= 2; 09409 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); 09410 if (tmp == NULL) { 09411 xmlFree(buf); 09412 xmlErrMemory(ctxt, NULL); 09413 return; 09414 } 09415 buf = tmp; 09416 } 09417 COPY_BUF(rl,buf,len,r); 09418 r = s; 09419 rl = sl; 09420 s = cur; 09421 sl = l; 09422 count++; 09423 if (count > 50) { 09424 GROW; 09425 count = 0; 09426 } 09427 NEXTL(l); 09428 cur = CUR_CHAR(l); 09429 } 09430 buf[len] = 0; 09431 ctxt->instate = XML_PARSER_CONTENT; 09432 if (cur != '>') { 09433 xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED, 09434 "CData section not finished\n%.50s\n", buf); 09435 xmlFree(buf); 09436 return; 09437 } 09438 NEXTL(l); 09439 09440 /* 09441 * OK the buffer is to be consumed as cdata. 09442 */ 09443 if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) { 09444 if (ctxt->sax->cdataBlock != NULL) 09445 ctxt->sax->cdataBlock(ctxt->userData, buf, len); 09446 else if (ctxt->sax->characters != NULL) 09447 ctxt->sax->characters(ctxt->userData, buf, len); 09448 } 09449 xmlFree(buf); 09450 } 09451 09461 void 09462 xmlParseContent(xmlParserCtxtPtr ctxt) { 09463 GROW; 09464 while ((RAW != 0) && 09465 ((RAW != '<') || (NXT(1) != '/')) && 09466 (ctxt->instate != XML_PARSER_EOF)) { 09467 const xmlChar *test = CUR_PTR; 09468 unsigned int cons = ctxt->input->consumed; 09469 const xmlChar *cur = ctxt->input->cur; 09470 09471 /* 09472 * First case : a Processing Instruction. 09473 */ 09474 if ((*cur == '<') && (cur[1] == '?')) { 09475 xmlParsePI(ctxt); 09476 } 09477 09478 /* 09479 * Second case : a CDSection 09480 */ 09481 /* 2.6.0 test was *cur not RAW */ 09482 else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) { 09483 xmlParseCDSect(ctxt); 09484 } 09485 09486 /* 09487 * Third case : a comment 09488 */ 09489 else if ((*cur == '<') && (NXT(1) == '!') && 09490 (NXT(2) == '-') && (NXT(3) == '-')) { 09491 xmlParseComment(ctxt); 09492 ctxt->instate = XML_PARSER_CONTENT; 09493 } 09494 09495 /* 09496 * Fourth case : a sub-element. 09497 */ 09498 else if (*cur == '<') { 09499 xmlParseElement(ctxt); 09500 } 09501 09502 /* 09503 * Fifth case : a reference. If if has not been resolved, 09504 * parsing returns it's Name, create the node 09505 */ 09506 09507 else if (*cur == '&') { 09508 xmlParseReference(ctxt); 09509 } 09510 09511 /* 09512 * Last case, text. Note that References are handled directly. 09513 */ 09514 else { 09515 xmlParseCharData(ctxt, 0); 09516 } 09517 09518 GROW; 09519 /* 09520 * Pop-up of finished entities. 09521 */ 09522 while ((RAW == 0) && (ctxt->inputNr > 1)) 09523 xmlPopInput(ctxt); 09524 SHRINK; 09525 09526 if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) { 09527 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, 09528 "detected an error in element content\n"); 09529 ctxt->instate = XML_PARSER_EOF; 09530 break; 09531 } 09532 } 09533 } 09534 09549 void 09550 xmlParseElement(xmlParserCtxtPtr ctxt) { 09551 const xmlChar *name; 09552 const xmlChar *prefix = NULL; 09553 const xmlChar *URI = NULL; 09554 xmlParserNodeInfo node_info; 09555 int line, tlen; 09556 xmlNodePtr ret; 09557 int nsNr = ctxt->nsNr; 09558 09559 if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) && 09560 ((ctxt->options & XML_PARSE_HUGE) == 0)) { 09561 xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR, 09562 "Excessive depth in document: %d use XML_PARSE_HUGE option\n", 09563 xmlParserMaxDepth); 09564 ctxt->instate = XML_PARSER_EOF; 09565 return; 09566 } 09567 09568 /* Capture start position */ 09569 if (ctxt->record_info) { 09570 node_info.begin_pos = ctxt->input->consumed + 09571 (CUR_PTR - ctxt->input->base); 09572 node_info.begin_line = ctxt->input->line; 09573 } 09574 09575 if (ctxt->spaceNr == 0) 09576 spacePush(ctxt, -1); 09577 else if (*ctxt->space == -2) 09578 spacePush(ctxt, -1); 09579 else 09580 spacePush(ctxt, *ctxt->space); 09581 09582 line = ctxt->input->line; 09583 #ifdef LIBXML_SAX1_ENABLED 09584 if (ctxt->sax2) 09585 #endif /* LIBXML_SAX1_ENABLED */ 09586 name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen); 09587 #ifdef LIBXML_SAX1_ENABLED 09588 else 09589 name = xmlParseStartTag(ctxt); 09590 #endif /* LIBXML_SAX1_ENABLED */ 09591 if (name == NULL) { 09592 spacePop(ctxt); 09593 return; 09594 } 09595 namePush(ctxt, name); 09596 ret = ctxt->node; 09597 09598 #ifdef LIBXML_VALID_ENABLED 09599 /* 09600 * [ VC: Root Element Type ] 09601 * The Name in the document type declaration must match the element 09602 * type of the root element. 09603 */ 09604 if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc && 09605 ctxt->node && (ctxt->node == ctxt->myDoc->children)) 09606 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); 09607 #endif /* LIBXML_VALID_ENABLED */ 09608 09609 /* 09610 * Check for an Empty Element. 09611 */ 09612 if ((RAW == '/') && (NXT(1) == '>')) { 09613 SKIP(2); 09614 if (ctxt->sax2) { 09615 if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) && 09616 (!ctxt->disableSAX)) 09617 ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI); 09618 #ifdef LIBXML_SAX1_ENABLED 09619 } else { 09620 if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) && 09621 (!ctxt->disableSAX)) 09622 ctxt->sax->endElement(ctxt->userData, name); 09623 #endif /* LIBXML_SAX1_ENABLED */ 09624 } 09625 namePop(ctxt); 09626 spacePop(ctxt); 09627 if (nsNr != ctxt->nsNr) 09628 nsPop(ctxt, ctxt->nsNr - nsNr); 09629 if ( ret != NULL && ctxt->record_info ) { 09630 node_info.end_pos = ctxt->input->consumed + 09631 (CUR_PTR - ctxt->input->base); 09632 node_info.end_line = ctxt->input->line; 09633 node_info.node = ret; 09634 xmlParserAddNodeInfo(ctxt, &node_info); 09635 } 09636 return; 09637 } 09638 if (RAW == '>') { 09639 NEXT1; 09640 } else { 09641 xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED, 09642 "Couldn't find end of Start Tag %s line %d\n", 09643 name, line, NULL); 09644 09645 /* 09646 * end of parsing of this node. 09647 */ 09648 nodePop(ctxt); 09649 namePop(ctxt); 09650 spacePop(ctxt); 09651 if (nsNr != ctxt->nsNr) 09652 nsPop(ctxt, ctxt->nsNr - nsNr); 09653 09654 /* 09655 * Capture end position and add node 09656 */ 09657 if ( ret != NULL && ctxt->record_info ) { 09658 node_info.end_pos = ctxt->input->consumed + 09659 (CUR_PTR - ctxt->input->base); 09660 node_info.end_line = ctxt->input->line; 09661 node_info.node = ret; 09662 xmlParserAddNodeInfo(ctxt, &node_info); 09663 } 09664 return; 09665 } 09666 09667 /* 09668 * Parse the content of the element: 09669 */ 09670 xmlParseContent(ctxt); 09671 if (!IS_BYTE_CHAR(RAW)) { 09672 xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED, 09673 "Premature end of data in tag %s line %d\n", 09674 name, line, NULL); 09675 09676 /* 09677 * end of parsing of this node. 09678 */ 09679 nodePop(ctxt); 09680 namePop(ctxt); 09681 spacePop(ctxt); 09682 if (nsNr != ctxt->nsNr) 09683 nsPop(ctxt, ctxt->nsNr - nsNr); 09684 return; 09685 } 09686 09687 /* 09688 * parse the end of tag: '</' should be here. 09689 */ 09690 if (ctxt->sax2) { 09691 xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen); 09692 namePop(ctxt); 09693 } 09694 #ifdef LIBXML_SAX1_ENABLED 09695 else 09696 xmlParseEndTag1(ctxt, line); 09697 #endif /* LIBXML_SAX1_ENABLED */ 09698 09699 /* 09700 * Capture end position and add node 09701 */ 09702 if ( ret != NULL && ctxt->record_info ) { 09703 node_info.end_pos = ctxt->input->consumed + 09704 (CUR_PTR - ctxt->input->base); 09705 node_info.end_line = ctxt->input->line; 09706 node_info.node = ret; 09707 xmlParserAddNodeInfo(ctxt, &node_info); 09708 } 09709 } 09710 09723 xmlChar * 09724 xmlParseVersionNum(xmlParserCtxtPtr ctxt) { 09725 xmlChar *buf = NULL; 09726 int len = 0; 09727 int size = 10; 09728 xmlChar cur; 09729 09730 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 09731 if (buf == NULL) { 09732 xmlErrMemory(ctxt, NULL); 09733 return(NULL); 09734 } 09735 cur = CUR; 09736 if (!((cur >= '0') && (cur <= '9'))) { 09737 xmlFree(buf); 09738 return(NULL); 09739 } 09740 buf[len++] = cur; 09741 NEXT; 09742 cur=CUR; 09743 if (cur != '.') { 09744 xmlFree(buf); 09745 return(NULL); 09746 } 09747 buf[len++] = cur; 09748 NEXT; 09749 cur=CUR; 09750 while ((cur >= '0') && (cur <= '9')) { 09751 if (len + 1 >= size) { 09752 xmlChar *tmp; 09753 09754 size *= 2; 09755 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); 09756 if (tmp == NULL) { 09757 xmlFree(buf); 09758 xmlErrMemory(ctxt, NULL); 09759 return(NULL); 09760 } 09761 buf = tmp; 09762 } 09763 buf[len++] = cur; 09764 NEXT; 09765 cur=CUR; 09766 } 09767 buf[len] = 0; 09768 return(buf); 09769 } 09770 09784 xmlChar * 09785 xmlParseVersionInfo(xmlParserCtxtPtr ctxt) { 09786 xmlChar *version = NULL; 09787 09788 if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) { 09789 SKIP(7); 09790 SKIP_BLANKS; 09791 if (RAW != '=') { 09792 xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL); 09793 return(NULL); 09794 } 09795 NEXT; 09796 SKIP_BLANKS; 09797 if (RAW == '"') { 09798 NEXT; 09799 version = xmlParseVersionNum(ctxt); 09800 if (RAW != '"') { 09801 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL); 09802 } else 09803 NEXT; 09804 } else if (RAW == '\''){ 09805 NEXT; 09806 version = xmlParseVersionNum(ctxt); 09807 if (RAW != '\'') { 09808 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL); 09809 } else 09810 NEXT; 09811 } else { 09812 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL); 09813 } 09814 } 09815 return(version); 09816 } 09817 09828 xmlChar * 09829 xmlParseEncName(xmlParserCtxtPtr ctxt) { 09830 xmlChar *buf = NULL; 09831 int len = 0; 09832 int size = 10; 09833 xmlChar cur; 09834 09835 cur = CUR; 09836 if (((cur >= 'a') && (cur <= 'z')) || 09837 ((cur >= 'A') && (cur <= 'Z'))) { 09838 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar)); 09839 if (buf == NULL) { 09840 xmlErrMemory(ctxt, NULL); 09841 return(NULL); 09842 } 09843 09844 buf[len++] = cur; 09845 NEXT; 09846 cur = CUR; 09847 while (((cur >= 'a') && (cur <= 'z')) || 09848 ((cur >= 'A') && (cur <= 'Z')) || 09849 ((cur >= '0') && (cur <= '9')) || 09850 (cur == '.') || (cur == '_') || 09851 (cur == '-')) { 09852 if (len + 1 >= size) { 09853 xmlChar *tmp; 09854 09855 size *= 2; 09856 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); 09857 if (tmp == NULL) { 09858 xmlErrMemory(ctxt, NULL); 09859 xmlFree(buf); 09860 return(NULL); 09861 } 09862 buf = tmp; 09863 } 09864 buf[len++] = cur; 09865 NEXT; 09866 cur = CUR; 09867 if (cur == 0) { 09868 SHRINK; 09869 GROW; 09870 cur = CUR; 09871 } 09872 } 09873 buf[len] = 0; 09874 } else { 09875 xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL); 09876 } 09877 return(buf); 09878 } 09879 09893 const xmlChar * 09894 xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) { 09895 xmlChar *encoding = NULL; 09896 09897 SKIP_BLANKS; 09898 if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) { 09899 SKIP(8); 09900 SKIP_BLANKS; 09901 if (RAW != '=') { 09902 xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL); 09903 return(NULL); 09904 } 09905 NEXT; 09906 SKIP_BLANKS; 09907 if (RAW == '"') { 09908 NEXT; 09909 encoding = xmlParseEncName(ctxt); 09910 if (RAW != '"') { 09911 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL); 09912 } else 09913 NEXT; 09914 } else if (RAW == '\''){ 09915 NEXT; 09916 encoding = xmlParseEncName(ctxt); 09917 if (RAW != '\'') { 09918 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL); 09919 } else 09920 NEXT; 09921 } else { 09922 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL); 09923 } 09924 /* 09925 * UTF-16 encoding stwich has already taken place at this stage, 09926 * more over the little-endian/big-endian selection is already done 09927 */ 09928 if ((encoding != NULL) && 09929 ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) || 09930 (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) { 09931 /* 09932 * If no encoding was passed to the parser, that we are 09933 * using UTF-16 and no decoder is present i.e. the 09934 * document is apparently UTF-8 compatible, then raise an 09935 * encoding mismatch fatal error 09936 */ 09937 if ((ctxt->encoding == NULL) && 09938 (ctxt->input->buf != NULL) && 09939 (ctxt->input->buf->encoder == NULL)) { 09940 xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING, 09941 "Document labelled UTF-16 but has UTF-8 content\n"); 09942 } 09943 if (ctxt->encoding != NULL) 09944 xmlFree((xmlChar *) ctxt->encoding); 09945 ctxt->encoding = encoding; 09946 } 09947 /* 09948 * UTF-8 encoding is handled natively 09949 */ 09950 else if ((encoding != NULL) && 09951 ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) || 09952 (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) { 09953 if (ctxt->encoding != NULL) 09954 xmlFree((xmlChar *) ctxt->encoding); 09955 ctxt->encoding = encoding; 09956 } 09957 else if (encoding != NULL) { 09958 xmlCharEncodingHandlerPtr handler; 09959 09960 if (ctxt->input->encoding != NULL) 09961 xmlFree((xmlChar *) ctxt->input->encoding); 09962 ctxt->input->encoding = encoding; 09963 09964 handler = xmlFindCharEncodingHandler((const char *) encoding); 09965 if (handler != NULL) { 09966 xmlSwitchToEncoding(ctxt, handler); 09967 } else { 09968 xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING, 09969 "Unsupported encoding %s\n", encoding); 09970 return(NULL); 09971 } 09972 } 09973 } 09974 return(encoding); 09975 } 09976 10008 int 10009 xmlParseSDDecl(xmlParserCtxtPtr ctxt) { 10010 int standalone = -2; 10011 10012 SKIP_BLANKS; 10013 if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) { 10014 SKIP(10); 10015 SKIP_BLANKS; 10016 if (RAW != '=') { 10017 xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL); 10018 return(standalone); 10019 } 10020 NEXT; 10021 SKIP_BLANKS; 10022 if (RAW == '\''){ 10023 NEXT; 10024 if ((RAW == 'n') && (NXT(1) == 'o')) { 10025 standalone = 0; 10026 SKIP(2); 10027 } else if ((RAW == 'y') && (NXT(1) == 'e') && 10028 (NXT(2) == 's')) { 10029 standalone = 1; 10030 SKIP(3); 10031 } else { 10032 xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL); 10033 } 10034 if (RAW != '\'') { 10035 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL); 10036 } else 10037 NEXT; 10038 } else if (RAW == '"'){ 10039 NEXT; 10040 if ((RAW == 'n') && (NXT(1) == 'o')) { 10041 standalone = 0; 10042 SKIP(2); 10043 } else if ((RAW == 'y') && (NXT(1) == 'e') && 10044 (NXT(2) == 's')) { 10045 standalone = 1; 10046 SKIP(3); 10047 } else { 10048 xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL); 10049 } 10050 if (RAW != '"') { 10051 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL); 10052 } else 10053 NEXT; 10054 } else { 10055 xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL); 10056 } 10057 } 10058 return(standalone); 10059 } 10060 10070 void 10071 xmlParseXMLDecl(xmlParserCtxtPtr ctxt) { 10072 xmlChar *version; 10073 10074 /* 10075 * This value for standalone indicates that the document has an 10076 * XML declaration but it does not have a standalone attribute. 10077 * It will be overwritten later if a standalone attribute is found. 10078 */ 10079 ctxt->input->standalone = -2; 10080 10081 /* 10082 * We know that '<?xml' is here. 10083 */ 10084 SKIP(5); 10085 10086 if (!IS_BLANK_CH(RAW)) { 10087 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, 10088 "Blank needed after '<?xml'\n"); 10089 } 10090 SKIP_BLANKS; 10091 10092 /* 10093 * We must have the VersionInfo here. 10094 */ 10095 version = xmlParseVersionInfo(ctxt); 10096 if (version == NULL) { 10097 xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL); 10098 } else { 10099 if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) { 10100 /* 10101 * Changed here for XML-1.0 5th edition 10102 */ 10103 if (ctxt->options & XML_PARSE_OLD10) { 10104 xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION, 10105 "Unsupported version '%s'\n", 10106 version); 10107 } else { 10108 if ((version[0] == '1') && ((version[1] == '.'))) { 10109 xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION, 10110 "Unsupported version '%s'\n", 10111 version, NULL); 10112 } else { 10113 xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION, 10114 "Unsupported version '%s'\n", 10115 version); 10116 } 10117 } 10118 } 10119 if (ctxt->version != NULL) 10120 xmlFree((void *) ctxt->version); 10121 ctxt->version = version; 10122 } 10123 10124 /* 10125 * We may have the encoding declaration 10126 */ 10127 if (!IS_BLANK_CH(RAW)) { 10128 if ((RAW == '?') && (NXT(1) == '>')) { 10129 SKIP(2); 10130 return; 10131 } 10132 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n"); 10133 } 10134 xmlParseEncodingDecl(ctxt); 10135 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) { 10136 /* 10137 * The XML REC instructs us to stop parsing right here 10138 */ 10139 return; 10140 } 10141 10142 /* 10143 * We may have the standalone status. 10144 */ 10145 if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) { 10146 if ((RAW == '?') && (NXT(1) == '>')) { 10147 SKIP(2); 10148 return; 10149 } 10150 xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n"); 10151 } 10152 10153 /* 10154 * We can grow the input buffer freely at that point 10155 */ 10156 GROW; 10157 10158 SKIP_BLANKS; 10159 ctxt->input->standalone = xmlParseSDDecl(ctxt); 10160 10161 SKIP_BLANKS; 10162 if ((RAW == '?') && (NXT(1) == '>')) { 10163 SKIP(2); 10164 } else if (RAW == '>') { 10165 /* Deprecated old WD ... */ 10166 xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL); 10167 NEXT; 10168 } else { 10169 xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL); 10170 MOVETO_ENDTAG(CUR_PTR); 10171 NEXT; 10172 } 10173 } 10174 10184 void 10185 xmlParseMisc(xmlParserCtxtPtr ctxt) { 10186 while (((RAW == '<') && (NXT(1) == '?')) || 10187 (CMP4(CUR_PTR, '<', '!', '-', '-')) || 10188 IS_BLANK_CH(CUR)) { 10189 if ((RAW == '<') && (NXT(1) == '?')) { 10190 xmlParsePI(ctxt); 10191 } else if (IS_BLANK_CH(CUR)) { 10192 NEXT; 10193 } else 10194 xmlParseComment(ctxt); 10195 } 10196 } 10197 10213 int 10214 xmlParseDocument(xmlParserCtxtPtr ctxt) { 10215 xmlChar start[4]; 10216 xmlCharEncoding enc; 10217 10218 xmlInitParser(); 10219 10220 if ((ctxt == NULL) || (ctxt->input == NULL)) 10221 return(-1); 10222 10223 GROW; 10224 10225 /* 10226 * SAX: detecting the level. 10227 */ 10228 xmlDetectSAX2(ctxt); 10229 10230 /* 10231 * SAX: beginning of the document processing. 10232 */ 10233 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) 10234 ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator); 10235 10236 if ((ctxt->encoding == NULL) && 10237 ((ctxt->input->end - ctxt->input->cur) >= 4)) { 10238 /* 10239 * Get the 4 first bytes and decode the charset 10240 * if enc != XML_CHAR_ENCODING_NONE 10241 * plug some encoding conversion routines. 10242 */ 10243 start[0] = RAW; 10244 start[1] = NXT(1); 10245 start[2] = NXT(2); 10246 start[3] = NXT(3); 10247 enc = xmlDetectCharEncoding(&start[0], 4); 10248 if (enc != XML_CHAR_ENCODING_NONE) { 10249 xmlSwitchEncoding(ctxt, enc); 10250 } 10251 } 10252 10253 10254 if (CUR == 0) { 10255 xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL); 10256 } 10257 10258 /* 10259 * Check for the XMLDecl in the Prolog. 10260 * do not GROW here to avoid the detected encoder to decode more 10261 * than just the first line, unless the amount of data is really 10262 * too small to hold "<?xml version="1.0" encoding="foo" 10263 */ 10264 if ((ctxt->input->end - ctxt->input->cur) < 35) { 10265 GROW; 10266 } 10267 if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) { 10268 10269 /* 10270 * Note that we will switch encoding on the fly. 10271 */ 10272 xmlParseXMLDecl(ctxt); 10273 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) { 10274 /* 10275 * The XML REC instructs us to stop parsing right here 10276 */ 10277 return(-1); 10278 } 10279 ctxt->standalone = ctxt->input->standalone; 10280 SKIP_BLANKS; 10281 } else { 10282 ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION); 10283 } 10284 if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX)) 10285 ctxt->sax->startDocument(ctxt->userData); 10286 10287 /* 10288 * The Misc part of the Prolog 10289 */ 10290 GROW; 10291 xmlParseMisc(ctxt); 10292 10293 /* 10294 * Then possibly doc type declaration(s) and more Misc 10295 * (doctypedecl Misc*)? 10296 */ 10297 GROW; 10298 if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) { 10299 10300 ctxt->inSubset = 1; 10301 xmlParseDocTypeDecl(ctxt); 10302 if (RAW == '[') { 10303 ctxt->instate = XML_PARSER_DTD; 10304 xmlParseInternalSubset(ctxt); 10305 } 10306 10307 /* 10308 * Create and update the external subset. 10309 */ 10310 ctxt->inSubset = 2; 10311 if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) && 10312 (!ctxt->disableSAX)) 10313 ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName, 10314 ctxt->extSubSystem, ctxt->extSubURI); 10315 ctxt->inSubset = 0; 10316 10317 xmlCleanSpecialAttr(ctxt); 10318 10319 ctxt->instate = XML_PARSER_PROLOG; 10320 xmlParseMisc(ctxt); 10321 } 10322 10323 /* 10324 * Time to start parsing the tree itself 10325 */ 10326 GROW; 10327 if (RAW != '<') { 10328 xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY, 10329 "Start tag expected, '<' not found\n"); 10330 } else { 10331 ctxt->instate = XML_PARSER_CONTENT; 10332 xmlParseElement(ctxt); 10333 ctxt->instate = XML_PARSER_EPILOG; 10334 10335 10336 /* 10337 * The Misc part at the end 10338 */ 10339 xmlParseMisc(ctxt); 10340 10341 if (RAW != 0) { 10342 xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); 10343 } 10344 ctxt->instate = XML_PARSER_EOF; 10345 } 10346 10347 /* 10348 * SAX: end of the document processing. 10349 */ 10350 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) 10351 ctxt->sax->endDocument(ctxt->userData); 10352 10353 /* 10354 * Remove locally kept entity definitions if the tree was not built 10355 */ 10356 if ((ctxt->myDoc != NULL) && 10357 (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) { 10358 xmlFreeDoc(ctxt->myDoc); 10359 ctxt->myDoc = NULL; 10360 } 10361 10362 if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) { 10363 ctxt->myDoc->properties |= XML_DOC_WELLFORMED; 10364 if (ctxt->valid) 10365 ctxt->myDoc->properties |= XML_DOC_DTDVALID; 10366 if (ctxt->nsWellFormed) 10367 ctxt->myDoc->properties |= XML_DOC_NSVALID; 10368 if (ctxt->options & XML_PARSE_OLD10) 10369 ctxt->myDoc->properties |= XML_DOC_OLD10; 10370 } 10371 if (! ctxt->wellFormed) { 10372 ctxt->valid = 0; 10373 return(-1); 10374 } 10375 return(0); 10376 } 10377 10392 int 10393 xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) { 10394 xmlChar start[4]; 10395 xmlCharEncoding enc; 10396 10397 if ((ctxt == NULL) || (ctxt->input == NULL)) 10398 return(-1); 10399 10400 xmlDefaultSAXHandlerInit(); 10401 10402 xmlDetectSAX2(ctxt); 10403 10404 GROW; 10405 10406 /* 10407 * SAX: beginning of the document processing. 10408 */ 10409 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) 10410 ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator); 10411 10412 /* 10413 * Get the 4 first bytes and decode the charset 10414 * if enc != XML_CHAR_ENCODING_NONE 10415 * plug some encoding conversion routines. 10416 */ 10417 if ((ctxt->input->end - ctxt->input->cur) >= 4) { 10418 start[0] = RAW; 10419 start[1] = NXT(1); 10420 start[2] = NXT(2); 10421 start[3] = NXT(3); 10422 enc = xmlDetectCharEncoding(start, 4); 10423 if (enc != XML_CHAR_ENCODING_NONE) { 10424 xmlSwitchEncoding(ctxt, enc); 10425 } 10426 } 10427 10428 10429 if (CUR == 0) { 10430 xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL); 10431 } 10432 10433 /* 10434 * Check for the XMLDecl in the Prolog. 10435 */ 10436 GROW; 10437 if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) { 10438 10439 /* 10440 * Note that we will switch encoding on the fly. 10441 */ 10442 xmlParseXMLDecl(ctxt); 10443 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) { 10444 /* 10445 * The XML REC instructs us to stop parsing right here 10446 */ 10447 return(-1); 10448 } 10449 SKIP_BLANKS; 10450 } else { 10451 ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION); 10452 } 10453 if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX)) 10454 ctxt->sax->startDocument(ctxt->userData); 10455 10456 /* 10457 * Doing validity checking on chunk doesn't make sense 10458 */ 10459 ctxt->instate = XML_PARSER_CONTENT; 10460 ctxt->validate = 0; 10461 ctxt->loadsubset = 0; 10462 ctxt->depth = 0; 10463 10464 xmlParseContent(ctxt); 10465 10466 if ((RAW == '<') && (NXT(1) == '/')) { 10467 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 10468 } else if (RAW != 0) { 10469 xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); 10470 } 10471 10472 /* 10473 * SAX: end of the document processing. 10474 */ 10475 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) 10476 ctxt->sax->endDocument(ctxt->userData); 10477 10478 if (! ctxt->wellFormed) return(-1); 10479 return(0); 10480 } 10481 10482 #ifdef LIBXML_PUSH_ENABLED 10483 /************************************************************************ 10484 * * 10485 * Progressive parsing interfaces * 10486 * * 10487 ************************************************************************/ 10488 10505 static int 10506 xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first, 10507 xmlChar next, xmlChar third) { 10508 int base, len; 10509 xmlParserInputPtr in; 10510 const xmlChar *buf; 10511 10512 in = ctxt->input; 10513 if (in == NULL) return(-1); 10514 base = in->cur - in->base; 10515 if (base < 0) return(-1); 10516 if (ctxt->checkIndex > base) 10517 base = ctxt->checkIndex; 10518 if (in->buf == NULL) { 10519 buf = in->base; 10520 len = in->length; 10521 } else { 10522 buf = in->buf->buffer->content; 10523 len = in->buf->buffer->use; 10524 } 10525 /* take into account the sequence length */ 10526 if (third) len -= 2; 10527 else if (next) len --; 10528 for (;base < len;base++) { 10529 if (buf[base] == first) { 10530 if (third != 0) { 10531 if ((buf[base + 1] != next) || 10532 (buf[base + 2] != third)) continue; 10533 } else if (next != 0) { 10534 if (buf[base + 1] != next) continue; 10535 } 10536 ctxt->checkIndex = 0; 10537 #ifdef DEBUG_PUSH 10538 if (next == 0) 10539 xmlGenericError(xmlGenericErrorContext, 10540 "PP: lookup '%c' found at %d\n", 10541 first, base); 10542 else if (third == 0) 10543 xmlGenericError(xmlGenericErrorContext, 10544 "PP: lookup '%c%c' found at %d\n", 10545 first, next, base); 10546 else 10547 xmlGenericError(xmlGenericErrorContext, 10548 "PP: lookup '%c%c%c' found at %d\n", 10549 first, next, third, base); 10550 #endif 10551 return(base - (in->cur - in->base)); 10552 } 10553 } 10554 ctxt->checkIndex = base; 10555 #ifdef DEBUG_PUSH 10556 if (next == 0) 10557 xmlGenericError(xmlGenericErrorContext, 10558 "PP: lookup '%c' failed\n", first); 10559 else if (third == 0) 10560 xmlGenericError(xmlGenericErrorContext, 10561 "PP: lookup '%c%c' failed\n", first, next); 10562 else 10563 xmlGenericError(xmlGenericErrorContext, 10564 "PP: lookup '%c%c%c' failed\n", first, next, third); 10565 #endif 10566 return(-1); 10567 } 10568 10577 static void 10578 xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt, 10579 const xmlChar **lastgt) { 10580 const xmlChar *tmp; 10581 10582 if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) { 10583 xmlGenericError(xmlGenericErrorContext, 10584 "Internal error: xmlParseGetLasts\n"); 10585 return; 10586 } 10587 if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) { 10588 tmp = ctxt->input->end; 10589 tmp--; 10590 while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--; 10591 if (tmp < ctxt->input->base) { 10592 *lastlt = NULL; 10593 *lastgt = NULL; 10594 } else { 10595 *lastlt = tmp; 10596 tmp++; 10597 while ((tmp < ctxt->input->end) && (*tmp != '>')) { 10598 if (*tmp == '\'') { 10599 tmp++; 10600 while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++; 10601 if (tmp < ctxt->input->end) tmp++; 10602 } else if (*tmp == '"') { 10603 tmp++; 10604 while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++; 10605 if (tmp < ctxt->input->end) tmp++; 10606 } else 10607 tmp++; 10608 } 10609 if (tmp < ctxt->input->end) 10610 *lastgt = tmp; 10611 else { 10612 tmp = *lastlt; 10613 tmp--; 10614 while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--; 10615 if (tmp >= ctxt->input->base) 10616 *lastgt = tmp; 10617 else 10618 *lastgt = NULL; 10619 } 10620 } 10621 } else { 10622 *lastlt = NULL; 10623 *lastgt = NULL; 10624 } 10625 } 10636 static int 10637 xmlCheckCdataPush(const xmlChar *utf, int len) { 10638 int ix; 10639 unsigned char c; 10640 int codepoint; 10641 10642 if ((utf == NULL) || (len <= 0)) 10643 return(0); 10644 10645 for (ix = 0; ix < len;) { /* string is 0-terminated */ 10646 c = utf[ix]; 10647 if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */ 10648 if (c >= 0x20) 10649 ix++; 10650 else if ((c == 0xA) || (c == 0xD) || (c == 0x9)) 10651 ix++; 10652 else 10653 return(-ix); 10654 } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */ 10655 if (ix + 2 > len) return(ix); 10656 if ((utf[ix+1] & 0xc0 ) != 0x80) 10657 return(-ix); 10658 codepoint = (utf[ix] & 0x1f) << 6; 10659 codepoint |= utf[ix+1] & 0x3f; 10660 if (!xmlIsCharQ(codepoint)) 10661 return(-ix); 10662 ix += 2; 10663 } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */ 10664 if (ix + 3 > len) return(ix); 10665 if (((utf[ix+1] & 0xc0) != 0x80) || 10666 ((utf[ix+2] & 0xc0) != 0x80)) 10667 return(-ix); 10668 codepoint = (utf[ix] & 0xf) << 12; 10669 codepoint |= (utf[ix+1] & 0x3f) << 6; 10670 codepoint |= utf[ix+2] & 0x3f; 10671 if (!xmlIsCharQ(codepoint)) 10672 return(-ix); 10673 ix += 3; 10674 } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */ 10675 if (ix + 4 > len) return(ix); 10676 if (((utf[ix+1] & 0xc0) != 0x80) || 10677 ((utf[ix+2] & 0xc0) != 0x80) || 10678 ((utf[ix+3] & 0xc0) != 0x80)) 10679 return(-ix); 10680 codepoint = (utf[ix] & 0x7) << 18; 10681 codepoint |= (utf[ix+1] & 0x3f) << 12; 10682 codepoint |= (utf[ix+2] & 0x3f) << 6; 10683 codepoint |= utf[ix+3] & 0x3f; 10684 if (!xmlIsCharQ(codepoint)) 10685 return(-ix); 10686 ix += 4; 10687 } else /* unknown encoding */ 10688 return(-ix); 10689 } 10690 return(ix); 10691 } 10692 10702 static int 10703 xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { 10704 int ret = 0; 10705 int avail, tlen; 10706 xmlChar cur, next; 10707 const xmlChar *lastlt, *lastgt; 10708 10709 if (ctxt->input == NULL) 10710 return(0); 10711 10712 #ifdef DEBUG_PUSH 10713 switch (ctxt->instate) { 10714 case XML_PARSER_EOF: 10715 xmlGenericError(xmlGenericErrorContext, 10716 "PP: try EOF\n"); break; 10717 case XML_PARSER_START: 10718 xmlGenericError(xmlGenericErrorContext, 10719 "PP: try START\n"); break; 10720 case XML_PARSER_MISC: 10721 xmlGenericError(xmlGenericErrorContext, 10722 "PP: try MISC\n");break; 10723 case XML_PARSER_COMMENT: 10724 xmlGenericError(xmlGenericErrorContext, 10725 "PP: try COMMENT\n");break; 10726 case XML_PARSER_PROLOG: 10727 xmlGenericError(xmlGenericErrorContext, 10728 "PP: try PROLOG\n");break; 10729 case XML_PARSER_START_TAG: 10730 xmlGenericError(xmlGenericErrorContext, 10731 "PP: try START_TAG\n");break; 10732 case XML_PARSER_CONTENT: 10733 xmlGenericError(xmlGenericErrorContext, 10734 "PP: try CONTENT\n");break; 10735 case XML_PARSER_CDATA_SECTION: 10736 xmlGenericError(xmlGenericErrorContext, 10737 "PP: try CDATA_SECTION\n");break; 10738 case XML_PARSER_END_TAG: 10739 xmlGenericError(xmlGenericErrorContext, 10740 "PP: try END_TAG\n");break; 10741 case XML_PARSER_ENTITY_DECL: 10742 xmlGenericError(xmlGenericErrorContext, 10743 "PP: try ENTITY_DECL\n");break; 10744 case XML_PARSER_ENTITY_VALUE: 10745 xmlGenericError(xmlGenericErrorContext, 10746 "PP: try ENTITY_VALUE\n");break; 10747 case XML_PARSER_ATTRIBUTE_VALUE: 10748 xmlGenericError(xmlGenericErrorContext, 10749 "PP: try ATTRIBUTE_VALUE\n");break; 10750 case XML_PARSER_DTD: 10751 xmlGenericError(xmlGenericErrorContext, 10752 "PP: try DTD\n");break; 10753 case XML_PARSER_EPILOG: 10754 xmlGenericError(xmlGenericErrorContext, 10755 "PP: try EPILOG\n");break; 10756 case XML_PARSER_PI: 10757 xmlGenericError(xmlGenericErrorContext, 10758 "PP: try PI\n");break; 10759 case XML_PARSER_IGNORE: 10760 xmlGenericError(xmlGenericErrorContext, 10761 "PP: try IGNORE\n");break; 10762 } 10763 #endif 10764 10765 if ((ctxt->input != NULL) && 10766 (ctxt->input->cur - ctxt->input->base > 4096)) { 10767 xmlSHRINK(ctxt); 10768 ctxt->checkIndex = 0; 10769 } 10770 xmlParseGetLasts(ctxt, &lastlt, &lastgt); 10771 10772 while (1) { 10773 if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1)) 10774 return(0); 10775 10776 10777 /* 10778 * Pop-up of finished entities. 10779 */ 10780 while ((RAW == 0) && (ctxt->inputNr > 1)) 10781 xmlPopInput(ctxt); 10782 10783 if (ctxt->input == NULL) break; 10784 if (ctxt->input->buf == NULL) 10785 avail = ctxt->input->length - 10786 (ctxt->input->cur - ctxt->input->base); 10787 else { 10788 /* 10789 * If we are operating on converted input, try to flush 10790 * remainng chars to avoid them stalling in the non-converted 10791 * buffer. 10792 */ 10793 if ((ctxt->input->buf->raw != NULL) && 10794 (ctxt->input->buf->raw->use > 0)) { 10795 int base = ctxt->input->base - 10796 ctxt->input->buf->buffer->content; 10797 int current = ctxt->input->cur - ctxt->input->base; 10798 10799 xmlParserInputBufferPush(ctxt->input->buf, 0, ""); 10800 ctxt->input->base = ctxt->input->buf->buffer->content + base; 10801 ctxt->input->cur = ctxt->input->base + current; 10802 ctxt->input->end = 10803 &ctxt->input->buf->buffer->content[ 10804 ctxt->input->buf->buffer->use]; 10805 } 10806 avail = ctxt->input->buf->buffer->use - 10807 (ctxt->input->cur - ctxt->input->base); 10808 } 10809 if (avail < 1) 10810 goto done; 10811 switch (ctxt->instate) { 10812 case XML_PARSER_EOF: 10813 /* 10814 * Document parsing is done ! 10815 */ 10816 goto done; 10817 case XML_PARSER_START: 10818 if (ctxt->charset == XML_CHAR_ENCODING_NONE) { 10819 xmlChar start[4]; 10820 xmlCharEncoding enc; 10821 10822 /* 10823 * Very first chars read from the document flow. 10824 */ 10825 if (avail < 4) 10826 goto done; 10827 10828 /* 10829 * Get the 4 first bytes and decode the charset 10830 * if enc != XML_CHAR_ENCODING_NONE 10831 * plug some encoding conversion routines, 10832 * else xmlSwitchEncoding will set to (default) 10833 * UTF8. 10834 */ 10835 start[0] = RAW; 10836 start[1] = NXT(1); 10837 start[2] = NXT(2); 10838 start[3] = NXT(3); 10839 enc = xmlDetectCharEncoding(start, 4); 10840 xmlSwitchEncoding(ctxt, enc); 10841 break; 10842 } 10843 10844 if (avail < 2) 10845 goto done; 10846 cur = ctxt->input->cur[0]; 10847 next = ctxt->input->cur[1]; 10848 if (cur == 0) { 10849 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) 10850 ctxt->sax->setDocumentLocator(ctxt->userData, 10851 &xmlDefaultSAXLocator); 10852 xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL); 10853 ctxt->instate = XML_PARSER_EOF; 10854 #ifdef DEBUG_PUSH 10855 xmlGenericError(xmlGenericErrorContext, 10856 "PP: entering EOF\n"); 10857 #endif 10858 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) 10859 ctxt->sax->endDocument(ctxt->userData); 10860 goto done; 10861 } 10862 if ((cur == '<') && (next == '?')) { 10863 /* PI or XML decl */ 10864 if (avail < 5) return(ret); 10865 if ((!terminate) && 10866 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) 10867 return(ret); 10868 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) 10869 ctxt->sax->setDocumentLocator(ctxt->userData, 10870 &xmlDefaultSAXLocator); 10871 if ((ctxt->input->cur[2] == 'x') && 10872 (ctxt->input->cur[3] == 'm') && 10873 (ctxt->input->cur[4] == 'l') && 10874 (IS_BLANK_CH(ctxt->input->cur[5]))) { 10875 ret += 5; 10876 #ifdef DEBUG_PUSH 10877 xmlGenericError(xmlGenericErrorContext, 10878 "PP: Parsing XML Decl\n"); 10879 #endif 10880 xmlParseXMLDecl(ctxt); 10881 if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) { 10882 /* 10883 * The XML REC instructs us to stop parsing right 10884 * here 10885 */ 10886 ctxt->instate = XML_PARSER_EOF; 10887 return(0); 10888 } 10889 ctxt->standalone = ctxt->input->standalone; 10890 if ((ctxt->encoding == NULL) && 10891 (ctxt->input->encoding != NULL)) 10892 ctxt->encoding = xmlStrdup(ctxt->input->encoding); 10893 if ((ctxt->sax) && (ctxt->sax->startDocument) && 10894 (!ctxt->disableSAX)) 10895 ctxt->sax->startDocument(ctxt->userData); 10896 ctxt->instate = XML_PARSER_MISC; 10897 #ifdef DEBUG_PUSH 10898 xmlGenericError(xmlGenericErrorContext, 10899 "PP: entering MISC\n"); 10900 #endif 10901 } else { 10902 ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION); 10903 if ((ctxt->sax) && (ctxt->sax->startDocument) && 10904 (!ctxt->disableSAX)) 10905 ctxt->sax->startDocument(ctxt->userData); 10906 ctxt->instate = XML_PARSER_MISC; 10907 #ifdef DEBUG_PUSH 10908 xmlGenericError(xmlGenericErrorContext, 10909 "PP: entering MISC\n"); 10910 #endif 10911 } 10912 } else { 10913 if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) 10914 ctxt->sax->setDocumentLocator(ctxt->userData, 10915 &xmlDefaultSAXLocator); 10916 ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION); 10917 if (ctxt->version == NULL) { 10918 xmlErrMemory(ctxt, NULL); 10919 break; 10920 } 10921 if ((ctxt->sax) && (ctxt->sax->startDocument) && 10922 (!ctxt->disableSAX)) 10923 ctxt->sax->startDocument(ctxt->userData); 10924 ctxt->instate = XML_PARSER_MISC; 10925 #ifdef DEBUG_PUSH 10926 xmlGenericError(xmlGenericErrorContext, 10927 "PP: entering MISC\n"); 10928 #endif 10929 } 10930 break; 10931 case XML_PARSER_START_TAG: { 10932 const xmlChar *name; 10933 const xmlChar *prefix = NULL; 10934 const xmlChar *URI = NULL; 10935 int nsNr = ctxt->nsNr; 10936 10937 if ((avail < 2) && (ctxt->inputNr == 1)) 10938 goto done; 10939 cur = ctxt->input->cur[0]; 10940 if (cur != '<') { 10941 xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL); 10942 ctxt->instate = XML_PARSER_EOF; 10943 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) 10944 ctxt->sax->endDocument(ctxt->userData); 10945 goto done; 10946 } 10947 if (!terminate) { 10948 if (ctxt->progressive) { 10949 /* > can be found unescaped in attribute values */ 10950 if ((lastgt == NULL) || (ctxt->input->cur >= lastgt)) 10951 goto done; 10952 } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) { 10953 goto done; 10954 } 10955 } 10956 if (ctxt->spaceNr == 0) 10957 spacePush(ctxt, -1); 10958 else if (*ctxt->space == -2) 10959 spacePush(ctxt, -1); 10960 else 10961 spacePush(ctxt, *ctxt->space); 10962 #ifdef LIBXML_SAX1_ENABLED 10963 if (ctxt->sax2) 10964 #endif /* LIBXML_SAX1_ENABLED */ 10965 name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen); 10966 #ifdef LIBXML_SAX1_ENABLED 10967 else 10968 name = xmlParseStartTag(ctxt); 10969 #endif /* LIBXML_SAX1_ENABLED */ 10970 if (name == NULL) { 10971 spacePop(ctxt); 10972 ctxt->instate = XML_PARSER_EOF; 10973 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) 10974 ctxt->sax->endDocument(ctxt->userData); 10975 goto done; 10976 } 10977 #ifdef LIBXML_VALID_ENABLED 10978 /* 10979 * [ VC: Root Element Type ] 10980 * The Name in the document type declaration must match 10981 * the element type of the root element. 10982 */ 10983 if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc && 10984 ctxt->node && (ctxt->node == ctxt->myDoc->children)) 10985 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); 10986 #endif /* LIBXML_VALID_ENABLED */ 10987 10988 /* 10989 * Check for an Empty Element. 10990 */ 10991 if ((RAW == '/') && (NXT(1) == '>')) { 10992 SKIP(2); 10993 10994 if (ctxt->sax2) { 10995 if ((ctxt->sax != NULL) && 10996 (ctxt->sax->endElementNs != NULL) && 10997 (!ctxt->disableSAX)) 10998 ctxt->sax->endElementNs(ctxt->userData, name, 10999 prefix, URI); 11000 if (ctxt->nsNr - nsNr > 0) 11001 nsPop(ctxt, ctxt->nsNr - nsNr); 11002 #ifdef LIBXML_SAX1_ENABLED 11003 } else { 11004 if ((ctxt->sax != NULL) && 11005 (ctxt->sax->endElement != NULL) && 11006 (!ctxt->disableSAX)) 11007 ctxt->sax->endElement(ctxt->userData, name); 11008 #endif /* LIBXML_SAX1_ENABLED */ 11009 } 11010 spacePop(ctxt); 11011 if (ctxt->nameNr == 0) { 11012 ctxt->instate = XML_PARSER_EPILOG; 11013 } else { 11014 ctxt->instate = XML_PARSER_CONTENT; 11015 } 11016 break; 11017 } 11018 if (RAW == '>') { 11019 NEXT; 11020 } else { 11021 xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED, 11022 "Couldn't find end of Start Tag %s\n", 11023 name); 11024 nodePop(ctxt); 11025 spacePop(ctxt); 11026 } 11027 if (ctxt->sax2) 11028 nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr); 11029 #ifdef LIBXML_SAX1_ENABLED 11030 else 11031 namePush(ctxt, name); 11032 #endif /* LIBXML_SAX1_ENABLED */ 11033 11034 ctxt->instate = XML_PARSER_CONTENT; 11035 break; 11036 } 11037 case XML_PARSER_CONTENT: { 11038 const xmlChar *test; 11039 unsigned int cons; 11040 if ((avail < 2) && (ctxt->inputNr == 1)) 11041 goto done; 11042 cur = ctxt->input->cur[0]; 11043 next = ctxt->input->cur[1]; 11044 11045 test = CUR_PTR; 11046 cons = ctxt->input->consumed; 11047 if ((cur == '<') && (next == '/')) { 11048 ctxt->instate = XML_PARSER_END_TAG; 11049 break; 11050 } else if ((cur == '<') && (next == '?')) { 11051 if ((!terminate) && 11052 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) 11053 goto done; 11054 xmlParsePI(ctxt); 11055 } else if ((cur == '<') && (next != '!')) { 11056 ctxt->instate = XML_PARSER_START_TAG; 11057 break; 11058 } else if ((cur == '<') && (next == '!') && 11059 (ctxt->input->cur[2] == '-') && 11060 (ctxt->input->cur[3] == '-')) { 11061 int term; 11062 11063 if (avail < 4) 11064 goto done; 11065 ctxt->input->cur += 4; 11066 term = xmlParseLookupSequence(ctxt, '-', '-', '>'); 11067 ctxt->input->cur -= 4; 11068 if ((!terminate) && (term < 0)) 11069 goto done; 11070 xmlParseComment(ctxt); 11071 ctxt->instate = XML_PARSER_CONTENT; 11072 } else if ((cur == '<') && (ctxt->input->cur[1] == '!') && 11073 (ctxt->input->cur[2] == '[') && 11074 (ctxt->input->cur[3] == 'C') && 11075 (ctxt->input->cur[4] == 'D') && 11076 (ctxt->input->cur[5] == 'A') && 11077 (ctxt->input->cur[6] == 'T') && 11078 (ctxt->input->cur[7] == 'A') && 11079 (ctxt->input->cur[8] == '[')) { 11080 SKIP(9); 11081 ctxt->instate = XML_PARSER_CDATA_SECTION; 11082 break; 11083 } else if ((cur == '<') && (next == '!') && 11084 (avail < 9)) { 11085 goto done; 11086 } else if (cur == '&') { 11087 if ((!terminate) && 11088 (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0)) 11089 goto done; 11090 xmlParseReference(ctxt); 11091 } else { 11092 /* TODO Avoid the extra copy, handle directly !!! */ 11093 /* 11094 * Goal of the following test is: 11095 * - minimize calls to the SAX 'character' callback 11096 * when they are mergeable 11097 * - handle an problem for isBlank when we only parse 11098 * a sequence of blank chars and the next one is 11099 * not available to check against '<' presence. 11100 * - tries to homogenize the differences in SAX 11101 * callbacks between the push and pull versions 11102 * of the parser. 11103 */ 11104 if ((ctxt->inputNr == 1) && 11105 (avail < XML_PARSER_BIG_BUFFER_SIZE)) { 11106 if (!terminate) { 11107 if (ctxt->progressive) { 11108 if ((lastlt == NULL) || 11109 (ctxt->input->cur > lastlt)) 11110 goto done; 11111 } else if (xmlParseLookupSequence(ctxt, 11112 '<', 0, 0) < 0) { 11113 goto done; 11114 } 11115 } 11116 } 11117 ctxt->checkIndex = 0; 11118 xmlParseCharData(ctxt, 0); 11119 } 11120 /* 11121 * Pop-up of finished entities. 11122 */ 11123 while ((RAW == 0) && (ctxt->inputNr > 1)) 11124 xmlPopInput(ctxt); 11125 if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) { 11126 xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, 11127 "detected an error in element content\n"); 11128 ctxt->instate = XML_PARSER_EOF; 11129 break; 11130 } 11131 break; 11132 } 11133 case XML_PARSER_END_TAG: 11134 if (avail < 2) 11135 goto done; 11136 if (!terminate) { 11137 if (ctxt->progressive) { 11138 /* > can be found unescaped in attribute values */ 11139 if ((lastgt == NULL) || (ctxt->input->cur >= lastgt)) 11140 goto done; 11141 } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) { 11142 goto done; 11143 } 11144 } 11145 if (ctxt->sax2) { 11146 xmlParseEndTag2(ctxt, 11147 (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3], 11148 (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0, 11149 (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0); 11150 nameNsPop(ctxt); 11151 } 11152 #ifdef LIBXML_SAX1_ENABLED 11153 else 11154 xmlParseEndTag1(ctxt, 0); 11155 #endif /* LIBXML_SAX1_ENABLED */ 11156 if (ctxt->nameNr == 0) { 11157 ctxt->instate = XML_PARSER_EPILOG; 11158 } else { 11159 ctxt->instate = XML_PARSER_CONTENT; 11160 } 11161 break; 11162 case XML_PARSER_CDATA_SECTION: { 11163 /* 11164 * The Push mode need to have the SAX callback for 11165 * cdataBlock merge back contiguous callbacks. 11166 */ 11167 int base; 11168 11169 base = xmlParseLookupSequence(ctxt, ']', ']', '>'); 11170 if (base < 0) { 11171 if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) { 11172 int tmp; 11173 11174 tmp = xmlCheckCdataPush(ctxt->input->cur, 11175 XML_PARSER_BIG_BUFFER_SIZE); 11176 if (tmp < 0) { 11177 tmp = -tmp; 11178 ctxt->input->cur += tmp; 11179 goto encoding_error; 11180 } 11181 if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) { 11182 if (ctxt->sax->cdataBlock != NULL) 11183 ctxt->sax->cdataBlock(ctxt->userData, 11184 ctxt->input->cur, tmp); 11185 else if (ctxt->sax->characters != NULL) 11186 ctxt->sax->characters(ctxt->userData, 11187 ctxt->input->cur, tmp); 11188 } 11189 SKIPL(tmp); 11190 ctxt->checkIndex = 0; 11191 } 11192 goto done; 11193 } else { 11194 int tmp; 11195 11196 tmp = xmlCheckCdataPush(ctxt->input->cur, base); 11197 if ((tmp < 0) || (tmp != base)) { 11198 tmp = -tmp; 11199 ctxt->input->cur += tmp; 11200 goto encoding_error; 11201 } 11202 if ((ctxt->sax != NULL) && (base == 0) && 11203 (ctxt->sax->cdataBlock != NULL) && 11204 (!ctxt->disableSAX)) { 11205 /* 11206 * Special case to provide identical behaviour 11207 * between pull and push parsers on enpty CDATA 11208 * sections 11209 */ 11210 if ((ctxt->input->cur - ctxt->input->base >= 9) && 11211 (!strncmp((const char *)&ctxt->input->cur[-9], 11212 "<![CDATA[", 9))) 11213 ctxt->sax->cdataBlock(ctxt->userData, 11214 BAD_CAST "", 0); 11215 } else if ((ctxt->sax != NULL) && (base > 0) && 11216 (!ctxt->disableSAX)) { 11217 if (ctxt->sax->cdataBlock != NULL) 11218 ctxt->sax->cdataBlock(ctxt->userData, 11219 ctxt->input->cur, base); 11220 else if (ctxt->sax->characters != NULL) 11221 ctxt->sax->characters(ctxt->userData, 11222 ctxt->input->cur, base); 11223 } 11224 SKIPL(base + 3); 11225 ctxt->checkIndex = 0; 11226 ctxt->instate = XML_PARSER_CONTENT; 11227 #ifdef DEBUG_PUSH 11228 xmlGenericError(xmlGenericErrorContext, 11229 "PP: entering CONTENT\n"); 11230 #endif 11231 } 11232 break; 11233 } 11234 case XML_PARSER_MISC: 11235 SKIP_BLANKS; 11236 if (ctxt->input->buf == NULL) 11237 avail = ctxt->input->length - 11238 (ctxt->input->cur - ctxt->input->base); 11239 else 11240 avail = ctxt->input->buf->buffer->use - 11241 (ctxt->input->cur - ctxt->input->base); 11242 if (avail < 2) 11243 goto done; 11244 cur = ctxt->input->cur[0]; 11245 next = ctxt->input->cur[1]; 11246 if ((cur == '<') && (next == '?')) { 11247 if ((!terminate) && 11248 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) 11249 goto done; 11250 #ifdef DEBUG_PUSH 11251 xmlGenericError(xmlGenericErrorContext, 11252 "PP: Parsing PI\n"); 11253 #endif 11254 xmlParsePI(ctxt); 11255 ctxt->checkIndex = 0; 11256 } else if ((cur == '<') && (next == '!') && 11257 (ctxt->input->cur[2] == '-') && 11258 (ctxt->input->cur[3] == '-')) { 11259 if ((!terminate) && 11260 (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) 11261 goto done; 11262 #ifdef DEBUG_PUSH 11263 xmlGenericError(xmlGenericErrorContext, 11264 "PP: Parsing Comment\n"); 11265 #endif 11266 xmlParseComment(ctxt); 11267 ctxt->instate = XML_PARSER_MISC; 11268 ctxt->checkIndex = 0; 11269 } else if ((cur == '<') && (next == '!') && 11270 (ctxt->input->cur[2] == 'D') && 11271 (ctxt->input->cur[3] == 'O') && 11272 (ctxt->input->cur[4] == 'C') && 11273 (ctxt->input->cur[5] == 'T') && 11274 (ctxt->input->cur[6] == 'Y') && 11275 (ctxt->input->cur[7] == 'P') && 11276 (ctxt->input->cur[8] == 'E')) { 11277 if ((!terminate) && 11278 (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0)) 11279 goto done; 11280 #ifdef DEBUG_PUSH 11281 xmlGenericError(xmlGenericErrorContext, 11282 "PP: Parsing internal subset\n"); 11283 #endif 11284 ctxt->inSubset = 1; 11285 xmlParseDocTypeDecl(ctxt); 11286 if (RAW == '[') { 11287 ctxt->instate = XML_PARSER_DTD; 11288 #ifdef DEBUG_PUSH 11289 xmlGenericError(xmlGenericErrorContext, 11290 "PP: entering DTD\n"); 11291 #endif 11292 } else { 11293 /* 11294 * Create and update the external subset. 11295 */ 11296 ctxt->inSubset = 2; 11297 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && 11298 (ctxt->sax->externalSubset != NULL)) 11299 ctxt->sax->externalSubset(ctxt->userData, 11300 ctxt->intSubName, ctxt->extSubSystem, 11301 ctxt->extSubURI); 11302 ctxt->inSubset = 0; 11303 xmlCleanSpecialAttr(ctxt); 11304 ctxt->instate = XML_PARSER_PROLOG; 11305 #ifdef DEBUG_PUSH 11306 xmlGenericError(xmlGenericErrorContext, 11307 "PP: entering PROLOG\n"); 11308 #endif 11309 } 11310 } else if ((cur == '<') && (next == '!') && 11311 (avail < 9)) { 11312 goto done; 11313 } else { 11314 ctxt->instate = XML_PARSER_START_TAG; 11315 ctxt->progressive = 1; 11316 xmlParseGetLasts(ctxt, &lastlt, &lastgt); 11317 #ifdef DEBUG_PUSH 11318 xmlGenericError(xmlGenericErrorContext, 11319 "PP: entering START_TAG\n"); 11320 #endif 11321 } 11322 break; 11323 case XML_PARSER_PROLOG: 11324 SKIP_BLANKS; 11325 if (ctxt->input->buf == NULL) 11326 avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base); 11327 else 11328 avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base); 11329 if (avail < 2) 11330 goto done; 11331 cur = ctxt->input->cur[0]; 11332 next = ctxt->input->cur[1]; 11333 if ((cur == '<') && (next == '?')) { 11334 if ((!terminate) && 11335 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) 11336 goto done; 11337 #ifdef DEBUG_PUSH 11338 xmlGenericError(xmlGenericErrorContext, 11339 "PP: Parsing PI\n"); 11340 #endif 11341 xmlParsePI(ctxt); 11342 } else if ((cur == '<') && (next == '!') && 11343 (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) { 11344 if ((!terminate) && 11345 (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) 11346 goto done; 11347 #ifdef DEBUG_PUSH 11348 xmlGenericError(xmlGenericErrorContext, 11349 "PP: Parsing Comment\n"); 11350 #endif 11351 xmlParseComment(ctxt); 11352 ctxt->instate = XML_PARSER_PROLOG; 11353 } else if ((cur == '<') && (next == '!') && 11354 (avail < 4)) { 11355 goto done; 11356 } else { 11357 ctxt->instate = XML_PARSER_START_TAG; 11358 if (ctxt->progressive == 0) 11359 ctxt->progressive = 1; 11360 xmlParseGetLasts(ctxt, &lastlt, &lastgt); 11361 #ifdef DEBUG_PUSH 11362 xmlGenericError(xmlGenericErrorContext, 11363 "PP: entering START_TAG\n"); 11364 #endif 11365 } 11366 break; 11367 case XML_PARSER_EPILOG: 11368 SKIP_BLANKS; 11369 if (ctxt->input->buf == NULL) 11370 avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base); 11371 else 11372 avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base); 11373 if (avail < 2) 11374 goto done; 11375 cur = ctxt->input->cur[0]; 11376 next = ctxt->input->cur[1]; 11377 if ((cur == '<') && (next == '?')) { 11378 if ((!terminate) && 11379 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) 11380 goto done; 11381 #ifdef DEBUG_PUSH 11382 xmlGenericError(xmlGenericErrorContext, 11383 "PP: Parsing PI\n"); 11384 #endif 11385 xmlParsePI(ctxt); 11386 ctxt->instate = XML_PARSER_EPILOG; 11387 } else if ((cur == '<') && (next == '!') && 11388 (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) { 11389 if ((!terminate) && 11390 (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) 11391 goto done; 11392 #ifdef DEBUG_PUSH 11393 xmlGenericError(xmlGenericErrorContext, 11394 "PP: Parsing Comment\n"); 11395 #endif 11396 xmlParseComment(ctxt); 11397 ctxt->instate = XML_PARSER_EPILOG; 11398 } else if ((cur == '<') && (next == '!') && 11399 (avail < 4)) { 11400 goto done; 11401 } else { 11402 xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); 11403 ctxt->instate = XML_PARSER_EOF; 11404 #ifdef DEBUG_PUSH 11405 xmlGenericError(xmlGenericErrorContext, 11406 "PP: entering EOF\n"); 11407 #endif 11408 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) 11409 ctxt->sax->endDocument(ctxt->userData); 11410 goto done; 11411 } 11412 break; 11413 case XML_PARSER_DTD: { 11414 /* 11415 * Sorry but progressive parsing of the internal subset 11416 * is not expected to be supported. We first check that 11417 * the full content of the internal subset is available and 11418 * the parsing is launched only at that point. 11419 * Internal subset ends up with "']' S? '>'" in an unescaped 11420 * section and not in a ']]>' sequence which are conditional 11421 * sections (whoever argued to keep that crap in XML deserve 11422 * a place in hell !). 11423 */ 11424 int base, i; 11425 xmlChar *buf; 11426 xmlChar quote = 0; 11427 11428 base = ctxt->input->cur - ctxt->input->base; 11429 if (base < 0) return(0); 11430 if (ctxt->checkIndex > base) 11431 base = ctxt->checkIndex; 11432 buf = ctxt->input->buf->buffer->content; 11433 for (;(unsigned int) base < ctxt->input->buf->buffer->use; 11434 base++) { 11435 if (quote != 0) { 11436 if (buf[base] == quote) 11437 quote = 0; 11438 continue; 11439 } 11440 if ((quote == 0) && (buf[base] == '<')) { 11441 int found = 0; 11442 /* special handling of comments */ 11443 if (((unsigned int) base + 4 < 11444 ctxt->input->buf->buffer->use) && 11445 (buf[base + 1] == '!') && 11446 (buf[base + 2] == '-') && 11447 (buf[base + 3] == '-')) { 11448 for (;(unsigned int) base + 3 < 11449 ctxt->input->buf->buffer->use; base++) { 11450 if ((buf[base] == '-') && 11451 (buf[base + 1] == '-') && 11452 (buf[base + 2] == '>')) { 11453 found = 1; 11454 base += 2; 11455 break; 11456 } 11457 } 11458 if (!found) { 11459 #if 0 11460 fprintf(stderr, "unfinished comment\n"); 11461 #endif 11462 break; /* for */ 11463 } 11464 continue; 11465 } 11466 } 11467 if (buf[base] == '"') { 11468 quote = '"'; 11469 continue; 11470 } 11471 if (buf[base] == '\'') { 11472 quote = '\''; 11473 continue; 11474 } 11475 if (buf[base] == ']') { 11476 #if 0 11477 fprintf(stderr, "%c%c%c%c: ", buf[base], 11478 buf[base + 1], buf[base + 2], buf[base + 3]); 11479 #endif 11480 if ((unsigned int) base +1 >= 11481 ctxt->input->buf->buffer->use) 11482 break; 11483 if (buf[base + 1] == ']') { 11484 /* conditional crap, skip both ']' ! */ 11485 base++; 11486 continue; 11487 } 11488 for (i = 1; 11489 (unsigned int) base + i < ctxt->input->buf->buffer->use; 11490 i++) { 11491 if (buf[base + i] == '>') { 11492 #if 0 11493 fprintf(stderr, "found\n"); 11494 #endif 11495 goto found_end_int_subset; 11496 } 11497 if (!IS_BLANK_CH(buf[base + i])) { 11498 #if 0 11499 fprintf(stderr, "not found\n"); 11500 #endif 11501 goto not_end_of_int_subset; 11502 } 11503 } 11504 #if 0 11505 fprintf(stderr, "end of stream\n"); 11506 #endif 11507 break; 11508 11509 } 11510 not_end_of_int_subset: 11511 continue; /* for */ 11512 } 11513 /* 11514 * We didn't found the end of the Internal subset 11515 */ 11516 #ifdef DEBUG_PUSH 11517 if (next == 0) 11518 xmlGenericError(xmlGenericErrorContext, 11519 "PP: lookup of int subset end filed\n"); 11520 #endif 11521 goto done; 11522 11523 found_end_int_subset: 11524 xmlParseInternalSubset(ctxt); 11525 ctxt->inSubset = 2; 11526 if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && 11527 (ctxt->sax->externalSubset != NULL)) 11528 ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName, 11529 ctxt->extSubSystem, ctxt->extSubURI); 11530 ctxt->inSubset = 0; 11531 xmlCleanSpecialAttr(ctxt); 11532 ctxt->instate = XML_PARSER_PROLOG; 11533 ctxt->checkIndex = 0; 11534 #ifdef DEBUG_PUSH 11535 xmlGenericError(xmlGenericErrorContext, 11536 "PP: entering PROLOG\n"); 11537 #endif 11538 break; 11539 } 11540 case XML_PARSER_COMMENT: 11541 xmlGenericError(xmlGenericErrorContext, 11542 "PP: internal error, state == COMMENT\n"); 11543 ctxt->instate = XML_PARSER_CONTENT; 11544 #ifdef DEBUG_PUSH 11545 xmlGenericError(xmlGenericErrorContext, 11546 "PP: entering CONTENT\n"); 11547 #endif 11548 break; 11549 case XML_PARSER_IGNORE: 11550 xmlGenericError(xmlGenericErrorContext, 11551 "PP: internal error, state == IGNORE"); 11552 ctxt->instate = XML_PARSER_DTD; 11553 #ifdef DEBUG_PUSH 11554 xmlGenericError(xmlGenericErrorContext, 11555 "PP: entering DTD\n"); 11556 #endif 11557 break; 11558 case XML_PARSER_PI: 11559 xmlGenericError(xmlGenericErrorContext, 11560 "PP: internal error, state == PI\n"); 11561 ctxt->instate = XML_PARSER_CONTENT; 11562 #ifdef DEBUG_PUSH 11563 xmlGenericError(xmlGenericErrorContext, 11564 "PP: entering CONTENT\n"); 11565 #endif 11566 break; 11567 case XML_PARSER_ENTITY_DECL: 11568 xmlGenericError(xmlGenericErrorContext, 11569 "PP: internal error, state == ENTITY_DECL\n"); 11570 ctxt->instate = XML_PARSER_DTD; 11571 #ifdef DEBUG_PUSH 11572 xmlGenericError(xmlGenericErrorContext, 11573 "PP: entering DTD\n"); 11574 #endif 11575 break; 11576 case XML_PARSER_ENTITY_VALUE: 11577 xmlGenericError(xmlGenericErrorContext, 11578 "PP: internal error, state == ENTITY_VALUE\n"); 11579 ctxt->instate = XML_PARSER_CONTENT; 11580 #ifdef DEBUG_PUSH 11581 xmlGenericError(xmlGenericErrorContext, 11582 "PP: entering DTD\n"); 11583 #endif 11584 break; 11585 case XML_PARSER_ATTRIBUTE_VALUE: 11586 xmlGenericError(xmlGenericErrorContext, 11587 "PP: internal error, state == ATTRIBUTE_VALUE\n"); 11588 ctxt->instate = XML_PARSER_START_TAG; 11589 #ifdef DEBUG_PUSH 11590 xmlGenericError(xmlGenericErrorContext, 11591 "PP: entering START_TAG\n"); 11592 #endif 11593 break; 11594 case XML_PARSER_SYSTEM_LITERAL: 11595 xmlGenericError(xmlGenericErrorContext, 11596 "PP: internal error, state == SYSTEM_LITERAL\n"); 11597 ctxt->instate = XML_PARSER_START_TAG; 11598 #ifdef DEBUG_PUSH 11599 xmlGenericError(xmlGenericErrorContext, 11600 "PP: entering START_TAG\n"); 11601 #endif 11602 break; 11603 case XML_PARSER_PUBLIC_LITERAL: 11604 xmlGenericError(xmlGenericErrorContext, 11605 "PP: internal error, state == PUBLIC_LITERAL\n"); 11606 ctxt->instate = XML_PARSER_START_TAG; 11607 #ifdef DEBUG_PUSH 11608 xmlGenericError(xmlGenericErrorContext, 11609 "PP: entering START_TAG\n"); 11610 #endif 11611 break; 11612 } 11613 } 11614 done: 11615 #ifdef DEBUG_PUSH 11616 xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret); 11617 #endif 11618 return(ret); 11619 encoding_error: 11620 { 11621 char buffer[150]; 11622 11623 snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", 11624 ctxt->input->cur[0], ctxt->input->cur[1], 11625 ctxt->input->cur[2], ctxt->input->cur[3]); 11626 __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, 11627 "Input is not proper UTF-8, indicate encoding !\n%s", 11628 BAD_CAST buffer, NULL); 11629 } 11630 return(0); 11631 } 11632 11644 int 11645 xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, 11646 int terminate) { 11647 int end_in_lf = 0; 11648 int remain = 0; 11649 11650 if (ctxt == NULL) 11651 return(XML_ERR_INTERNAL_ERROR); 11652 if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1)) 11653 return(ctxt->errNo); 11654 if (ctxt->instate == XML_PARSER_START) 11655 xmlDetectSAX2(ctxt); 11656 if ((size > 0) && (chunk != NULL) && (!terminate) && 11657 (chunk[size - 1] == '\r')) { 11658 end_in_lf = 1; 11659 size--; 11660 } 11661 11662 xmldecl_done: 11663 11664 if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && 11665 (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) { 11666 int base = ctxt->input->base - ctxt->input->buf->buffer->content; 11667 int cur = ctxt->input->cur - ctxt->input->base; 11668 int res; 11669 11670 /* 11671 * Specific handling if we autodetected an encoding, we should not 11672 * push more than the first line ... which depend on the encoding 11673 * And only push the rest once the final encoding was detected 11674 */ 11675 if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) && 11676 (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) { 11677 unsigned int len = 45; 11678 11679 if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name, 11680 BAD_CAST "UTF-16")) || 11681 (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name, 11682 BAD_CAST "UTF16"))) 11683 len = 90; 11684 else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name, 11685 BAD_CAST "UCS-4")) || 11686 (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name, 11687 BAD_CAST "UCS4"))) 11688 len = 180; 11689 11690 if (ctxt->input->buf->rawconsumed < len) 11691 len -= ctxt->input->buf->rawconsumed; 11692 11693 /* 11694 * Change size for reading the initial declaration only 11695 * if size is greater than len. Otherwise, memmove in xmlBufferAdd 11696 * will blindly copy extra bytes from memory. 11697 */ 11698 if ((unsigned int) size > len) { 11699 remain = size - len; 11700 size = len; 11701 } else { 11702 remain = 0; 11703 } 11704 } 11705 res =xmlParserInputBufferPush(ctxt->input->buf, size, chunk); 11706 if (res < 0) { 11707 ctxt->errNo = XML_PARSER_EOF; 11708 ctxt->disableSAX = 1; 11709 return (XML_PARSER_EOF); 11710 } 11711 ctxt->input->base = ctxt->input->buf->buffer->content + base; 11712 ctxt->input->cur = ctxt->input->base + cur; 11713 ctxt->input->end = 11714 &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use]; 11715 #ifdef DEBUG_PUSH 11716 xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size); 11717 #endif 11718 11719 } else if (ctxt->instate != XML_PARSER_EOF) { 11720 if ((ctxt->input != NULL) && ctxt->input->buf != NULL) { 11721 xmlParserInputBufferPtr in = ctxt->input->buf; 11722 if ((in->encoder != NULL) && (in->buffer != NULL) && 11723 (in->raw != NULL)) { 11724 int nbchars; 11725 11726 nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw); 11727 if (nbchars < 0) { 11728 /* TODO 2.6.0 */ 11729 xmlGenericError(xmlGenericErrorContext, 11730 "xmlParseChunk: encoder error\n"); 11731 return(XML_ERR_INVALID_ENCODING); 11732 } 11733 } 11734 } 11735 } 11736 if (remain != 0) 11737 xmlParseTryOrFinish(ctxt, 0); 11738 else 11739 xmlParseTryOrFinish(ctxt, terminate); 11740 if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1)) 11741 return(ctxt->errNo); 11742 11743 if (remain != 0) { 11744 chunk += size; 11745 size = remain; 11746 remain = 0; 11747 goto xmldecl_done; 11748 } 11749 if ((end_in_lf == 1) && (ctxt->input != NULL) && 11750 (ctxt->input->buf != NULL)) { 11751 xmlParserInputBufferPush(ctxt->input->buf, 1, "\r"); 11752 } 11753 if (terminate) { 11754 /* 11755 * Check for termination 11756 */ 11757 int avail = 0; 11758 11759 if (ctxt->input != NULL) { 11760 if (ctxt->input->buf == NULL) 11761 avail = ctxt->input->length - 11762 (ctxt->input->cur - ctxt->input->base); 11763 else 11764 avail = ctxt->input->buf->buffer->use - 11765 (ctxt->input->cur - ctxt->input->base); 11766 } 11767 11768 if ((ctxt->instate != XML_PARSER_EOF) && 11769 (ctxt->instate != XML_PARSER_EPILOG)) { 11770 xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); 11771 } 11772 if ((ctxt->instate == XML_PARSER_EPILOG) && (avail > 0)) { 11773 xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); 11774 } 11775 if (ctxt->instate != XML_PARSER_EOF) { 11776 if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) 11777 ctxt->sax->endDocument(ctxt->userData); 11778 } 11779 ctxt->instate = XML_PARSER_EOF; 11780 } 11781 return((xmlParserErrors) ctxt->errNo); 11782 } 11783 11784 /************************************************************************ 11785 * * 11786 * I/O front end functions to the parser * 11787 * * 11788 ************************************************************************/ 11789 11809 xmlParserCtxtPtr 11810 xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, 11811 const char *chunk, int size, const char *filename) { 11812 xmlParserCtxtPtr ctxt; 11813 xmlParserInputPtr inputStream; 11814 xmlParserInputBufferPtr buf; 11815 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; 11816 11817 /* 11818 * plug some encoding conversion routines 11819 */ 11820 if ((chunk != NULL) && (size >= 4)) 11821 enc = xmlDetectCharEncoding((const xmlChar *) chunk, size); 11822 11823 buf = xmlAllocParserInputBuffer(enc); 11824 if (buf == NULL) return(NULL); 11825 11826 ctxt = xmlNewParserCtxt(); 11827 if (ctxt == NULL) { 11828 xmlErrMemory(NULL, "creating parser: out of memory\n"); 11829 xmlFreeParserInputBuffer(buf); 11830 return(NULL); 11831 } 11832 ctxt->dictNames = 1; 11833 ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *)); 11834 if (ctxt->pushTab == NULL) { 11835 xmlErrMemory(ctxt, NULL); 11836 xmlFreeParserInputBuffer(buf); 11837 xmlFreeParserCtxt(ctxt); 11838 return(NULL); 11839 } 11840 if (sax != NULL) { 11841 #ifdef LIBXML_SAX1_ENABLED 11842 if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) 11843 #endif /* LIBXML_SAX1_ENABLED */ 11844 xmlFree(ctxt->sax); 11845 ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler)); 11846 if (ctxt->sax == NULL) { 11847 xmlErrMemory(ctxt, NULL); 11848 xmlFreeParserInputBuffer(buf); 11849 xmlFreeParserCtxt(ctxt); 11850 return(NULL); 11851 } 11852 memset(ctxt->sax, 0, sizeof(xmlSAXHandler)); 11853 if (sax->initialized == XML_SAX2_MAGIC) 11854 memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler)); 11855 else 11856 memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1)); 11857 if (user_data != NULL) 11858 ctxt->userData = user_data; 11859 } 11860 if (filename == NULL) { 11861 ctxt->directory = NULL; 11862 } else { 11863 ctxt->directory = xmlParserGetDirectory(filename); 11864 } 11865 11866 inputStream = xmlNewInputStream(ctxt); 11867 if (inputStream == NULL) { 11868 xmlFreeParserCtxt(ctxt); 11869 xmlFreeParserInputBuffer(buf); 11870 return(NULL); 11871 } 11872 11873 if (filename == NULL) 11874 inputStream->filename = NULL; 11875 else { 11876 inputStream->filename = (char *) 11877 xmlCanonicPath((const xmlChar *) filename); 11878 if (inputStream->filename == NULL) { 11879 xmlFreeParserCtxt(ctxt); 11880 xmlFreeParserInputBuffer(buf); 11881 return(NULL); 11882 } 11883 } 11884 inputStream->buf = buf; 11885 inputStream->base = inputStream->buf->buffer->content; 11886 inputStream->cur = inputStream->buf->buffer->content; 11887 inputStream->end = 11888 &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; 11889 11890 inputPush(ctxt, inputStream); 11891 11892 /* 11893 * If the caller didn't provide an initial 'chunk' for determining 11894 * the encoding, we set the context to XML_CHAR_ENCODING_NONE so 11895 * that it can be automatically determined later 11896 */ 11897 if ((size == 0) || (chunk == NULL)) { 11898 ctxt->charset = XML_CHAR_ENCODING_NONE; 11899 } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) { 11900 int base = ctxt->input->base - ctxt->input->buf->buffer->content; 11901 int cur = ctxt->input->cur - ctxt->input->base; 11902 11903 xmlParserInputBufferPush(ctxt->input->buf, size, chunk); 11904 11905 ctxt->input->base = ctxt->input->buf->buffer->content + base; 11906 ctxt->input->cur = ctxt->input->base + cur; 11907 ctxt->input->end = 11908 &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use]; 11909 #ifdef DEBUG_PUSH 11910 xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size); 11911 #endif 11912 } 11913 11914 if (enc != XML_CHAR_ENCODING_NONE) { 11915 xmlSwitchEncoding(ctxt, enc); 11916 } 11917 11918 return(ctxt); 11919 } 11920 #endif /* LIBXML_PUSH_ENABLED */ 11921 11928 void 11929 xmlStopParser(xmlParserCtxtPtr ctxt) { 11930 if (ctxt == NULL) 11931 return; 11932 ctxt->instate = XML_PARSER_EOF; 11933 ctxt->disableSAX = 1; 11934 if (ctxt->input != NULL) { 11935 ctxt->input->cur = BAD_CAST""; 11936 ctxt->input->base = ctxt->input->cur; 11937 } 11938 } 11939 11954 xmlParserCtxtPtr 11955 xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data, 11956 xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, 11957 void *ioctx, xmlCharEncoding enc) { 11958 xmlParserCtxtPtr ctxt; 11959 xmlParserInputPtr inputStream; 11960 xmlParserInputBufferPtr buf; 11961 11962 if (ioread == NULL) return(NULL); 11963 11964 buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc); 11965 if (buf == NULL) return(NULL); 11966 11967 ctxt = xmlNewParserCtxt(); 11968 if (ctxt == NULL) { 11969 xmlFreeParserInputBuffer(buf); 11970 return(NULL); 11971 } 11972 if (sax != NULL) { 11973 #ifdef LIBXML_SAX1_ENABLED 11974 if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) 11975 #endif /* LIBXML_SAX1_ENABLED */ 11976 xmlFree(ctxt->sax); 11977 ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler)); 11978 if (ctxt->sax == NULL) { 11979 xmlErrMemory(ctxt, NULL); 11980 xmlFreeParserCtxt(ctxt); 11981 return(NULL); 11982 } 11983 memset(ctxt->sax, 0, sizeof(xmlSAXHandler)); 11984 if (sax->initialized == XML_SAX2_MAGIC) 11985 memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler)); 11986 else 11987 memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1)); 11988 if (user_data != NULL) 11989 ctxt->userData = user_data; 11990 } 11991 11992 inputStream = xmlNewIOInputStream(ctxt, buf, enc); 11993 if (inputStream == NULL) { 11994 xmlFreeParserCtxt(ctxt); 11995 return(NULL); 11996 } 11997 inputPush(ctxt, inputStream); 11998 11999 return(ctxt); 12000 } 12001 12002 #ifdef LIBXML_VALID_ENABLED 12003 /************************************************************************ 12004 * * 12005 * Front ends when parsing a DTD * 12006 * * 12007 ************************************************************************/ 12008 12021 xmlDtdPtr 12022 xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input, 12023 xmlCharEncoding enc) { 12024 xmlDtdPtr ret = NULL; 12025 xmlParserCtxtPtr ctxt; 12026 xmlParserInputPtr pinput = NULL; 12027 xmlChar start[4]; 12028 12029 if (input == NULL) 12030 return(NULL); 12031 12032 ctxt = xmlNewParserCtxt(); 12033 if (ctxt == NULL) { 12034 xmlFreeParserInputBuffer(input); 12035 return(NULL); 12036 } 12037 12038 /* 12039 * Set-up the SAX context 12040 */ 12041 if (sax != NULL) { 12042 if (ctxt->sax != NULL) 12043 xmlFree(ctxt->sax); 12044 ctxt->sax = sax; 12045 ctxt->userData = ctxt; 12046 } 12047 xmlDetectSAX2(ctxt); 12048 12049 /* 12050 * generate a parser input from the I/O handler 12051 */ 12052 12053 pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); 12054 if (pinput == NULL) { 12055 if (sax != NULL) ctxt->sax = NULL; 12056 xmlFreeParserInputBuffer(input); 12057 xmlFreeParserCtxt(ctxt); 12058 return(NULL); 12059 } 12060 12061 /* 12062 * plug some encoding conversion routines here. 12063 */ 12064 if (xmlPushInput(ctxt, pinput) < 0) { 12065 if (sax != NULL) ctxt->sax = NULL; 12066 xmlFreeParserCtxt(ctxt); 12067 return(NULL); 12068 } 12069 if (enc != XML_CHAR_ENCODING_NONE) { 12070 xmlSwitchEncoding(ctxt, enc); 12071 } 12072 12073 pinput->filename = NULL; 12074 pinput->line = 1; 12075 pinput->col = 1; 12076 pinput->base = ctxt->input->cur; 12077 pinput->cur = ctxt->input->cur; 12078 pinput->free = NULL; 12079 12080 /* 12081 * let's parse that entity knowing it's an external subset. 12082 */ 12083 ctxt->inSubset = 2; 12084 ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0"); 12085 if (ctxt->myDoc == NULL) { 12086 xmlErrMemory(ctxt, "New Doc failed"); 12087 return(NULL); 12088 } 12089 ctxt->myDoc->properties = XML_DOC_INTERNAL; 12090 ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none", 12091 BAD_CAST "none", BAD_CAST "none"); 12092 12093 if ((enc == XML_CHAR_ENCODING_NONE) && 12094 ((ctxt->input->end - ctxt->input->cur) >= 4)) { 12095 /* 12096 * Get the 4 first bytes and decode the charset 12097 * if enc != XML_CHAR_ENCODING_NONE 12098 * plug some encoding conversion routines. 12099 */ 12100 start[0] = RAW; 12101 start[1] = NXT(1); 12102 start[2] = NXT(2); 12103 start[3] = NXT(3); 12104 enc = xmlDetectCharEncoding(start, 4); 12105 if (enc != XML_CHAR_ENCODING_NONE) { 12106 xmlSwitchEncoding(ctxt, enc); 12107 } 12108 } 12109 12110 xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none"); 12111 12112 if (ctxt->myDoc != NULL) { 12113 if (ctxt->wellFormed) { 12114 ret = ctxt->myDoc->extSubset; 12115 ctxt->myDoc->extSubset = NULL; 12116 if (ret != NULL) { 12117 xmlNodePtr tmp; 12118 12119 ret->doc = NULL; 12120 tmp = ret->children; 12121 while (tmp != NULL) { 12122 tmp->doc = NULL; 12123 tmp = tmp->next; 12124 } 12125 } 12126 } else { 12127 ret = NULL; 12128 } 12129 xmlFreeDoc(ctxt->myDoc); 12130 ctxt->myDoc = NULL; 12131 } 12132 if (sax != NULL) ctxt->sax = NULL; 12133 xmlFreeParserCtxt(ctxt); 12134 12135 return(ret); 12136 } 12137 12149 xmlDtdPtr 12150 xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID, 12151 const xmlChar *SystemID) { 12152 xmlDtdPtr ret = NULL; 12153 xmlParserCtxtPtr ctxt; 12154 xmlParserInputPtr input = NULL; 12155 xmlCharEncoding enc; 12156 xmlChar* systemIdCanonic; 12157 12158 if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL); 12159 12160 ctxt = xmlNewParserCtxt(); 12161 if (ctxt == NULL) { 12162 return(NULL); 12163 } 12164 12165 /* 12166 * Set-up the SAX context 12167 */ 12168 if (sax != NULL) { 12169 if (ctxt->sax != NULL) 12170 xmlFree(ctxt->sax); 12171 ctxt->sax = sax; 12172 ctxt->userData = ctxt; 12173 } 12174 12175 /* 12176 * Canonicalise the system ID 12177 */ 12178 systemIdCanonic = xmlCanonicPath(SystemID); 12179 if ((SystemID != NULL) && (systemIdCanonic == NULL)) { 12180 xmlFreeParserCtxt(ctxt); 12181 return(NULL); 12182 } 12183 12184 /* 12185 * Ask the Entity resolver to load the damn thing 12186 */ 12187 12188 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL)) 12189 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, 12190 systemIdCanonic); 12191 if (input == NULL) { 12192 if (sax != NULL) ctxt->sax = NULL; 12193 xmlFreeParserCtxt(ctxt); 12194 if (systemIdCanonic != NULL) 12195 xmlFree(systemIdCanonic); 12196 return(NULL); 12197 } 12198 12199 /* 12200 * plug some encoding conversion routines here. 12201 */ 12202 if (xmlPushInput(ctxt, input) < 0) { 12203 if (sax != NULL) ctxt->sax = NULL; 12204 xmlFreeParserCtxt(ctxt); 12205 if (systemIdCanonic != NULL) 12206 xmlFree(systemIdCanonic); 12207 return(NULL); 12208 } 12209 if ((ctxt->input->end - ctxt->input->cur) >= 4) { 12210 enc = xmlDetectCharEncoding(ctxt->input->cur, 4); 12211 xmlSwitchEncoding(ctxt, enc); 12212 } 12213 12214 if (input->filename == NULL) 12215 input->filename = (char *) systemIdCanonic; 12216 else 12217 xmlFree(systemIdCanonic); 12218 input->line = 1; 12219 input->col = 1; 12220 input->base = ctxt->input->cur; 12221 input->cur = ctxt->input->cur; 12222 input->free = NULL; 12223 12224 /* 12225 * let's parse that entity knowing it's an external subset. 12226 */ 12227 ctxt->inSubset = 2; 12228 ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0"); 12229 if (ctxt->myDoc == NULL) { 12230 xmlErrMemory(ctxt, "New Doc failed"); 12231 if (sax != NULL) ctxt->sax = NULL; 12232 xmlFreeParserCtxt(ctxt); 12233 return(NULL); 12234 } 12235 ctxt->myDoc->properties = XML_DOC_INTERNAL; 12236 ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none", 12237 ExternalID, SystemID); 12238 xmlParseExternalSubset(ctxt, ExternalID, SystemID); 12239 12240 if (ctxt->myDoc != NULL) { 12241 if (ctxt->wellFormed) { 12242 ret = ctxt->myDoc->extSubset; 12243 ctxt->myDoc->extSubset = NULL; 12244 if (ret != NULL) { 12245 xmlNodePtr tmp; 12246 12247 ret->doc = NULL; 12248 tmp = ret->children; 12249 while (tmp != NULL) { 12250 tmp->doc = NULL; 12251 tmp = tmp->next; 12252 } 12253 } 12254 } else { 12255 ret = NULL; 12256 } 12257 xmlFreeDoc(ctxt->myDoc); 12258 ctxt->myDoc = NULL; 12259 } 12260 if (sax != NULL) ctxt->sax = NULL; 12261 xmlFreeParserCtxt(ctxt); 12262 12263 return(ret); 12264 } 12265 12266 12277 xmlDtdPtr 12278 xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) { 12279 return(xmlSAXParseDTD(NULL, ExternalID, SystemID)); 12280 } 12281 #endif /* LIBXML_VALID_ENABLED */ 12282 12283 /************************************************************************ 12284 * * 12285 * Front ends when parsing an Entity * 12286 * * 12287 ************************************************************************/ 12288 12306 int 12307 xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL, 12308 const xmlChar *ID, xmlNodePtr *lst) { 12309 xmlParserCtxtPtr ctxt; 12310 xmlDocPtr newDoc; 12311 xmlNodePtr newRoot; 12312 xmlSAXHandlerPtr oldsax = NULL; 12313 int ret = 0; 12314 xmlChar start[4]; 12315 xmlCharEncoding enc; 12316 12317 if (ctx == NULL) return(-1); 12318 12319 if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) || 12320 (ctx->depth > 1024)) { 12321 return(XML_ERR_ENTITY_LOOP); 12322 } 12323 12324 if (lst != NULL) 12325 *lst = NULL; 12326 if ((URL == NULL) && (ID == NULL)) 12327 return(-1); 12328 if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */ 12329 return(-1); 12330 12331 ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, ctx); 12332 if (ctxt == NULL) { 12333 return(-1); 12334 } 12335 12336 oldsax = ctxt->sax; 12337 ctxt->sax = ctx->sax; 12338 xmlDetectSAX2(ctxt); 12339 newDoc = xmlNewDoc(BAD_CAST "1.0"); 12340 if (newDoc == NULL) { 12341 xmlFreeParserCtxt(ctxt); 12342 return(-1); 12343 } 12344 newDoc->properties = XML_DOC_INTERNAL; 12345 if (ctx->myDoc->dict) { 12346 newDoc->dict = ctx->myDoc->dict; 12347 xmlDictReference(newDoc->dict); 12348 } 12349 if (ctx->myDoc != NULL) { 12350 newDoc->intSubset = ctx->myDoc->intSubset; 12351 newDoc->extSubset = ctx->myDoc->extSubset; 12352 } 12353 if (ctx->myDoc->URL != NULL) { 12354 newDoc->URL = xmlStrdup(ctx->myDoc->URL); 12355 } 12356 newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL); 12357 if (newRoot == NULL) { 12358 ctxt->sax = oldsax; 12359 xmlFreeParserCtxt(ctxt); 12360 newDoc->intSubset = NULL; 12361 newDoc->extSubset = NULL; 12362 xmlFreeDoc(newDoc); 12363 return(-1); 12364 } 12365 xmlAddChild((xmlNodePtr) newDoc, newRoot); 12366 nodePush(ctxt, newDoc->children); 12367 if (ctx->myDoc == NULL) { 12368 ctxt->myDoc = newDoc; 12369 } else { 12370 ctxt->myDoc = ctx->myDoc; 12371 newDoc->children->doc = ctx->myDoc; 12372 } 12373 12374 /* 12375 * Get the 4 first bytes and decode the charset 12376 * if enc != XML_CHAR_ENCODING_NONE 12377 * plug some encoding conversion routines. 12378 */ 12379 GROW 12380 if ((ctxt->input->end - ctxt->input->cur) >= 4) { 12381 start[0] = RAW; 12382 start[1] = NXT(1); 12383 start[2] = NXT(2); 12384 start[3] = NXT(3); 12385 enc = xmlDetectCharEncoding(start, 4); 12386 if (enc != XML_CHAR_ENCODING_NONE) { 12387 xmlSwitchEncoding(ctxt, enc); 12388 } 12389 } 12390 12391 /* 12392 * Parse a possible text declaration first 12393 */ 12394 if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) { 12395 xmlParseTextDecl(ctxt); 12396 /* 12397 * An XML-1.0 document can't reference an entity not XML-1.0 12398 */ 12399 if ((xmlStrEqual(ctx->version, BAD_CAST "1.0")) && 12400 (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) { 12401 xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH, 12402 "Version mismatch between document and entity\n"); 12403 } 12404 } 12405 12406 /* 12407 * Doing validity checking on chunk doesn't make sense 12408 */ 12409 ctxt->instate = XML_PARSER_CONTENT; 12410 ctxt->validate = ctx->validate; 12411 ctxt->valid = ctx->valid; 12412 ctxt->loadsubset = ctx->loadsubset; 12413 ctxt->depth = ctx->depth + 1; 12414 ctxt->replaceEntities = ctx->replaceEntities; 12415 if (ctxt->validate) { 12416 ctxt->vctxt.error = ctx->vctxt.error; 12417 ctxt->vctxt.warning = ctx->vctxt.warning; 12418 } else { 12419 ctxt->vctxt.error = NULL; 12420 ctxt->vctxt.warning = NULL; 12421 } 12422 ctxt->vctxt.nodeTab = NULL; 12423 ctxt->vctxt.nodeNr = 0; 12424 ctxt->vctxt.nodeMax = 0; 12425 ctxt->vctxt.node = NULL; 12426 if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); 12427 ctxt->dict = ctx->dict; 12428 ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); 12429 ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); 12430 ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); 12431 ctxt->dictNames = ctx->dictNames; 12432 ctxt->attsDefault = ctx->attsDefault; 12433 ctxt->attsSpecial = ctx->attsSpecial; 12434 ctxt->linenumbers = ctx->linenumbers; 12435 12436 xmlParseContent(ctxt); 12437 12438 ctx->validate = ctxt->validate; 12439 ctx->valid = ctxt->valid; 12440 if ((RAW == '<') && (NXT(1) == '/')) { 12441 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 12442 } else if (RAW != 0) { 12443 xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); 12444 } 12445 if (ctxt->node != newDoc->children) { 12446 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 12447 } 12448 12449 if (!ctxt->wellFormed) { 12450 if (ctxt->errNo == 0) 12451 ret = 1; 12452 else 12453 ret = ctxt->errNo; 12454 } else { 12455 if (lst != NULL) { 12456 xmlNodePtr cur; 12457 12458 /* 12459 * Return the newly created nodeset after unlinking it from 12460 * they pseudo parent. 12461 */ 12462 cur = newDoc->children->children; 12463 *lst = cur; 12464 while (cur != NULL) { 12465 cur->parent = NULL; 12466 cur = cur->next; 12467 } 12468 newDoc->children->children = NULL; 12469 } 12470 ret = 0; 12471 } 12472 ctxt->sax = oldsax; 12473 ctxt->dict = NULL; 12474 ctxt->attsDefault = NULL; 12475 ctxt->attsSpecial = NULL; 12476 xmlFreeParserCtxt(ctxt); 12477 newDoc->intSubset = NULL; 12478 newDoc->extSubset = NULL; 12479 xmlFreeDoc(newDoc); 12480 12481 return(ret); 12482 } 12483 12501 static xmlParserErrors 12502 xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, 12503 xmlSAXHandlerPtr sax, 12504 void *user_data, int depth, const xmlChar *URL, 12505 const xmlChar *ID, xmlNodePtr *list) { 12506 xmlParserCtxtPtr ctxt; 12507 xmlDocPtr newDoc; 12508 xmlNodePtr newRoot; 12509 xmlSAXHandlerPtr oldsax = NULL; 12510 xmlParserErrors ret = XML_ERR_OK; 12511 xmlChar start[4]; 12512 xmlCharEncoding enc; 12513 12514 if (((depth > 40) && 12515 ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) || 12516 (depth > 1024)) { 12517 return(XML_ERR_ENTITY_LOOP); 12518 } 12519 12520 if (list != NULL) 12521 *list = NULL; 12522 if ((URL == NULL) && (ID == NULL)) 12523 return(XML_ERR_INTERNAL_ERROR); 12524 if (doc == NULL) 12525 return(XML_ERR_INTERNAL_ERROR); 12526 12527 12528 ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt); 12529 if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY); 12530 ctxt->userData = ctxt; 12531 if (oldctxt != NULL) { 12532 ctxt->_private = oldctxt->_private; 12533 ctxt->loadsubset = oldctxt->loadsubset; 12534 ctxt->validate = oldctxt->validate; 12535 ctxt->external = oldctxt->external; 12536 ctxt->record_info = oldctxt->record_info; 12537 ctxt->node_seq.maximum = oldctxt->node_seq.maximum; 12538 ctxt->node_seq.length = oldctxt->node_seq.length; 12539 ctxt->node_seq.buffer = oldctxt->node_seq.buffer; 12540 } else { 12541 /* 12542 * Doing validity checking on chunk without context 12543 * doesn't make sense 12544 */ 12545 ctxt->_private = NULL; 12546 ctxt->validate = 0; 12547 ctxt->external = 2; 12548 ctxt->loadsubset = 0; 12549 } 12550 if (sax != NULL) { 12551 oldsax = ctxt->sax; 12552 ctxt->sax = sax; 12553 if (user_data != NULL) 12554 ctxt->userData = user_data; 12555 } 12556 xmlDetectSAX2(ctxt); 12557 newDoc = xmlNewDoc(BAD_CAST "1.0"); 12558 if (newDoc == NULL) { 12559 ctxt->node_seq.maximum = 0; 12560 ctxt->node_seq.length = 0; 12561 ctxt->node_seq.buffer = NULL; 12562 xmlFreeParserCtxt(ctxt); 12563 return(XML_ERR_INTERNAL_ERROR); 12564 } 12565 newDoc->properties = XML_DOC_INTERNAL; 12566 newDoc->intSubset = doc->intSubset; 12567 newDoc->extSubset = doc->extSubset; 12568 newDoc->dict = doc->dict; 12569 xmlDictReference(newDoc->dict); 12570 12571 if (doc->URL != NULL) { 12572 newDoc->URL = xmlStrdup(doc->URL); 12573 } 12574 newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL); 12575 if (newRoot == NULL) { 12576 if (sax != NULL) 12577 ctxt->sax = oldsax; 12578 ctxt->node_seq.maximum = 0; 12579 ctxt->node_seq.length = 0; 12580 ctxt->node_seq.buffer = NULL; 12581 xmlFreeParserCtxt(ctxt); 12582 newDoc->intSubset = NULL; 12583 newDoc->extSubset = NULL; 12584 xmlFreeDoc(newDoc); 12585 return(XML_ERR_INTERNAL_ERROR); 12586 } 12587 xmlAddChild((xmlNodePtr) newDoc, newRoot); 12588 nodePush(ctxt, newDoc->children); 12589 ctxt->myDoc = doc; 12590 newRoot->doc = doc; 12591 12592 /* 12593 * Get the 4 first bytes and decode the charset 12594 * if enc != XML_CHAR_ENCODING_NONE 12595 * plug some encoding conversion routines. 12596 */ 12597 GROW; 12598 if ((ctxt->input->end - ctxt->input->cur) >= 4) { 12599 start[0] = RAW; 12600 start[1] = NXT(1); 12601 start[2] = NXT(2); 12602 start[3] = NXT(3); 12603 enc = xmlDetectCharEncoding(start, 4); 12604 if (enc != XML_CHAR_ENCODING_NONE) { 12605 xmlSwitchEncoding(ctxt, enc); 12606 } 12607 } 12608 12609 /* 12610 * Parse a possible text declaration first 12611 */ 12612 if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) { 12613 xmlParseTextDecl(ctxt); 12614 } 12615 12616 ctxt->instate = XML_PARSER_CONTENT; 12617 ctxt->depth = depth; 12618 12619 xmlParseContent(ctxt); 12620 12621 if ((RAW == '<') && (NXT(1) == '/')) { 12622 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 12623 } else if (RAW != 0) { 12624 xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); 12625 } 12626 if (ctxt->node != newDoc->children) { 12627 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 12628 } 12629 12630 if (!ctxt->wellFormed) { 12631 if (ctxt->errNo == 0) 12632 ret = XML_ERR_INTERNAL_ERROR; 12633 else 12634 ret = (xmlParserErrors)ctxt->errNo; 12635 } else { 12636 if (list != NULL) { 12637 xmlNodePtr cur; 12638 12639 /* 12640 * Return the newly created nodeset after unlinking it from 12641 * they pseudo parent. 12642 */ 12643 cur = newDoc->children->children; 12644 *list = cur; 12645 while (cur != NULL) { 12646 cur->parent = NULL; 12647 cur = cur->next; 12648 } 12649 newDoc->children->children = NULL; 12650 } 12651 ret = XML_ERR_OK; 12652 } 12653 12654 /* 12655 * Record in the parent context the number of entities replacement 12656 * done when parsing that reference. 12657 */ 12658 if (oldctxt != NULL) 12659 oldctxt->nbentities += ctxt->nbentities; 12660 12661 /* 12662 * Also record the size of the entity parsed 12663 */ 12664 if (ctxt->input != NULL) { 12665 oldctxt->sizeentities += ctxt->input->consumed; 12666 oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base); 12667 } 12668 /* 12669 * And record the last error if any 12670 */ 12671 if (ctxt->lastError.code != XML_ERR_OK) 12672 xmlCopyError(&ctxt->lastError, &oldctxt->lastError); 12673 12674 if (sax != NULL) 12675 ctxt->sax = oldsax; 12676 oldctxt->node_seq.maximum = ctxt->node_seq.maximum; 12677 oldctxt->node_seq.length = ctxt->node_seq.length; 12678 oldctxt->node_seq.buffer = ctxt->node_seq.buffer; 12679 ctxt->node_seq.maximum = 0; 12680 ctxt->node_seq.length = 0; 12681 ctxt->node_seq.buffer = NULL; 12682 xmlFreeParserCtxt(ctxt); 12683 newDoc->intSubset = NULL; 12684 newDoc->extSubset = NULL; 12685 xmlFreeDoc(newDoc); 12686 12687 return(ret); 12688 } 12689 12690 #ifdef LIBXML_SAX1_ENABLED 12691 12711 int 12712 xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data, 12713 int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) { 12714 return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL, 12715 ID, lst)); 12716 } 12717 12738 int 12739 xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax, 12740 void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) { 12741 return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data, 12742 depth, string, lst, 0 ); 12743 } 12744 #endif /* LIBXML_SAX1_ENABLED */ 12745 12767 static xmlParserErrors 12768 xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, 12769 const xmlChar *string, void *user_data, xmlNodePtr *lst) { 12770 xmlParserCtxtPtr ctxt; 12771 xmlDocPtr newDoc = NULL; 12772 xmlNodePtr newRoot; 12773 xmlSAXHandlerPtr oldsax = NULL; 12774 xmlNodePtr content = NULL; 12775 xmlNodePtr last = NULL; 12776 int size; 12777 xmlParserErrors ret = XML_ERR_OK; 12778 #ifdef SAX2 12779 int i; 12780 #endif 12781 12782 if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) || 12783 (oldctxt->depth > 1024)) { 12784 return(XML_ERR_ENTITY_LOOP); 12785 } 12786 12787 12788 if (lst != NULL) 12789 *lst = NULL; 12790 if (string == NULL) 12791 return(XML_ERR_INTERNAL_ERROR); 12792 12793 size = xmlStrlen(string); 12794 12795 ctxt = xmlCreateMemoryParserCtxt((char *) string, size); 12796 if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY); 12797 if (user_data != NULL) 12798 ctxt->userData = user_data; 12799 else 12800 ctxt->userData = ctxt; 12801 if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); 12802 ctxt->dict = oldctxt->dict; 12803 ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); 12804 ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); 12805 ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); 12806 12807 #ifdef SAX2 12808 /* propagate namespaces down the entity */ 12809 for (i = 0;i < oldctxt->nsNr;i += 2) { 12810 nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]); 12811 } 12812 #endif 12813 12814 oldsax = ctxt->sax; 12815 ctxt->sax = oldctxt->sax; 12816 xmlDetectSAX2(ctxt); 12817 ctxt->replaceEntities = oldctxt->replaceEntities; 12818 ctxt->options = oldctxt->options; 12819 12820 ctxt->_private = oldctxt->_private; 12821 if (oldctxt->myDoc == NULL) { 12822 newDoc = xmlNewDoc(BAD_CAST "1.0"); 12823 if (newDoc == NULL) { 12824 ctxt->sax = oldsax; 12825 ctxt->dict = NULL; 12826 xmlFreeParserCtxt(ctxt); 12827 return(XML_ERR_INTERNAL_ERROR); 12828 } 12829 newDoc->properties = XML_DOC_INTERNAL; 12830 newDoc->dict = ctxt->dict; 12831 xmlDictReference(newDoc->dict); 12832 ctxt->myDoc = newDoc; 12833 } else { 12834 ctxt->myDoc = oldctxt->myDoc; 12835 content = ctxt->myDoc->children; 12836 last = ctxt->myDoc->last; 12837 } 12838 newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL); 12839 if (newRoot == NULL) { 12840 ctxt->sax = oldsax; 12841 ctxt->dict = NULL; 12842 xmlFreeParserCtxt(ctxt); 12843 if (newDoc != NULL) { 12844 xmlFreeDoc(newDoc); 12845 } 12846 return(XML_ERR_INTERNAL_ERROR); 12847 } 12848 ctxt->myDoc->children = NULL; 12849 ctxt->myDoc->last = NULL; 12850 xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot); 12851 nodePush(ctxt, ctxt->myDoc->children); 12852 ctxt->instate = XML_PARSER_CONTENT; 12853 ctxt->depth = oldctxt->depth + 1; 12854 12855 ctxt->validate = 0; 12856 ctxt->loadsubset = oldctxt->loadsubset; 12857 if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) { 12858 /* 12859 * ID/IDREF registration will be done in xmlValidateElement below 12860 */ 12861 ctxt->loadsubset |= XML_SKIP_IDS; 12862 } 12863 ctxt->dictNames = oldctxt->dictNames; 12864 ctxt->attsDefault = oldctxt->attsDefault; 12865 ctxt->attsSpecial = oldctxt->attsSpecial; 12866 12867 xmlParseContent(ctxt); 12868 if ((RAW == '<') && (NXT(1) == '/')) { 12869 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 12870 } else if (RAW != 0) { 12871 xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); 12872 } 12873 if (ctxt->node != ctxt->myDoc->children) { 12874 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 12875 } 12876 12877 if (!ctxt->wellFormed) { 12878 if (ctxt->errNo == 0) 12879 ret = XML_ERR_INTERNAL_ERROR; 12880 else 12881 ret = (xmlParserErrors)ctxt->errNo; 12882 } else { 12883 ret = XML_ERR_OK; 12884 } 12885 12886 if ((lst != NULL) && (ret == XML_ERR_OK)) { 12887 xmlNodePtr cur; 12888 12889 /* 12890 * Return the newly created nodeset after unlinking it from 12891 * they pseudo parent. 12892 */ 12893 cur = ctxt->myDoc->children->children; 12894 *lst = cur; 12895 while (cur != NULL) { 12896 #ifdef LIBXML_VALID_ENABLED 12897 if ((oldctxt->validate) && (oldctxt->wellFormed) && 12898 (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) && 12899 (cur->type == XML_ELEMENT_NODE)) { 12900 oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt, 12901 oldctxt->myDoc, cur); 12902 } 12903 #endif /* LIBXML_VALID_ENABLED */ 12904 cur->parent = NULL; 12905 cur = cur->next; 12906 } 12907 ctxt->myDoc->children->children = NULL; 12908 } 12909 if (ctxt->myDoc != NULL) { 12910 xmlFreeNode(ctxt->myDoc->children); 12911 ctxt->myDoc->children = content; 12912 ctxt->myDoc->last = last; 12913 } 12914 12915 /* 12916 * Record in the parent context the number of entities replacement 12917 * done when parsing that reference. 12918 */ 12919 if (oldctxt != NULL) 12920 oldctxt->nbentities += ctxt->nbentities; 12921 12922 /* 12923 * Also record the last error if any 12924 */ 12925 if (ctxt->lastError.code != XML_ERR_OK) 12926 xmlCopyError(&ctxt->lastError, &oldctxt->lastError); 12927 12928 ctxt->sax = oldsax; 12929 ctxt->dict = NULL; 12930 ctxt->attsDefault = NULL; 12931 ctxt->attsSpecial = NULL; 12932 xmlFreeParserCtxt(ctxt); 12933 if (newDoc != NULL) { 12934 xmlFreeDoc(newDoc); 12935 } 12936 12937 return(ret); 12938 } 12939 12959 xmlParserErrors 12960 xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, 12961 int options, xmlNodePtr *lst) { 12962 #ifdef SAX2 12963 xmlParserCtxtPtr ctxt; 12964 xmlDocPtr doc = NULL; 12965 xmlNodePtr fake, cur; 12966 int nsnr = 0; 12967 12968 xmlParserErrors ret = XML_ERR_OK; 12969 12970 /* 12971 * check all input parameters, grab the document 12972 */ 12973 if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0)) 12974 return(XML_ERR_INTERNAL_ERROR); 12975 switch (node->type) { 12976 case XML_ELEMENT_NODE: 12977 case XML_ATTRIBUTE_NODE: 12978 case XML_TEXT_NODE: 12979 case XML_CDATA_SECTION_NODE: 12980 case XML_ENTITY_REF_NODE: 12981 case XML_PI_NODE: 12982 case XML_COMMENT_NODE: 12983 case XML_DOCUMENT_NODE: 12984 case XML_HTML_DOCUMENT_NODE: 12985 break; 12986 default: 12987 return(XML_ERR_INTERNAL_ERROR); 12988 12989 } 12990 while ((node != NULL) && (node->type != XML_ELEMENT_NODE) && 12991 (node->type != XML_DOCUMENT_NODE) && 12992 (node->type != XML_HTML_DOCUMENT_NODE)) 12993 node = node->parent; 12994 if (node == NULL) 12995 return(XML_ERR_INTERNAL_ERROR); 12996 if (node->type == XML_ELEMENT_NODE) 12997 doc = node->doc; 12998 else 12999 doc = (xmlDocPtr) node; 13000 if (doc == NULL) 13001 return(XML_ERR_INTERNAL_ERROR); 13002 13003 /* 13004 * allocate a context and set-up everything not related to the 13005 * node position in the tree 13006 */ 13007 if (doc->type == XML_DOCUMENT_NODE) 13008 ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen); 13009 #ifdef LIBXML_HTML_ENABLED 13010 else if (doc->type == XML_HTML_DOCUMENT_NODE) { 13011 ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen); 13012 /* 13013 * When parsing in context, it makes no sense to add implied 13014 * elements like html/body/etc... 13015 */ 13016 options |= HTML_PARSE_NOIMPLIED; 13017 } 13018 #endif 13019 else 13020 return(XML_ERR_INTERNAL_ERROR); 13021 13022 if (ctxt == NULL) 13023 return(XML_ERR_NO_MEMORY); 13024 13025 /* 13026 * Use input doc's dict if present, else assure XML_PARSE_NODICT is set. 13027 * We need a dictionary for xmlDetectSAX2, so if there's no doc dict 13028 * we must wait until the last moment to free the original one. 13029 */ 13030 if (doc->dict != NULL) { 13031 if (ctxt->dict != NULL) 13032 xmlDictFree(ctxt->dict); 13033 ctxt->dict = doc->dict; 13034 } else 13035 options |= XML_PARSE_NODICT; 13036 13037 if (doc->encoding != NULL) { 13038 xmlCharEncodingHandlerPtr hdlr; 13039 13040 if (ctxt->encoding != NULL) 13041 xmlFree((xmlChar *) ctxt->encoding); 13042 ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding); 13043 13044 hdlr = xmlFindCharEncodingHandler(doc->encoding); 13045 if (hdlr != NULL) { 13046 xmlSwitchToEncoding(ctxt, hdlr); 13047 } else { 13048 return(XML_ERR_UNSUPPORTED_ENCODING); 13049 } 13050 } 13051 13052 xmlCtxtUseOptionsInternal(ctxt, options, NULL); 13053 xmlDetectSAX2(ctxt); 13054 ctxt->myDoc = doc; 13055 13056 fake = xmlNewComment(NULL); 13057 if (fake == NULL) { 13058 xmlFreeParserCtxt(ctxt); 13059 return(XML_ERR_NO_MEMORY); 13060 } 13061 xmlAddChild(node, fake); 13062 13063 if (node->type == XML_ELEMENT_NODE) { 13064 nodePush(ctxt, node); 13065 /* 13066 * initialize the SAX2 namespaces stack 13067 */ 13068 cur = node; 13069 while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) { 13070 xmlNsPtr ns = cur->nsDef; 13071 const xmlChar *iprefix, *ihref; 13072 13073 while (ns != NULL) { 13074 if (ctxt->dict) { 13075 iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1); 13076 ihref = xmlDictLookup(ctxt->dict, ns->href, -1); 13077 } else { 13078 iprefix = ns->prefix; 13079 ihref = ns->href; 13080 } 13081 13082 if (xmlGetNamespace(ctxt, iprefix) == NULL) { 13083 nsPush(ctxt, iprefix, ihref); 13084 nsnr++; 13085 } 13086 ns = ns->next; 13087 } 13088 cur = cur->parent; 13089 } 13090 ctxt->instate = XML_PARSER_CONTENT; 13091 } 13092 13093 if ((ctxt->validate) || (ctxt->replaceEntities != 0)) { 13094 /* 13095 * ID/IDREF registration will be done in xmlValidateElement below 13096 */ 13097 ctxt->loadsubset |= XML_SKIP_IDS; 13098 } 13099 13100 #ifdef LIBXML_HTML_ENABLED 13101 if (doc->type == XML_HTML_DOCUMENT_NODE) 13102 __htmlParseContent(ctxt); 13103 else 13104 #endif 13105 xmlParseContent(ctxt); 13106 13107 nsPop(ctxt, nsnr); 13108 if ((RAW == '<') && (NXT(1) == '/')) { 13109 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 13110 } else if (RAW != 0) { 13111 xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); 13112 } 13113 if ((ctxt->node != NULL) && (ctxt->node != node)) { 13114 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 13115 ctxt->wellFormed = 0; 13116 } 13117 13118 if (!ctxt->wellFormed) { 13119 if (ctxt->errNo == 0) 13120 ret = XML_ERR_INTERNAL_ERROR; 13121 else 13122 ret = (xmlParserErrors)ctxt->errNo; 13123 } else { 13124 ret = XML_ERR_OK; 13125 } 13126 13127 /* 13128 * Return the newly created nodeset after unlinking it from 13129 * the pseudo sibling. 13130 */ 13131 13132 cur = fake->next; 13133 fake->next = NULL; 13134 node->last = fake; 13135 13136 if (cur != NULL) { 13137 cur->prev = NULL; 13138 } 13139 13140 *lst = cur; 13141 13142 while (cur != NULL) { 13143 cur->parent = NULL; 13144 cur = cur->next; 13145 } 13146 13147 xmlUnlinkNode(fake); 13148 xmlFreeNode(fake); 13149 13150 13151 if (ret != XML_ERR_OK) { 13152 xmlFreeNodeList(*lst); 13153 *lst = NULL; 13154 } 13155 13156 if (doc->dict != NULL) 13157 ctxt->dict = NULL; 13158 xmlFreeParserCtxt(ctxt); 13159 13160 return(ret); 13161 #else /* !SAX2 */ 13162 return(XML_ERR_INTERNAL_ERROR); 13163 #endif 13164 } 13165 13166 #ifdef LIBXML_SAX1_ENABLED 13167 13192 int 13193 xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax, 13194 void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst, 13195 int recover) { 13196 xmlParserCtxtPtr ctxt; 13197 xmlDocPtr newDoc; 13198 xmlSAXHandlerPtr oldsax = NULL; 13199 xmlNodePtr content, newRoot; 13200 int size; 13201 int ret = 0; 13202 13203 if (depth > 40) { 13204 return(XML_ERR_ENTITY_LOOP); 13205 } 13206 13207 13208 if (lst != NULL) 13209 *lst = NULL; 13210 if (string == NULL) 13211 return(-1); 13212 13213 size = xmlStrlen(string); 13214 13215 ctxt = xmlCreateMemoryParserCtxt((char *) string, size); 13216 if (ctxt == NULL) return(-1); 13217 ctxt->userData = ctxt; 13218 if (sax != NULL) { 13219 oldsax = ctxt->sax; 13220 ctxt->sax = sax; 13221 if (user_data != NULL) 13222 ctxt->userData = user_data; 13223 } 13224 newDoc = xmlNewDoc(BAD_CAST "1.0"); 13225 if (newDoc == NULL) { 13226 xmlFreeParserCtxt(ctxt); 13227 return(-1); 13228 } 13229 newDoc->properties = XML_DOC_INTERNAL; 13230 if ((doc != NULL) && (doc->dict != NULL)) { 13231 xmlDictFree(ctxt->dict); 13232 ctxt->dict = doc->dict; 13233 xmlDictReference(ctxt->dict); 13234 ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); 13235 ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); 13236 ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); 13237 ctxt->dictNames = 1; 13238 } else { 13239 xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL); 13240 } 13241 if (doc != NULL) { 13242 newDoc->intSubset = doc->intSubset; 13243 newDoc->extSubset = doc->extSubset; 13244 } 13245 newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL); 13246 if (newRoot == NULL) { 13247 if (sax != NULL) 13248 ctxt->sax = oldsax; 13249 xmlFreeParserCtxt(ctxt); 13250 newDoc->intSubset = NULL; 13251 newDoc->extSubset = NULL; 13252 xmlFreeDoc(newDoc); 13253 return(-1); 13254 } 13255 xmlAddChild((xmlNodePtr) newDoc, newRoot); 13256 nodePush(ctxt, newRoot); 13257 if (doc == NULL) { 13258 ctxt->myDoc = newDoc; 13259 } else { 13260 ctxt->myDoc = newDoc; 13261 newDoc->children->doc = doc; 13262 /* Ensure that doc has XML spec namespace */ 13263 xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE); 13264 newDoc->oldNs = doc->oldNs; 13265 } 13266 ctxt->instate = XML_PARSER_CONTENT; 13267 ctxt->depth = depth; 13268 13269 /* 13270 * Doing validity checking on chunk doesn't make sense 13271 */ 13272 ctxt->validate = 0; 13273 ctxt->loadsubset = 0; 13274 xmlDetectSAX2(ctxt); 13275 13276 if ( doc != NULL ){ 13277 content = doc->children; 13278 doc->children = NULL; 13279 xmlParseContent(ctxt); 13280 doc->children = content; 13281 } 13282 else { 13283 xmlParseContent(ctxt); 13284 } 13285 if ((RAW == '<') && (NXT(1) == '/')) { 13286 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 13287 } else if (RAW != 0) { 13288 xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); 13289 } 13290 if (ctxt->node != newDoc->children) { 13291 xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); 13292 } 13293 13294 if (!ctxt->wellFormed) { 13295 if (ctxt->errNo == 0) 13296 ret = 1; 13297 else 13298 ret = ctxt->errNo; 13299 } else { 13300 ret = 0; 13301 } 13302 13303 if ((lst != NULL) && ((ret == 0) || (recover == 1))) { 13304 xmlNodePtr cur; 13305 13306 /* 13307 * Return the newly created nodeset after unlinking it from 13308 * they pseudo parent. 13309 */ 13310 cur = newDoc->children->children; 13311 *lst = cur; 13312 while (cur != NULL) { 13313 xmlSetTreeDoc(cur, doc); 13314 cur->parent = NULL; 13315 cur = cur->next; 13316 } 13317 newDoc->children->children = NULL; 13318 } 13319 13320 if (sax != NULL) 13321 ctxt->sax = oldsax; 13322 xmlFreeParserCtxt(ctxt); 13323 newDoc->intSubset = NULL; 13324 newDoc->extSubset = NULL; 13325 newDoc->oldNs = NULL; 13326 xmlFreeDoc(newDoc); 13327 13328 return(ret); 13329 } 13330 13347 xmlDocPtr 13348 xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) { 13349 xmlDocPtr ret; 13350 xmlParserCtxtPtr ctxt; 13351 13352 ctxt = xmlCreateFileParserCtxt(filename); 13353 if (ctxt == NULL) { 13354 return(NULL); 13355 } 13356 if (sax != NULL) { 13357 if (ctxt->sax != NULL) 13358 xmlFree(ctxt->sax); 13359 ctxt->sax = sax; 13360 ctxt->userData = NULL; 13361 } 13362 13363 xmlParseExtParsedEnt(ctxt); 13364 13365 if (ctxt->wellFormed) 13366 ret = ctxt->myDoc; 13367 else { 13368 ret = NULL; 13369 xmlFreeDoc(ctxt->myDoc); 13370 ctxt->myDoc = NULL; 13371 } 13372 if (sax != NULL) 13373 ctxt->sax = NULL; 13374 xmlFreeParserCtxt(ctxt); 13375 13376 return(ret); 13377 } 13378 13392 xmlDocPtr 13393 xmlParseEntity(const char *filename) { 13394 return(xmlSAXParseEntity(NULL, filename)); 13395 } 13396 #endif /* LIBXML_SAX1_ENABLED */ 13397 13411 static xmlParserCtxtPtr 13412 xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID, 13413 const xmlChar *base, xmlParserCtxtPtr pctx) { 13414 xmlParserCtxtPtr ctxt; 13415 xmlParserInputPtr inputStream; 13416 char *directory = NULL; 13417 xmlChar *uri; 13418 13419 ctxt = xmlNewParserCtxt(); 13420 if (ctxt == NULL) { 13421 return(NULL); 13422 } 13423 13424 if (pctx != NULL) { 13425 ctxt->options = pctx->options; 13426 ctxt->_private = pctx->_private; 13427 } 13428 13429 uri = xmlBuildURI(URL, base); 13430 13431 if (uri == NULL) { 13432 inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt); 13433 if (inputStream == NULL) { 13434 xmlFreeParserCtxt(ctxt); 13435 return(NULL); 13436 } 13437 13438 inputPush(ctxt, inputStream); 13439 13440 if ((ctxt->directory == NULL) && (directory == NULL)) 13441 directory = xmlParserGetDirectory((char *)URL); 13442 if ((ctxt->directory == NULL) && (directory != NULL)) 13443 ctxt->directory = directory; 13444 } else { 13445 inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt); 13446 if (inputStream == NULL) { 13447 xmlFree(uri); 13448 xmlFreeParserCtxt(ctxt); 13449 return(NULL); 13450 } 13451 13452 inputPush(ctxt, inputStream); 13453 13454 if ((ctxt->directory == NULL) && (directory == NULL)) 13455 directory = xmlParserGetDirectory((char *)uri); 13456 if ((ctxt->directory == NULL) && (directory != NULL)) 13457 ctxt->directory = directory; 13458 xmlFree(uri); 13459 } 13460 return(ctxt); 13461 } 13462 13475 xmlParserCtxtPtr 13476 xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID, 13477 const xmlChar *base) { 13478 return xmlCreateEntityParserCtxtInternal(URL, ID, base, NULL); 13479 13480 } 13481 13482 /************************************************************************ 13483 * * 13484 * Front ends when parsing from a file * 13485 * * 13486 ************************************************************************/ 13487 13499 xmlParserCtxtPtr 13500 xmlCreateURLParserCtxt(const char *filename, int options) 13501 { 13502 xmlParserCtxtPtr ctxt; 13503 xmlParserInputPtr inputStream; 13504 char *directory = NULL; 13505 13506 ctxt = xmlNewParserCtxt(); 13507 if (ctxt == NULL) { 13508 xmlErrMemory(NULL, "cannot allocate parser context"); 13509 return(NULL); 13510 } 13511 13512 if (options) 13513 xmlCtxtUseOptionsInternal(ctxt, options, NULL); 13514 ctxt->linenumbers = 1; 13515 13516 inputStream = xmlLoadExternalEntity(filename, NULL, ctxt); 13517 if (inputStream == NULL) { 13518 xmlFreeParserCtxt(ctxt); 13519 return(NULL); 13520 } 13521 13522 inputPush(ctxt, inputStream); 13523 if ((ctxt->directory == NULL) && (directory == NULL)) 13524 directory = xmlParserGetDirectory(filename); 13525 if ((ctxt->directory == NULL) && (directory != NULL)) 13526 ctxt->directory = directory; 13527 13528 return(ctxt); 13529 } 13530 13541 xmlParserCtxtPtr 13542 xmlCreateFileParserCtxt(const char *filename) 13543 { 13544 return(xmlCreateURLParserCtxt(filename, 0)); 13545 } 13546 13547 #ifdef LIBXML_SAX1_ENABLED 13548 13567 xmlDocPtr 13568 xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename, 13569 int recovery, void *data) { 13570 xmlDocPtr ret; 13571 xmlParserCtxtPtr ctxt; 13572 13573 xmlInitParser(); 13574 13575 ctxt = xmlCreateFileParserCtxt(filename); 13576 if (ctxt == NULL) { 13577 return(NULL); 13578 } 13579 if (sax != NULL) { 13580 if (ctxt->sax != NULL) 13581 xmlFree(ctxt->sax); 13582 ctxt->sax = sax; 13583 } 13584 xmlDetectSAX2(ctxt); 13585 if (data!=NULL) { 13586 ctxt->_private = data; 13587 } 13588 13589 if (ctxt->directory == NULL) 13590 ctxt->directory = xmlParserGetDirectory(filename); 13591 13592 ctxt->recovery = recovery; 13593 13594 xmlParseDocument(ctxt); 13595 13596 if ((ctxt->wellFormed) || recovery) { 13597 ret = ctxt->myDoc; 13598 if (ret != NULL) { 13599 if (ctxt->input->buf->compressed > 0) 13600 ret->compression = 9; 13601 else 13602 ret->compression = ctxt->input->buf->compressed; 13603 } 13604 } 13605 else { 13606 ret = NULL; 13607 xmlFreeDoc(ctxt->myDoc); 13608 ctxt->myDoc = NULL; 13609 } 13610 if (sax != NULL) 13611 ctxt->sax = NULL; 13612 xmlFreeParserCtxt(ctxt); 13613 13614 return(ret); 13615 } 13616 13632 xmlDocPtr 13633 xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename, 13634 int recovery) { 13635 return(xmlSAXParseFileWithData(sax,filename,recovery,NULL)); 13636 } 13637 13649 xmlDocPtr 13650 xmlRecoverDoc(const xmlChar *cur) { 13651 return(xmlSAXParseDoc(NULL, cur, 1)); 13652 } 13653 13665 xmlDocPtr 13666 xmlParseFile(const char *filename) { 13667 return(xmlSAXParseFile(NULL, filename, 0)); 13668 } 13669 13682 xmlDocPtr 13683 xmlRecoverFile(const char *filename) { 13684 return(xmlSAXParseFile(NULL, filename, 1)); 13685 } 13686 13687 13698 void 13699 xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer, 13700 const char* filename) 13701 { 13702 xmlParserInputPtr input; 13703 13704 if ((ctxt == NULL) || (buffer == NULL)) 13705 return; 13706 13707 input = xmlNewInputStream(ctxt); 13708 if (input == NULL) { 13709 xmlErrMemory(NULL, "parsing new buffer: out of memory\n"); 13710 xmlClearParserCtxt(ctxt); 13711 return; 13712 } 13713 13714 xmlClearParserCtxt(ctxt); 13715 if (filename != NULL) 13716 input->filename = (char *) xmlCanonicPath((const xmlChar *)filename); 13717 input->base = buffer; 13718 input->cur = buffer; 13719 input->end = &buffer[xmlStrlen(buffer)]; 13720 inputPush(ctxt, input); 13721 } 13722 13734 int 13735 xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data, 13736 const char *filename) { 13737 int ret = 0; 13738 xmlParserCtxtPtr ctxt; 13739 13740 ctxt = xmlCreateFileParserCtxt(filename); 13741 if (ctxt == NULL) return -1; 13742 if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) 13743 xmlFree(ctxt->sax); 13744 ctxt->sax = sax; 13745 xmlDetectSAX2(ctxt); 13746 13747 if (user_data != NULL) 13748 ctxt->userData = user_data; 13749 13750 xmlParseDocument(ctxt); 13751 13752 if (ctxt->wellFormed) 13753 ret = 0; 13754 else { 13755 if (ctxt->errNo != 0) 13756 ret = ctxt->errNo; 13757 else 13758 ret = -1; 13759 } 13760 if (sax != NULL) 13761 ctxt->sax = NULL; 13762 if (ctxt->myDoc != NULL) { 13763 xmlFreeDoc(ctxt->myDoc); 13764 ctxt->myDoc = NULL; 13765 } 13766 xmlFreeParserCtxt(ctxt); 13767 13768 return ret; 13769 } 13770 #endif /* LIBXML_SAX1_ENABLED */ 13771 13772 /************************************************************************ 13773 * * 13774 * Front ends when parsing from memory * 13775 * * 13776 ************************************************************************/ 13777 13787 xmlParserCtxtPtr 13788 xmlCreateMemoryParserCtxt(const char *buffer, int size) { 13789 xmlParserCtxtPtr ctxt; 13790 xmlParserInputPtr input; 13791 xmlParserInputBufferPtr buf; 13792 13793 if (buffer == NULL) 13794 return(NULL); 13795 if (size <= 0) 13796 return(NULL); 13797 13798 ctxt = xmlNewParserCtxt(); 13799 if (ctxt == NULL) 13800 return(NULL); 13801 13802 /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */ 13803 buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); 13804 if (buf == NULL) { 13805 xmlFreeParserCtxt(ctxt); 13806 return(NULL); 13807 } 13808 13809 input = xmlNewInputStream(ctxt); 13810 if (input == NULL) { 13811 xmlFreeParserInputBuffer(buf); 13812 xmlFreeParserCtxt(ctxt); 13813 return(NULL); 13814 } 13815 13816 input->filename = NULL; 13817 input->buf = buf; 13818 input->base = input->buf->buffer->content; 13819 input->cur = input->buf->buffer->content; 13820 input->end = &input->buf->buffer->content[input->buf->buffer->use]; 13821 13822 inputPush(ctxt, input); 13823 return(ctxt); 13824 } 13825 13826 #ifdef LIBXML_SAX1_ENABLED 13827 13846 xmlDocPtr 13847 xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer, 13848 int size, int recovery, void *data) { 13849 xmlDocPtr ret; 13850 xmlParserCtxtPtr ctxt; 13851 13852 xmlInitParser(); 13853 13854 ctxt = xmlCreateMemoryParserCtxt(buffer, size); 13855 if (ctxt == NULL) return(NULL); 13856 if (sax != NULL) { 13857 if (ctxt->sax != NULL) 13858 xmlFree(ctxt->sax); 13859 ctxt->sax = sax; 13860 } 13861 xmlDetectSAX2(ctxt); 13862 if (data!=NULL) { 13863 ctxt->_private=data; 13864 } 13865 13866 ctxt->recovery = recovery; 13867 13868 xmlParseDocument(ctxt); 13869 13870 if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc; 13871 else { 13872 ret = NULL; 13873 xmlFreeDoc(ctxt->myDoc); 13874 ctxt->myDoc = NULL; 13875 } 13876 if (sax != NULL) 13877 ctxt->sax = NULL; 13878 xmlFreeParserCtxt(ctxt); 13879 13880 return(ret); 13881 } 13882 13897 xmlDocPtr 13898 xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer, 13899 int size, int recovery) { 13900 return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL); 13901 } 13902 13913 xmlDocPtr xmlParseMemory(const char *buffer, int size) { 13914 return(xmlSAXParseMemory(NULL, buffer, size, 0)); 13915 } 13916 13929 xmlDocPtr xmlRecoverMemory(const char *buffer, int size) { 13930 return(xmlSAXParseMemory(NULL, buffer, size, 1)); 13931 } 13932 13945 int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data, 13946 const char *buffer, int size) { 13947 int ret = 0; 13948 xmlParserCtxtPtr ctxt; 13949 13950 xmlInitParser(); 13951 13952 ctxt = xmlCreateMemoryParserCtxt(buffer, size); 13953 if (ctxt == NULL) return -1; 13954 if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) 13955 xmlFree(ctxt->sax); 13956 ctxt->sax = sax; 13957 xmlDetectSAX2(ctxt); 13958 13959 if (user_data != NULL) 13960 ctxt->userData = user_data; 13961 13962 xmlParseDocument(ctxt); 13963 13964 if (ctxt->wellFormed) 13965 ret = 0; 13966 else { 13967 if (ctxt->errNo != 0) 13968 ret = ctxt->errNo; 13969 else 13970 ret = -1; 13971 } 13972 if (sax != NULL) 13973 ctxt->sax = NULL; 13974 if (ctxt->myDoc != NULL) { 13975 xmlFreeDoc(ctxt->myDoc); 13976 ctxt->myDoc = NULL; 13977 } 13978 xmlFreeParserCtxt(ctxt); 13979 13980 return ret; 13981 } 13982 #endif /* LIBXML_SAX1_ENABLED */ 13983 13992 xmlParserCtxtPtr 13993 xmlCreateDocParserCtxt(const xmlChar *cur) { 13994 int len; 13995 13996 if (cur == NULL) 13997 return(NULL); 13998 len = xmlStrlen(cur); 13999 return(xmlCreateMemoryParserCtxt((const char *)cur, len)); 14000 } 14001 14002 #ifdef LIBXML_SAX1_ENABLED 14003 14017 xmlDocPtr 14018 xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) { 14019 xmlDocPtr ret; 14020 xmlParserCtxtPtr ctxt; 14021 xmlSAXHandlerPtr oldsax = NULL; 14022 14023 if (cur == NULL) return(NULL); 14024 14025 14026 ctxt = xmlCreateDocParserCtxt(cur); 14027 if (ctxt == NULL) return(NULL); 14028 if (sax != NULL) { 14029 oldsax = ctxt->sax; 14030 ctxt->sax = sax; 14031 ctxt->userData = NULL; 14032 } 14033 xmlDetectSAX2(ctxt); 14034 14035 xmlParseDocument(ctxt); 14036 if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc; 14037 else { 14038 ret = NULL; 14039 xmlFreeDoc(ctxt->myDoc); 14040 ctxt->myDoc = NULL; 14041 } 14042 if (sax != NULL) 14043 ctxt->sax = oldsax; 14044 xmlFreeParserCtxt(ctxt); 14045 14046 return(ret); 14047 } 14048 14058 xmlDocPtr 14059 xmlParseDoc(const xmlChar *cur) { 14060 return(xmlSAXParseDoc(NULL, cur, 0)); 14061 } 14062 #endif /* LIBXML_SAX1_ENABLED */ 14063 14064 #ifdef LIBXML_LEGACY_ENABLED 14065 /************************************************************************ 14066 * * 14067 * Specific function to keep track of entities references * 14068 * and used by the XSLT debugger * 14069 * * 14070 ************************************************************************/ 14071 14072 static xmlEntityReferenceFunc xmlEntityRefFunc = NULL; 14073 14082 static void 14083 xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode, 14084 xmlNodePtr lastNode) 14085 { 14086 if (xmlEntityRefFunc != NULL) { 14087 (*xmlEntityRefFunc) (ent, firstNode, lastNode); 14088 } 14089 } 14090 14091 14098 void 14099 xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func) 14100 { 14101 xmlEntityRefFunc = func; 14102 } 14103 #endif /* LIBXML_LEGACY_ENABLED */ 14104 14105 /************************************************************************ 14106 * * 14107 * Miscellaneous * 14108 * * 14109 ************************************************************************/ 14110 14111 #ifdef LIBXML_XPATH_ENABLED 14112 #include <libxml/xpath.h> 14113 #endif 14114 14115 extern void XMLCDECL xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...); 14116 static int xmlParserInitialized = 0; 14117 14126 void 14127 xmlInitParser(void) { 14128 if (xmlParserInitialized != 0) 14129 return; 14130 14131 #ifdef LIBXML_THREAD_ENABLED 14132 __xmlGlobalInitMutexLock(); 14133 if (xmlParserInitialized == 0) { 14134 #endif 14135 xmlInitThreads(); 14136 xmlInitGlobals(); 14137 if ((xmlGenericError == xmlGenericErrorDefaultFunc) || 14138 (xmlGenericError == NULL)) 14139 initGenericErrorDefaultFunc(NULL); 14140 xmlInitMemory(); 14141 xmlInitCharEncodingHandlers(); 14142 xmlDefaultSAXHandlerInit(); 14143 xmlRegisterDefaultInputCallbacks(); 14144 #ifdef LIBXML_OUTPUT_ENABLED 14145 xmlRegisterDefaultOutputCallbacks(); 14146 #endif /* LIBXML_OUTPUT_ENABLED */ 14147 #ifdef LIBXML_HTML_ENABLED 14148 htmlInitAutoClose(); 14149 htmlDefaultSAXHandlerInit(); 14150 #endif 14151 #ifdef LIBXML_XPATH_ENABLED 14152 xmlXPathInit(); 14153 #endif 14154 xmlParserInitialized = 1; 14155 #ifdef LIBXML_THREAD_ENABLED 14156 } 14157 __xmlGlobalInitMutexUnlock(); 14158 #endif 14159 } 14160 14183 void 14184 xmlCleanupParser(void) { 14185 if (!xmlParserInitialized) 14186 return; 14187 14188 xmlCleanupCharEncodingHandlers(); 14189 #ifdef LIBXML_CATALOG_ENABLED 14190 xmlCatalogCleanup(); 14191 #endif 14192 xmlDictCleanup(); 14193 xmlCleanupInputCallbacks(); 14194 #ifdef LIBXML_OUTPUT_ENABLED 14195 xmlCleanupOutputCallbacks(); 14196 #endif 14197 #ifdef LIBXML_SCHEMAS_ENABLED 14198 xmlSchemaCleanupTypes(); 14199 xmlRelaxNGCleanupTypes(); 14200 #endif 14201 xmlCleanupGlobals(); 14202 xmlResetLastError(); 14203 xmlCleanupThreads(); /* must be last if called not from the main thread */ 14204 xmlCleanupMemory(); 14205 xmlParserInitialized = 0; 14206 } 14207 14208 /************************************************************************ 14209 * * 14210 * New set (2.6.0) of simpler and more flexible APIs * 14211 * * 14212 ************************************************************************/ 14213 14221 #define DICT_FREE(str) \ 14222 if ((str) && ((!dict) || \ 14223 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ 14224 xmlFree((char *)(str)); 14225 14232 void 14233 xmlCtxtReset(xmlParserCtxtPtr ctxt) 14234 { 14235 xmlParserInputPtr input; 14236 xmlDictPtr dict; 14237 14238 if (ctxt == NULL) 14239 return; 14240 14241 dict = ctxt->dict; 14242 14243 while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */ 14244 xmlFreeInputStream(input); 14245 } 14246 ctxt->inputNr = 0; 14247 ctxt->input = NULL; 14248 14249 ctxt->spaceNr = 0; 14250 if (ctxt->spaceTab != NULL) { 14251 ctxt->spaceTab[0] = -1; 14252 ctxt->space = &ctxt->spaceTab[0]; 14253 } else { 14254 ctxt->space = NULL; 14255 } 14256 14257 14258 ctxt->nodeNr = 0; 14259 ctxt->node = NULL; 14260 14261 ctxt->nameNr = 0; 14262 ctxt->name = NULL; 14263 14264 DICT_FREE(ctxt->version); 14265 ctxt->version = NULL; 14266 DICT_FREE(ctxt->encoding); 14267 ctxt->encoding = NULL; 14268 DICT_FREE(ctxt->directory); 14269 ctxt->directory = NULL; 14270 DICT_FREE(ctxt->extSubURI); 14271 ctxt->extSubURI = NULL; 14272 DICT_FREE(ctxt->extSubSystem); 14273 ctxt->extSubSystem = NULL; 14274 if (ctxt->myDoc != NULL) 14275 xmlFreeDoc(ctxt->myDoc); 14276 ctxt->myDoc = NULL; 14277 14278 ctxt->standalone = -1; 14279 ctxt->hasExternalSubset = 0; 14280 ctxt->hasPErefs = 0; 14281 ctxt->html = 0; 14282 ctxt->external = 0; 14283 ctxt->instate = XML_PARSER_START; 14284 ctxt->token = 0; 14285 14286 ctxt->wellFormed = 1; 14287 ctxt->nsWellFormed = 1; 14288 ctxt->disableSAX = 0; 14289 ctxt->valid = 1; 14290 #if 0 14291 ctxt->vctxt.userData = ctxt; 14292 ctxt->vctxt.error = xmlParserValidityError; 14293 ctxt->vctxt.warning = xmlParserValidityWarning; 14294 #endif 14295 ctxt->record_info = 0; 14296 ctxt->nbChars = 0; 14297 ctxt->checkIndex = 0; 14298 ctxt->inSubset = 0; 14299 ctxt->errNo = XML_ERR_OK; 14300 ctxt->depth = 0; 14301 ctxt->charset = XML_CHAR_ENCODING_UTF8; 14302 ctxt->catalogs = NULL; 14303 ctxt->nbentities = 0; 14304 ctxt->sizeentities = 0; 14305 xmlInitNodeInfoSeq(&ctxt->node_seq); 14306 14307 if (ctxt->attsDefault != NULL) { 14308 xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree); 14309 ctxt->attsDefault = NULL; 14310 } 14311 if (ctxt->attsSpecial != NULL) { 14312 xmlHashFree(ctxt->attsSpecial, NULL); 14313 ctxt->attsSpecial = NULL; 14314 } 14315 14316 #ifdef LIBXML_CATALOG_ENABLED 14317 if (ctxt->catalogs != NULL) 14318 xmlCatalogFreeLocal(ctxt->catalogs); 14319 #endif 14320 if (ctxt->lastError.code != XML_ERR_OK) 14321 xmlResetError(&ctxt->lastError); 14322 } 14323 14336 int 14337 xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk, 14338 int size, const char *filename, const char *encoding) 14339 { 14340 xmlParserInputPtr inputStream; 14341 xmlParserInputBufferPtr buf; 14342 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; 14343 14344 if (ctxt == NULL) 14345 return(1); 14346 14347 if ((encoding == NULL) && (chunk != NULL) && (size >= 4)) 14348 enc = xmlDetectCharEncoding((const xmlChar *) chunk, size); 14349 14350 buf = xmlAllocParserInputBuffer(enc); 14351 if (buf == NULL) 14352 return(1); 14353 14354 if (ctxt == NULL) { 14355 xmlFreeParserInputBuffer(buf); 14356 return(1); 14357 } 14358 14359 xmlCtxtReset(ctxt); 14360 14361 if (ctxt->pushTab == NULL) { 14362 ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * 14363 sizeof(xmlChar *)); 14364 if (ctxt->pushTab == NULL) { 14365 xmlErrMemory(ctxt, NULL); 14366 xmlFreeParserInputBuffer(buf); 14367 return(1); 14368 } 14369 } 14370 14371 if (filename == NULL) { 14372 ctxt->directory = NULL; 14373 } else { 14374 ctxt->directory = xmlParserGetDirectory(filename); 14375 } 14376 14377 inputStream = xmlNewInputStream(ctxt); 14378 if (inputStream == NULL) { 14379 xmlFreeParserInputBuffer(buf); 14380 return(1); 14381 } 14382 14383 if (filename == NULL) 14384 inputStream->filename = NULL; 14385 else 14386 inputStream->filename = (char *) 14387 xmlCanonicPath((const xmlChar *) filename); 14388 inputStream->buf = buf; 14389 inputStream->base = inputStream->buf->buffer->content; 14390 inputStream->cur = inputStream->buf->buffer->content; 14391 inputStream->end = 14392 &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; 14393 14394 inputPush(ctxt, inputStream); 14395 14396 if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && 14397 (ctxt->input->buf != NULL)) { 14398 int base = ctxt->input->base - ctxt->input->buf->buffer->content; 14399 int cur = ctxt->input->cur - ctxt->input->base; 14400 14401 xmlParserInputBufferPush(ctxt->input->buf, size, chunk); 14402 14403 ctxt->input->base = ctxt->input->buf->buffer->content + base; 14404 ctxt->input->cur = ctxt->input->base + cur; 14405 ctxt->input->end = 14406 &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer-> 14407 use]; 14408 #ifdef DEBUG_PUSH 14409 xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size); 14410 #endif 14411 } 14412 14413 if (encoding != NULL) { 14414 xmlCharEncodingHandlerPtr hdlr; 14415 14416 if (ctxt->encoding != NULL) 14417 xmlFree((xmlChar *) ctxt->encoding); 14418 ctxt->encoding = xmlStrdup((const xmlChar *) encoding); 14419 14420 hdlr = xmlFindCharEncodingHandler(encoding); 14421 if (hdlr != NULL) { 14422 xmlSwitchToEncoding(ctxt, hdlr); 14423 } else { 14424 xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING, 14425 "Unsupported encoding %s\n", BAD_CAST encoding); 14426 } 14427 } else if (enc != XML_CHAR_ENCODING_NONE) { 14428 xmlSwitchEncoding(ctxt, enc); 14429 } 14430 14431 return(0); 14432 } 14433 14434 14446 static int 14447 xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding) 14448 { 14449 if (ctxt == NULL) 14450 return(-1); 14451 if (encoding != NULL) { 14452 if (ctxt->encoding != NULL) 14453 xmlFree((xmlChar *) ctxt->encoding); 14454 ctxt->encoding = xmlStrdup((const xmlChar *) encoding); 14455 } 14456 if (options & XML_PARSE_RECOVER) { 14457 ctxt->recovery = 1; 14458 options -= XML_PARSE_RECOVER; 14459 ctxt->options |= XML_PARSE_RECOVER; 14460 } else 14461 ctxt->recovery = 0; 14462 if (options & XML_PARSE_DTDLOAD) { 14463 ctxt->loadsubset = XML_DETECT_IDS; 14464 options -= XML_PARSE_DTDLOAD; 14465 ctxt->options |= XML_PARSE_DTDLOAD; 14466 } else 14467 ctxt->loadsubset = 0; 14468 if (options & XML_PARSE_DTDATTR) { 14469 ctxt->loadsubset |= XML_COMPLETE_ATTRS; 14470 options -= XML_PARSE_DTDATTR; 14471 ctxt->options |= XML_PARSE_DTDATTR; 14472 } 14473 if (options & XML_PARSE_NOENT) { 14474 ctxt->replaceEntities = 1; 14475 /* ctxt->loadsubset |= XML_DETECT_IDS; */ 14476 options -= XML_PARSE_NOENT; 14477 ctxt->options |= XML_PARSE_NOENT; 14478 } else 14479 ctxt->replaceEntities = 0; 14480 if (options & XML_PARSE_PEDANTIC) { 14481 ctxt->pedantic = 1; 14482 options -= XML_PARSE_PEDANTIC; 14483 ctxt->options |= XML_PARSE_PEDANTIC; 14484 } else 14485 ctxt->pedantic = 0; 14486 if (options & XML_PARSE_NOBLANKS) { 14487 ctxt->keepBlanks = 0; 14488 ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace; 14489 options -= XML_PARSE_NOBLANKS; 14490 ctxt->options |= XML_PARSE_NOBLANKS; 14491 } else 14492 ctxt->keepBlanks = 1; 14493 if (options & XML_PARSE_DTDVALID) { 14494 ctxt->validate = 1; 14495 if (options & XML_PARSE_NOWARNING) 14496 ctxt->vctxt.warning = NULL; 14497 if (options & XML_PARSE_NOERROR) 14498 ctxt->vctxt.error = NULL; 14499 options -= XML_PARSE_DTDVALID; 14500 ctxt->options |= XML_PARSE_DTDVALID; 14501 } else 14502 ctxt->validate = 0; 14503 if (options & XML_PARSE_NOWARNING) { 14504 ctxt->sax->warning = NULL; 14505 options -= XML_PARSE_NOWARNING; 14506 } 14507 if (options & XML_PARSE_NOERROR) { 14508 ctxt->sax->error = NULL; 14509 ctxt->sax->fatalError = NULL; 14510 options -= XML_PARSE_NOERROR; 14511 } 14512 #ifdef LIBXML_SAX1_ENABLED 14513 if (options & XML_PARSE_SAX1) { 14514 ctxt->sax->startElement = xmlSAX2StartElement; 14515 ctxt->sax->endElement = xmlSAX2EndElement; 14516 ctxt->sax->startElementNs = NULL; 14517 ctxt->sax->endElementNs = NULL; 14518 ctxt->sax->initialized = 1; 14519 options -= XML_PARSE_SAX1; 14520 ctxt->options |= XML_PARSE_SAX1; 14521 } 14522 #endif /* LIBXML_SAX1_ENABLED */ 14523 if (options & XML_PARSE_NODICT) { 14524 ctxt->dictNames = 0; 14525 options -= XML_PARSE_NODICT; 14526 ctxt->options |= XML_PARSE_NODICT; 14527 } else { 14528 ctxt->dictNames = 1; 14529 } 14530 if (options & XML_PARSE_NOCDATA) { 14531 ctxt->sax->cdataBlock = NULL; 14532 options -= XML_PARSE_NOCDATA; 14533 ctxt->options |= XML_PARSE_NOCDATA; 14534 } 14535 if (options & XML_PARSE_NSCLEAN) { 14536 ctxt->options |= XML_PARSE_NSCLEAN; 14537 options -= XML_PARSE_NSCLEAN; 14538 } 14539 if (options & XML_PARSE_NONET) { 14540 ctxt->options |= XML_PARSE_NONET; 14541 options -= XML_PARSE_NONET; 14542 } 14543 if (options & XML_PARSE_COMPACT) { 14544 ctxt->options |= XML_PARSE_COMPACT; 14545 options -= XML_PARSE_COMPACT; 14546 } 14547 if (options & XML_PARSE_OLD10) { 14548 ctxt->options |= XML_PARSE_OLD10; 14549 options -= XML_PARSE_OLD10; 14550 } 14551 if (options & XML_PARSE_NOBASEFIX) { 14552 ctxt->options |= XML_PARSE_NOBASEFIX; 14553 options -= XML_PARSE_NOBASEFIX; 14554 } 14555 if (options & XML_PARSE_HUGE) { 14556 ctxt->options |= XML_PARSE_HUGE; 14557 options -= XML_PARSE_HUGE; 14558 } 14559 if (options & XML_PARSE_OLDSAX) { 14560 ctxt->options |= XML_PARSE_OLDSAX; 14561 options -= XML_PARSE_OLDSAX; 14562 } 14563 ctxt->linenumbers = 1; 14564 return (options); 14565 } 14566 14577 int 14578 xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options) 14579 { 14580 return(xmlCtxtUseOptionsInternal(ctxt, options, NULL)); 14581 } 14582 14595 static xmlDocPtr 14596 xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding, 14597 int options, int reuse) 14598 { 14599 xmlDocPtr ret; 14600 14601 xmlCtxtUseOptionsInternal(ctxt, options, encoding); 14602 if (encoding != NULL) { 14603 xmlCharEncodingHandlerPtr hdlr; 14604 14605 hdlr = xmlFindCharEncodingHandler(encoding); 14606 if (hdlr != NULL) 14607 xmlSwitchToEncoding(ctxt, hdlr); 14608 } 14609 if ((URL != NULL) && (ctxt->input != NULL) && 14610 (ctxt->input->filename == NULL)) 14611 ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL); 14612 xmlParseDocument(ctxt); 14613 if ((ctxt->wellFormed) || ctxt->recovery) 14614 ret = ctxt->myDoc; 14615 else { 14616 ret = NULL; 14617 if (ctxt->myDoc != NULL) { 14618 xmlFreeDoc(ctxt->myDoc); 14619 } 14620 } 14621 ctxt->myDoc = NULL; 14622 if (!reuse) { 14623 xmlFreeParserCtxt(ctxt); 14624 } 14625 14626 return (ret); 14627 } 14628 14640 xmlDocPtr 14641 xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options) 14642 { 14643 xmlParserCtxtPtr ctxt; 14644 14645 if (cur == NULL) 14646 return (NULL); 14647 14648 ctxt = xmlCreateDocParserCtxt(cur); 14649 if (ctxt == NULL) 14650 return (NULL); 14651 return (xmlDoRead(ctxt, URL, encoding, options, 0)); 14652 } 14653 14664 xmlDocPtr 14665 xmlReadFile(const char *filename, const char *encoding, int options) 14666 { 14667 xmlParserCtxtPtr ctxt; 14668 14669 ctxt = xmlCreateURLParserCtxt(filename, options); 14670 if (ctxt == NULL) 14671 return (NULL); 14672 return (xmlDoRead(ctxt, NULL, encoding, options, 0)); 14673 } 14674 14687 xmlDocPtr 14688 xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options) 14689 { 14690 xmlParserCtxtPtr ctxt; 14691 14692 ctxt = xmlCreateMemoryParserCtxt(buffer, size); 14693 if (ctxt == NULL) 14694 return (NULL); 14695 return (xmlDoRead(ctxt, URL, encoding, options, 0)); 14696 } 14697 14711 xmlDocPtr 14712 xmlReadFd(int fd, const char *URL, const char *encoding, int options) 14713 { 14714 xmlParserCtxtPtr ctxt; 14715 xmlParserInputBufferPtr input; 14716 xmlParserInputPtr stream; 14717 14718 if (fd < 0) 14719 return (NULL); 14720 14721 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); 14722 if (input == NULL) 14723 return (NULL); 14724 input->closecallback = NULL; 14725 ctxt = xmlNewParserCtxt(); 14726 if (ctxt == NULL) { 14727 xmlFreeParserInputBuffer(input); 14728 return (NULL); 14729 } 14730 stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); 14731 if (stream == NULL) { 14732 xmlFreeParserInputBuffer(input); 14733 xmlFreeParserCtxt(ctxt); 14734 return (NULL); 14735 } 14736 inputPush(ctxt, stream); 14737 return (xmlDoRead(ctxt, URL, encoding, options, 0)); 14738 } 14739 14753 xmlDocPtr 14754 xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, 14755 void *ioctx, const char *URL, const char *encoding, int options) 14756 { 14757 xmlParserCtxtPtr ctxt; 14758 xmlParserInputBufferPtr input; 14759 xmlParserInputPtr stream; 14760 14761 if (ioread == NULL) 14762 return (NULL); 14763 14764 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, 14765 XML_CHAR_ENCODING_NONE); 14766 if (input == NULL) 14767 return (NULL); 14768 ctxt = xmlNewParserCtxt(); 14769 if (ctxt == NULL) { 14770 xmlFreeParserInputBuffer(input); 14771 return (NULL); 14772 } 14773 stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); 14774 if (stream == NULL) { 14775 xmlFreeParserInputBuffer(input); 14776 xmlFreeParserCtxt(ctxt); 14777 return (NULL); 14778 } 14779 inputPush(ctxt, stream); 14780 return (xmlDoRead(ctxt, URL, encoding, options, 0)); 14781 } 14782 14796 xmlDocPtr 14797 xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur, 14798 const char *URL, const char *encoding, int options) 14799 { 14800 xmlParserInputPtr stream; 14801 14802 if (cur == NULL) 14803 return (NULL); 14804 if (ctxt == NULL) 14805 return (NULL); 14806 14807 xmlCtxtReset(ctxt); 14808 14809 stream = xmlNewStringInputStream(ctxt, cur); 14810 if (stream == NULL) { 14811 return (NULL); 14812 } 14813 inputPush(ctxt, stream); 14814 return (xmlDoRead(ctxt, URL, encoding, options, 1)); 14815 } 14816 14829 xmlDocPtr 14830 xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename, 14831 const char *encoding, int options) 14832 { 14833 xmlParserInputPtr stream; 14834 14835 if (filename == NULL) 14836 return (NULL); 14837 if (ctxt == NULL) 14838 return (NULL); 14839 14840 xmlCtxtReset(ctxt); 14841 14842 stream = xmlLoadExternalEntity(filename, NULL, ctxt); 14843 if (stream == NULL) { 14844 return (NULL); 14845 } 14846 inputPush(ctxt, stream); 14847 return (xmlDoRead(ctxt, NULL, encoding, options, 1)); 14848 } 14849 14864 xmlDocPtr 14865 xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size, 14866 const char *URL, const char *encoding, int options) 14867 { 14868 xmlParserInputBufferPtr input; 14869 xmlParserInputPtr stream; 14870 14871 if (ctxt == NULL) 14872 return (NULL); 14873 if (buffer == NULL) 14874 return (NULL); 14875 14876 xmlCtxtReset(ctxt); 14877 14878 input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); 14879 if (input == NULL) { 14880 return(NULL); 14881 } 14882 14883 stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); 14884 if (stream == NULL) { 14885 xmlFreeParserInputBuffer(input); 14886 return(NULL); 14887 } 14888 14889 inputPush(ctxt, stream); 14890 return (xmlDoRead(ctxt, URL, encoding, options, 1)); 14891 } 14892 14908 xmlDocPtr 14909 xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd, 14910 const char *URL, const char *encoding, int options) 14911 { 14912 xmlParserInputBufferPtr input; 14913 xmlParserInputPtr stream; 14914 14915 if (fd < 0) 14916 return (NULL); 14917 if (ctxt == NULL) 14918 return (NULL); 14919 14920 xmlCtxtReset(ctxt); 14921 14922 14923 input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); 14924 if (input == NULL) 14925 return (NULL); 14926 input->closecallback = NULL; 14927 stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); 14928 if (stream == NULL) { 14929 xmlFreeParserInputBuffer(input); 14930 return (NULL); 14931 } 14932 inputPush(ctxt, stream); 14933 return (xmlDoRead(ctxt, URL, encoding, options, 1)); 14934 } 14935 14951 xmlDocPtr 14952 xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread, 14953 xmlInputCloseCallback ioclose, void *ioctx, 14954 const char *URL, 14955 const char *encoding, int options) 14956 { 14957 xmlParserInputBufferPtr input; 14958 xmlParserInputPtr stream; 14959 14960 if (ioread == NULL) 14961 return (NULL); 14962 if (ctxt == NULL) 14963 return (NULL); 14964 14965 xmlCtxtReset(ctxt); 14966 14967 input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, 14968 XML_CHAR_ENCODING_NONE); 14969 if (input == NULL) 14970 return (NULL); 14971 stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); 14972 if (stream == NULL) { 14973 xmlFreeParserInputBuffer(input); 14974 return (NULL); 14975 } 14976 inputPush(ctxt, stream); 14977 return (xmlDoRead(ctxt, URL, encoding, options, 1)); 14978 } 14979 14980 #define bottom_parser 14981 #include "elfgcchack.h" Generated on Fri May 25 2012 04:15:42 for ReactOS by
1.7.6.1
|