📄 parser.c
字号:
case XML_PARSER_ATTRIBUTE_VALUE: case XML_PARSER_PI: case XML_PARSER_SYSTEM_LITERAL: /* we just ignore it there */ return; case XML_PARSER_EPILOG: ctxt->errNo = XML_ERR_PEREF_IN_EPILOG; if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "PEReference in epilog!\n"); ctxt->wellFormed = 0; ctxt->disableSAX = 1; return; case XML_PARSER_ENTITY_VALUE: /* * NOTE: in the case of entity values, we don't do the * substitution here since we need the literal * entity value to be able to save the internal * subset of the document. * This will be handled by xmlDecodeEntities */ return; case XML_PARSER_DTD: /* * [WFC: Well-Formedness Constraint: PEs in Internal Subset] * In the internal DTD subset, parameter-entity references * can occur only where markup declarations can occur, not * within markup declarations. * In that case this is handled in xmlParseMarkupDecl */ if ((ctxt->external == 0) && (ctxt->inputNr == 1)) return; } NEXT; name = xmlParseName(ctxt); if (name == NULL) { ctxt->errNo = XML_ERR_PEREF_NO_NAME; if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "xmlHandlePEReference: no name\n"); ctxt->wellFormed = 0; ctxt->disableSAX = 1; } else { if (RAW == ';') { NEXT; if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL)) entity = ctxt->sax->getParameterEntity(ctxt->userData, name); if (entity == NULL) { /* * [ WFC: Entity Declared ] * In a document without any DTD, a document with only an * internal DTD subset which contains no parameter entity * references, or a document with "standalone='yes'", ... * ... The declaration of a parameter entity must precede * any reference to it... */ if ((ctxt->standalone == 1) || ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "PEReference: %%%s; not found\n", name); ctxt->wellFormed = 0; ctxt->disableSAX = 1; } else { /* * [ VC: Entity Declared ] * In a document with an external subset or external * parameter entities with "standalone='no'", ... * ... The declaration of a parameter entity must precede * any reference to it... */ if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) ctxt->sax->warning(ctxt->userData, "PEReference: %%%s; not found\n", name); ctxt->valid = 0; } } else { if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) || (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) { /* * TODO !!! handle the extra spaces added before and after * c.f. http://www.w3.org/TR/REC-xml#as-PE */ input = xmlNewEntityInputStream(ctxt, entity); xmlPushInput(ctxt, input); if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) && (RAW == '<') && (NXT(1) == '?') && (NXT(2) == 'x') && (NXT(3) == 'm') && (NXT(4) == 'l') && (IS_BLANK(NXT(5)))) { xmlParseTextDecl(ctxt); } if (ctxt->token == 0) ctxt->token = ' '; } else { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "xmlHandlePEReference: %s is not a parameter entity\n", name); ctxt->wellFormed = 0; ctxt->disableSAX = 1; } } } else { ctxt->errNo = XML_ERR_PEREF_SEMICOL_MISSING; if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "xmlHandlePEReference: expecting ';'\n"); ctxt->wellFormed = 0; ctxt->disableSAX = 1; } xmlFree(name); }}/* * Macro used to grow the current buffer. */#define growBuffer(buffer) { \ buffer##_size *= 2; \ buffer = (xmlChar *) \ xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \ if (buffer == NULL) { \ perror("realloc failed"); \ return(NULL); \ } \}/** * xmlDecodeEntities: * @ctxt: the parser context * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF * @len: the len to decode (in bytes !), -1 for no size limit * @end: an end marker xmlChar, 0 if none * @end2: an end marker xmlChar, 0 if none * @end3: an end marker xmlChar, 0 if none * * [67] Reference ::= EntityRef | CharRef * * [69] PEReference ::= '%' Name ';' * * Returns A newly allocated string with the substitution done. The caller * must deallocate it ! */xmlChar *xmlDecodeEntities(xmlParserCtxtPtr ctxt, int len, int what, xmlChar end, xmlChar end2, xmlChar end3) { xmlChar *buffer = NULL; int buffer_size = 0; int nbchars = 0; xmlChar *current = NULL; xmlEntityPtr ent; unsigned int max = (unsigned int) len; int c,l; if (ctxt->depth > 40) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "Detected entity reference loop\n"); ctxt->wellFormed = 0; ctxt->disableSAX = 1; ctxt->errNo = XML_ERR_ENTITY_LOOP; return(NULL); } /* * allocate a translation buffer. */ buffer_size = XML_PARSER_BIG_BUFFER_SIZE; buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar)); if (buffer == NULL) { perror("xmlDecodeEntities: malloc failed"); return(NULL); } /* * Ok loop until we reach one of the ending char or a size limit. */ c = CUR_CHAR(l); while ((nbchars < max) && (c != end) && (c != end2) && (c != end3)) { if (c == 0) break; if (((c == '&') && (ctxt->token != '&')) && (NXT(1) == '#')) { int val = xmlParseCharRef(ctxt); COPY_BUF(0,buffer,nbchars,val); NEXTL(l); } else if ((c == '&') && (ctxt->token != '&') && (what & XML_SUBSTITUTE_REF)) { ent = xmlParseEntityRef(ctxt); if ((ent != NULL) && (ctxt->replaceEntities != 0)) { current = ent->content; while (*current != 0) { buffer[nbchars++] = *current++; if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { growBuffer(buffer); } } } else if (ent != NULL) { const xmlChar *cur = ent->name; buffer[nbchars++] = '&'; if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { growBuffer(buffer); } while (*cur != 0) { buffer[nbchars++] = *cur++; } buffer[nbchars++] = ';'; } } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) { /* * a PEReference induce to switch the entity flow, * we break here to flush the current set of chars * parsed if any. We will be called back later. */ if (nbchars != 0) break; xmlParsePEReference(ctxt); /* * Pop-up of finished entities. */ while ((RAW == 0) && (ctxt->inputNr > 1)) xmlPopInput(ctxt); break; } else { COPY_BUF(l,buffer,nbchars,c); NEXTL(l); if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { growBuffer(buffer); } } c = CUR_CHAR(l); } buffer[nbchars++] = 0; return(buffer);}/** * xmlStringDecodeEntities: * @ctxt: the parser context * @str: the input string * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF * @end: an end marker xmlChar, 0 if none * @end2: an end marker xmlChar, 0 if none * @end3: an end marker xmlChar, 0 if none * * [67] Reference ::= EntityRef | CharRef * * [69] PEReference ::= '%' Name ';' * * Returns A newly allocated string with the substitution done. The caller * must deallocate it ! */xmlChar *xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what, xmlChar end, xmlChar end2, xmlChar end3) { xmlChar *buffer = NULL; int buffer_size = 0; xmlChar *current = NULL; xmlEntityPtr ent; int c,l; int nbchars = 0; if (ctxt->depth > 40) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "Detected entity reference loop\n"); ctxt->wellFormed = 0; ctxt->disableSAX = 1; ctxt->errNo = XML_ERR_ENTITY_LOOP; return(NULL); } /* * allocate a translation buffer. */ buffer_size = XML_PARSER_BIG_BUFFER_SIZE; buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar)); if (buffer == NULL) { perror("xmlDecodeEntities: malloc failed"); return(NULL); } /* * Ok loop until we reach one of the ending char or a size limit. */ c = CUR_SCHAR(str, l); while ((c != 0) && (c != end) && (c != end2) && (c != end3)) { if (c == 0) break; if ((c == '&') && (str[1] == '#')) { int val = xmlParseStringCharRef(ctxt, &str); if (val != 0) { COPY_BUF(0,buffer,nbchars,val); } } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) { ent = xmlParseStringEntityRef(ctxt, &str); if ((ent != NULL) && (ent->content != NULL)) { xmlChar *rep; ctxt->depth++; rep = xmlStringDecodeEntities(ctxt, ent->content, what, 0, 0, 0); ctxt->depth--; if (rep != NULL) { current = rep; while (*current != 0) { buffer[nbchars++] = *current++; if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { growBuffer(buffer); } } xmlFree(rep); } } else if (ent != NULL) { int i = xmlStrlen(ent->name); const xmlChar *cur = ent->name; buffer[nbchars++] = '&'; if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) { growBuffer(buffer); } for (;i > 0;i--) buffer[nbchars++] = *cur++; buffer[nbchars++] = ';'; } } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) { ent = xmlParseStringPEReference(ctxt, &str); if (ent != NULL) { xmlChar *rep; ctxt->depth++; rep = xmlStringDecodeEntities(ctxt, ent->content, what, 0, 0, 0); ctxt->depth--; if (rep != NULL) { current = rep; while (*current != 0) { buffer[nbchars++] = *current++; if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { growBuffer(buffer); } } xmlFree(rep); } } } else { COPY_BUF(l,buffer,nbchars,c); str += l; if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { growBuffer(buffer); } } c = CUR_SCHAR(str, l); } buffer[nbchars++] = 0; return(buffer);}/************************************************************************ * * * Commodity functions to handle encodings * * * ************************************************************************//* * xmlCheckLanguageID * @lang: pointer to the string value * * Checks that the value conforms to the LanguageID production: * * [33] LanguageID ::= Langcode ('-' Subcode)* * [34] Langcode ::= ISO639Code | IanaCode | UserCode * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z]) * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+ * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+ * [38] Subcode ::= ([a-z] | [A-Z])+ * * Returns 1 if correct 0 otherwise **/intxmlCheckLanguageID(const xmlChar *lang) { const xmlChar *cur = lang; if (cur == NULL) return(0); if (((cur[0] == 'i') && (cur[1] == '-')) || ((cur[0] == 'I') && (cur[1] == '-'))) { /* * IANA code */ cur += 2; while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || ((cur[0] >= 'a') && (cur[0] <= 'z'))) cur++; } else if (((cur[0] == 'x') && (cur[1] == '-')) || ((cur[0] == 'X') && (cur[1] == '-'))) { /* * User code */ cur += 2; while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || ((cur[0] >= 'a') && (cur[0] <= 'z'))) cur++; } else if (((cur[0] >= 'A') && (cur[0] <= 'Z')) || ((cur[0] >= 'a') && (cur[0] <= 'z'))) { /* * ISO639 */ cur++; if (((cur[0] >= 'A') && (cur[0] <= 'Z')) || ((cur[0] >= 'a') && (cur[0] <= 'z'))) cur++; else return(0); } else return(0); while (cur[0] != 0) { if (cur[0] != '-') return(0); cur++; if (((cur[0] >= 'A') && (cur[0] <= 'Z')) || ((cur[0] >= 'a') && (cur[0] <= 'z'))) cur++; else return(0); while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || ((cur[0] >= 'a') && (cur[0] <= 'z'))) cur++; } return(1);}/** * xmlSwitchEncoding: * @ctxt: the parser context * @enc: the encoding value (number) * * change the input functions when discovering the character encoding * of a given entity. */voidxmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc){ xmlCharEncodingHandlerPtr handler; handler = xmlGetCharEncodingHandler(enc); if (handler != NULL) { if (ctxt->input != NU
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -