Compare commits

...
9 Commits
Author SHA1 Message Date
James Clark 11067a403b +C:/home/work/expat/expat.pj 1998.05.11 16:35:12 revision 1.8 by jjc
checkpointed, new revision 1.8
+C:/home/work/expat/expat.pj 1998.05.11 17:16:37  revision 1.8 by jjc
C:/home/work/expat/xmltok/xmltok.c new-revision 1.24 was 1.23
+C:/home/work/expat/expat.pj 1998.05.14 11:41:52  revision 1.8 by jjc
C:/home/work/expat/expat.html new-revision 1.6 was 1.5
1998-05-14 04:42:18 +00:00
James Clark 0505f1cd36 Update date. 1998-05-14 04:41:52 +00:00
James Clark d504c1c894 Add support for US-ASCII encoding 1998-05-11 10:16:36 +00:00
James Clark 59023a9533 +C:/home/work/expat/expat.pj 1998.05.04 16:40:35 revision 1.7 by jjc
checkpointed, new revision 1.7
+C:/home/work/expat/expat.pj 1998.05.10 17:18:14  revision 1.7 by jjc
C:/home/work/expat/xmlparse/xmlparse.c new-revision 1.26 was 1.25
+C:/home/work/expat/expat.pj 1998.05.10 17:18:14  revision 1.7 by jjc
C:/home/work/expat/xmlparse/xmlparse.h new-revision 1.5 was 1.4
+C:/home/work/expat/expat.pj 1998.05.10 17:18:16  revision 1.7 by jjc
C:/home/work/expat/xmlwf/xmlwf.c new-revision 1.18 was 1.17
+C:/home/work/expat/expat.pj 1998.05.10 17:46:35  revision 1.7 by jjc
C:/home/work/expat/xmlparse/xmlparse.c new-revision 1.27 was 1.26
+C:/home/work/expat/expat.pj 1998.05.10 18:26:58  revision 1.7 by jjc
C:/home/work/expat/xmlparse/xmlparse.h new-revision 1.6 was 1.5
+C:/home/work/expat/expat.pj 1998.05.11 07:59:54  revision 1.7 by jjc
C:/home/work/expat/xmlparse/xmlparse.c new-revision 1.28 was 1.27
+C:/home/work/expat/expat.pj 1998.05.11 16:34:27  revision 1.7 by jjc
C:/home/work/expat/expat.html new-revision 1.5 was 1.4
1998-05-11 09:35:11 +00:00
James Clark d54b83991c Mention -x. Update version. 1998-05-11 09:34:26 +00:00
James Clark 0317338f10 When creating an external entity parser, don't set the processor if the encoding was unknown. 1998-05-11 00:59:52 +00:00
James Clark 5d0c27b76c Add some more comments on new interfaces 1998-05-10 11:26:58 +00:00
James Clark 1250e1d136 Fix dtdCopy bug 1998-05-10 10:46:34 +00:00
James Clark 4b8e8545c5 Support for parsing external entities 1998-05-10 10:18:15 +00:00
6 changed files with 608 additions and 12 deletions
+5 -2
View File
@@ -4,7 +4,7 @@
<TITLE>expat</TITLE>
<BODY>
<H1>expat - XML Parser Toolkit</H1>
<H3>Version 19980504</H3>
<H3>Version 19980514</H3>
<P>
Copyright (c) 1998 James Clark. Expat is subject to the <A
HREF="MPL-1_0.html">Mozilla Public License Version 1.0</A>. You may
@@ -33,7 +33,10 @@ file the corresponding <A
href="http://www.jclark.com/xml/canonxml.html">canonical XML</A> will
be written to <SAMP>dir/<VAR>f</VAR></SAMP>, where
<SAMP><VAR>f</VAR></SAMP> is the filename (without any path) of the
input file.</P>
input file.
A <CODE>-x</CODE> option will cause references to external general entities
to be processed.
</P>
<P></P>
<ADDRESS>
<A HREF="mailto:jjc@jclark.com">James Clark</A>
+5 -5
View File
@@ -3,13 +3,13 @@ $Revision: 1.17 $
EndOptions
$(projectdir)/MPL-1_0.html a 1.1
$(projectdir)/Makefile a 1.5
$(projectdir)/expat.html a 1.4
$(projectdir)/expat.html a 1.6
$(projectdir)/expat.mak a 1.12
$(projectdir)/gennmtab/gennmtab.c a 1.2
$(projectdir)/xmlparse/hashtable.c a 1.4
$(projectdir)/xmlparse/hashtable.h a 1.3
$(projectdir)/xmlparse/xmlparse.c a 1.25
$(projectdir)/xmlparse/xmlparse.h a 1.4
$(projectdir)/xmlparse/xmlparse.c a 1.28
$(projectdir)/xmlparse/xmlparse.h a 1.6
$(projectdir)/xmltok/asciitab.h a 1.4
$(projectdir)/xmltok/dllmain.c a 1.2
$(projectdir)/xmltok/iasciitab.h a 1.2
@@ -18,7 +18,7 @@ $(projectdir)/xmltok/utf8tab.h a 1.4
$(projectdir)/xmltok/xmldef.h a 1.3
$(projectdir)/xmltok/xmlrole.c a 1.8
$(projectdir)/xmltok/xmlrole.h a 1.4
$(projectdir)/xmltok/xmltok.c a 1.23
$(projectdir)/xmltok/xmltok.c a 1.24
$(projectdir)/xmltok/xmltok.h a 1.16
$(projectdir)/xmltok/xmltok_impl.c a 1.22
$(projectdir)/xmltok/xmltok_impl.h a 1.5
@@ -26,4 +26,4 @@ $(projectdir)/xmlwf/filemap.h a 1.2
$(projectdir)/xmlwf/readfilemap.c a 1.3
$(projectdir)/xmlwf/unixfilemap.c a 1.2
$(projectdir)/xmlwf/win32filemap.c a 1.3
$(projectdir)/xmlwf/xmlwf.c a 1.17
$(projectdir)/xmlwf/xmlwf.c a 1.18
+411 -1
View File
@@ -47,6 +47,7 @@ typedef struct {
const char *textPtr;
int textLen;
const char *systemId;
const char *base;
const char *publicId;
const char *notation;
char open;
@@ -94,6 +95,7 @@ typedef struct {
STRING_POOL pool;
int complete;
int standalone;
const char *base;
} DTD;
typedef enum XML_Error Processor(XML_Parser parser,
@@ -106,6 +108,8 @@ static Processor contentProcessor;
static Processor cdataSectionProcessor;
static Processor epilogProcessor;
static Processor errorProcessor;
static Processor externalEntityInitProcessor;
static Processor externalEntityContentProcessor;
static enum XML_Error
doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
@@ -128,8 +132,12 @@ storeEntityValue(XML_Parser parser, const char *start, const char *end);
static int
reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
static const char *getOpenEntityNames(XML_Parser parser);
static int setOpenEntityNames(XML_Parser parser, const char *openEntityNames);
static void normalizePublicId(char *s);
static int dtdInit(DTD *);
static void dtdDestroy(DTD *);
static int dtdCopy(DTD *newDtd, const DTD *oldDtd);
static void poolInit(STRING_POOL *);
static void poolClear(STRING_POOL *);
static void poolDestroy(STRING_POOL *);
@@ -138,6 +146,8 @@ static char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
static char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
const char *ptr, const char *end);
static int poolGrow(STRING_POOL *pool);
static const char *poolCopyString(STRING_POOL *pool, const char *s);
static const char *poolCopyStringN(STRING_POOL *pool, const char *s, int n);
#define poolStart(pool) ((pool)->start)
#define poolEnd(pool) ((pool)->ptr)
@@ -167,6 +177,7 @@ typedef struct {
XML_EndElementHandler endElementHandler;
XML_CharacterDataHandler characterDataHandler;
XML_ProcessingInstructionHandler processingInstructionHandler;
XML_ExternalEntityRefHandler externalEntityRefHandler;
const ENCODING *encoding;
INIT_ENCODING initEncoding;
PROLOG_STATE prologState;
@@ -197,6 +208,7 @@ typedef struct {
#define endElementHandler (((Parser *)parser)->endElementHandler)
#define characterDataHandler (((Parser *)parser)->characterDataHandler)
#define processingInstructionHandler (((Parser *)parser)->processingInstructionHandler)
#define externalEntityRefHandler (((Parser *)parser)->externalEntityRefHandler)
#define encoding (((Parser *)parser)->encoding)
#define initEncoding (((Parser *)parser)->initEncoding)
#define prologState (((Parser *)parser)->prologState)
@@ -240,6 +252,7 @@ XML_Parser XML_ParserCreate(const char *encodingName)
endElementHandler = 0;
characterDataHandler = 0;
processingInstructionHandler = 0;
externalEntityRefHandler = 0;
buffer = 0;
bufferPtr = 0;
bufferEnd = 0;
@@ -275,6 +288,40 @@ XML_Parser XML_ParserCreate(const char *encodingName)
return parser;
}
XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser,
const char *openEntityNames,
const char *encodingName)
{
XML_Parser parser = oldParser;
DTD *oldDtd = &dtd;
XML_StartElementHandler oldStartElementHandler = startElementHandler;
XML_EndElementHandler oldEndElementHandler = endElementHandler;
XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler;
XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler;
void *oldUserData = userData;
parser = XML_ParserCreate(encodingName);
if (!parser)
return 0;
startElementHandler = oldStartElementHandler;
endElementHandler = oldEndElementHandler;
characterDataHandler = oldCharacterDataHandler;
processingInstructionHandler = oldProcessingInstructionHandler;
externalEntityRefHandler = oldExternalEntityRefHandler;
userData = oldUserData;
if (!dtdCopy(&dtd, oldDtd) || !setOpenEntityNames(parser, openEntityNames)) {
XML_ParserFree(parser);
return 0;
}
if (errorCode != XML_ERROR_UNKNOWN_ENCODING)
processor = externalEntityInitProcessor;
return parser;
}
void XML_ParserFree(XML_Parser parser)
{
for (;;) {
@@ -305,6 +352,24 @@ void XML_SetUserData(XML_Parser parser, void *p)
userData = p;
}
void *XML_GetUserData(XML_Parser parser)
{
return userData;
}
int XML_SetBase(XML_Parser parser, const char *p)
{
if (p) {
p = poolCopyString(&dtd.pool, p);
if (!p)
return 0;
dtd.base = p;
}
else
dtd.base = 0;
return 1;
}
void XML_SetElementHandler(XML_Parser parser,
XML_StartElementHandler start,
XML_EndElementHandler end)
@@ -325,6 +390,12 @@ void XML_SetProcessingInstructionHandler(XML_Parser parser,
processingInstructionHandler = handler;
}
void XML_SetExternalEntityRefHandler(XML_Parser parser,
XML_ExternalEntityRefHandler handler)
{
externalEntityRefHandler = handler;
}
int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
{
bufferEndByteIndex += len;
@@ -478,6 +549,7 @@ const char *XML_ErrorString(int code)
"unknown encoding",
"encoding specified in XML declaration is incorrect",
"unclosed CDATA section",
"error in processing external entity reference"
};
if (code > 0 && code < sizeof(message)/sizeof(message[0]))
return message[code];
@@ -493,6 +565,80 @@ enum XML_Error contentProcessor(XML_Parser parser,
return doContent(parser, 0, encoding, start, end, endPtr);
}
static
enum XML_Error externalEntityInitProcessor(XML_Parser parser,
const char *start,
const char *end,
const char **endPtr)
{
const char *next;
int tok = XmlContentTok(encoding, start, end, &next);
switch (tok) {
case XML_TOK_BOM:
start = next;
tok = XmlContentTok(encoding, start, end, &next);
if (tok != XML_TOK_XML_DECL)
break;
/* fall through */
case XML_TOK_XML_DECL:
{
const char *encodingName = 0;
const ENCODING *newEncoding = 0;
const char *version;
int standalone;
if (!XmlParseXmlDecl(1,
encoding,
start,
next,
&errorPtr,
&version,
&encodingName,
&newEncoding,
&standalone))
return XML_ERROR_SYNTAX;
if (newEncoding) {
if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
errorPtr = encodingName;
return XML_ERROR_INCORRECT_ENCODING;
}
encoding = newEncoding;
}
else if (encodingName) {
errorPtr = encodingName;
return XML_ERROR_UNKNOWN_ENCODING;
}
start = next;
break;
}
case XML_TOK_PARTIAL:
if (endPtr) {
*endPtr = start;
return XML_ERROR_NONE;
}
errorPtr = start;
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
if (endPtr) {
*endPtr = start;
return XML_ERROR_NONE;
}
errorPtr = start;
return XML_ERROR_PARTIAL_CHAR;
}
processor = externalEntityContentProcessor;
tagLevel = 1;
return doContent(parser, 1, encoding, start, end, endPtr);
}
static
enum XML_Error externalEntityContentProcessor(XML_Parser parser,
const char *start,
const char *end,
const char **endPtr)
{
return doContent(parser, 1, encoding, start, end, endPtr);
}
static enum XML_Error
doContent(XML_Parser parser,
int startTagLevel,
@@ -507,6 +653,24 @@ doContent(XML_Parser parser,
int tok = XmlContentTok(enc, s, end, &next);
switch (tok) {
case XML_TOK_TRAILING_CR:
if (nextPtr) {
*nextPtr = s;
return XML_ERROR_NONE;
}
if (characterDataHandler) {
char c = '\n';
characterDataHandler(userData, &c, 1);
}
if (startTagLevel == 0) {
errorPtr = s;
return XML_ERROR_NO_ELEMENTS;
}
if (tagLevel != startTagLevel) {
errorPtr = s;
return XML_ERROR_ASYNC_ENTITY;
}
return XML_ERROR_NONE;
case XML_TOK_NONE:
if (nextPtr) {
*nextPtr = s;
@@ -584,6 +748,18 @@ doContent(XML_Parser parser,
return result;
}
}
else if (externalEntityRefHandler) {
const char *openEntityNames;
entity->open = 1;
openEntityNames = getOpenEntityNames(parser);
entity->open = 0;
if (!openEntityNames)
return XML_ERROR_NO_MEMORY;
if (!externalEntityRefHandler(parser, openEntityNames, dtd.base, entity->systemId, entity->publicId)) {
errorPtr = s;
return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
}
}
}
break;
}
@@ -1030,8 +1206,22 @@ prologProcessor(XML_Parser parser,
case XML_ROLE_DOCTYPE_SYSTEM_ID:
hadExternalDoctype = 1;
break;
case XML_ROLE_DOCTYPE_PUBLIC_ID:
case XML_ROLE_ENTITY_PUBLIC_ID:
if (!XmlIsPublicId(encoding, s, next, &errorPtr))
return XML_ERROR_SYNTAX;
if (declEntity) {
char *tem = poolStoreString(&dtd.pool,
encoding,
s + encoding->minBytesPerChar,
next - encoding->minBytesPerChar);
if (!tem)
return XML_ERROR_NO_MEMORY;
normalizePublicId(tem);
declEntity->publicId = tem;
poolFinish(&dtd.pool);
}
break;
case XML_ROLE_DOCTYPE_PUBLIC_ID:
case XML_ROLE_NOTATION_PUBLIC_ID:
if (!XmlIsPublicId(encoding, s, next, &errorPtr))
return XML_ERROR_SYNTAX;
@@ -1102,6 +1292,7 @@ prologProcessor(XML_Parser parser,
next - encoding->minBytesPerChar);
if (!declEntity->systemId)
return XML_ERROR_NO_MEMORY;
declEntity->base = dtd.base;
poolFinish(&dtd.pool);
}
break;
@@ -1537,6 +1728,80 @@ getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const
return id;
}
static
const char *getOpenEntityNames(XML_Parser parser)
{
HASH_TABLE_ITER iter;
hashTableIterInit(&iter, &(dtd.generalEntities));
for (;;) {
const char *s;
ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
if (!e)
break;
if (!e->open)
continue;
if (poolLength(&tempPool) > 0 && !poolAppendByte(&tempPool, ' '))
return 0;
for (s = e->name; *s; s++)
if (!poolAppendByte(&tempPool, *s))
return 0;
}
if (!poolAppendByte(&tempPool, '\0'))
return 0;
return tempPool.start;
}
static
int setOpenEntityNames(XML_Parser parser, const char *openEntityNames)
{
const char *s = openEntityNames;
while (*openEntityNames != '\0') {
if (*s == ' ' || *s == '\0') {
ENTITY *e;
if (!poolAppendByte(&tempPool, '\0'))
return 0;
e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0);
if (e)
e->open = 1;
if (*s == ' ')
s++;
openEntityNames = s;
poolDiscard(&tempPool);
}
else {
if (!poolAppendByte(&tempPool, *s))
return 0;
s++;
}
}
return 1;
}
static
void normalizePublicId(char *publicId)
{
char *p = publicId;
char *s;
for (s = publicId; *s; s++) {
switch (*s) {
case ' ':
case '\r':
case '\n':
if (p != publicId && p[-1] != ' ')
*p++ = ' ';
break;
default:
*p++ = *s;
}
}
if (p != publicId && p[-1] == ' ')
--p;
*p = '\0';
}
static int dtdInit(DTD *p)
{
static const char *names[] = { "lt", "amp", "gt", "quot", "apos" };
@@ -1556,6 +1821,7 @@ static int dtdInit(DTD *p)
hashTableInit(&(p->elementTypes));
hashTableInit(&(p->attributeIds));
p->complete = 1;
p->base = 0;
return 1;
}
@@ -1575,6 +1841,126 @@ static void dtdDestroy(DTD *p)
poolDestroy(&(p->pool));
}
/* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise.
The new DTD has already been initialized. */
static int dtdCopy(DTD *newDtd, const DTD *oldDtd)
{
HASH_TABLE_ITER iter;
if (oldDtd->base) {
const char *tem = poolCopyString(&(newDtd->pool), oldDtd->base);
if (!tem)
return 0;
newDtd->base = tem;
}
hashTableIterInit(&iter, &(oldDtd->attributeIds));
/* Copy the attribute id table. */
for (;;) {
ATTRIBUTE_ID *newA;
const char *name;
const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
if (!oldA)
break;
/* Remember to allocate the scratch byte before the name. */
if (!poolAppendByte(&(newDtd->pool), 0))
return 0;
name = poolCopyString(&(newDtd->pool), oldA->name);
if (!name)
return 0;
++name;
newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
if (!newA)
return 0;
newA->maybeTokenized = oldA->maybeTokenized;
}
/* Copy the element type table. */
hashTableIterInit(&iter, &(oldDtd->elementTypes));
for (;;) {
int i;
ELEMENT_TYPE *newE;
const char *name;
const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
if (!oldE)
break;
name = poolCopyString(&(newDtd->pool), oldE->name);
if (!name)
return 0;
newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
if (!newE)
return 0;
newE->defaultAtts = (DEFAULT_ATTRIBUTE *)malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
if (!newE->defaultAtts)
return 0;
newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
for (i = 0; i < newE->nDefaultAtts; i++) {
newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
if (!newE->defaultAtts[i].value)
return 0;
}
}
/* Copy the entity table. */
hashTableIterInit(&iter, &(oldDtd->generalEntities));
for (;;) {
ENTITY *newE;
const char *name;
const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
if (!oldE)
break;
if (oldE->magic)
continue;
name = poolCopyString(&(newDtd->pool), oldE->name);
if (!name)
return 0;
newE = (ENTITY *)lookup(&(newDtd->generalEntities), name, sizeof(ENTITY));
if (!newE)
return 0;
if (oldE->systemId) {
const char *tem = poolCopyString(&(newDtd->pool), oldE->systemId);
if (!tem)
return 0;
newE->systemId = tem;
if (oldE->base) {
if (oldE->base == oldDtd->base)
newE->base = newDtd->base;
tem = poolCopyString(&(newDtd->pool), oldE->base);
if (!tem)
return 0;
newE->base = tem;
}
}
else {
const char *tem = poolCopyStringN(&(newDtd->pool), oldE->textPtr, oldE->textLen);
if (!tem)
return 0;
newE->textPtr = tem;
newE->textLen = oldE->textLen;
}
if (oldE->notation) {
const char *tem = poolCopyString(&(newDtd->pool), oldE->notation);
if (!tem)
return 0;
newE->notation = tem;
}
}
newDtd->complete = oldDtd->complete;
newDtd->standalone = oldDtd->standalone;
return 1;
}
static
void poolInit(STRING_POOL *pool)
{
@@ -1643,6 +2029,30 @@ char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
return pool->start;
}
static const char *poolCopyString(STRING_POOL *pool, const char *s)
{
do {
if (!poolAppendByte(pool, *s))
return 0;
} while (*s++);
s = pool->start;
poolFinish(pool);
return s;
}
static const char *poolCopyStringN(STRING_POOL *pool, const char *s, int n)
{
if (!pool->ptr && !poolGrow(pool))
return 0;
for (; n > 0; --n, s++) {
if (!poolAppendByte(pool, *s))
return 0;
}
s = pool->start;
poolFinish(pool);
return s;
}
static
char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+67 -3
View File
@@ -31,8 +31,8 @@ extern "C" {
typedef void *XML_Parser;
/* Constructs a new parser; encoding should be the name of the charset from
the Content-Type header if the Content-Type is text/xml, or null otherwise. */
/* Constructs a new parser; encoding is the externally specified encoding,
or null if there is no externally specified encoding. */
XML_Parser XMLPARSEAPI
XML_ParserCreate(const char *encoding);
@@ -58,6 +58,37 @@ typedef void (*XML_ProcessingInstructionHandler)(void *userData,
const char *target,
const char *data);
/* Reports a reference to an external parsed general entity.
The referenced entity is not automatically parsed.
The application can parse it immediately or later using
XML_ExternalEntityParserCreate.
The parser argument is the parser parsing the entity containing the reference;
it can be passed as the parser argument to XML_ExternalEntityParserCreate.
The systemId argument is the system identifier as specified in the entity declaration;
it will not be null.
The base argument is the system identifier that should be used as the base for
resolving systemId if systemId was relative; this is set by XML_SetBase;
it may be null.
The publicId argument is the public identifier as specified in the entity declaration,
or null if none was specified; the whitespace in the public identifier
will have been normalized as required by the XML spec.
The openEntityNames argument is a space-separated list of the names of the entities
that are open for the parse of this entity (including the name of the referenced
entity); this can be passed as the openEntityNames argument to
XML_ExternalEntityParserCreate; openEntityNames is valid only until the handler
returns, so if the referenced entity is to be parsed later, it must be copied.
The handler should return 0 if processing should not continue because of
a fatal error in the handling of the external entity.
In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING
error.
Note that unlike other handlers the first argument is the parser, not userData. */
typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser,
const char *openEntityNames,
const char *base,
const char *systemId,
const char *publicId);
void XMLPARSEAPI
XML_SetElementHandler(XML_Parser parser,
XML_StartElementHandler start,
@@ -71,10 +102,27 @@ void XMLPARSEAPI
XML_SetProcessingInstructionHandler(XML_Parser parser,
XML_ProcessingInstructionHandler handler);
void XMLPARSEAPI
XML_SetExternalEntityRefHandler(XML_Parser parser,
XML_ExternalEntityRefHandler handler);
/* This value is passed as the userData argument to callbacks. */
void XMLPARSEAPI
XML_SetUserData(XML_Parser parser, void *userData);
/* Returns the last value set by XML_SetUserData or null. */
void XMLPARSEAPI *
XML_GetUserData(XML_Parser parser);
/* Sets the base to be used for resolving relative URIs in system identifiers in
declarations. Resolving relative identifiers is left to the application:
this value will be passed through as the base argumentto the ExternalEntityRefHandler.
The base argument will be copied. Returns zero if out of memory, non-zero otherwise. */
int XMLPARSEAPI
XML_SetBase(XML_Parser parser, const char *base);
/* Parses some input. Returns 0 if a fatal error is detected.
The last call to XML_Parse must have isFinal true;
len may be zero for this call (or any other). */
@@ -87,6 +135,21 @@ XML_GetBuffer(XML_Parser parser, int len);
int XMLPARSEAPI
XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
/* Creates an XML_Parser object that can parse an external general entity;
openEntityNames is a space-separated list of the names of the entities that are open
for the parse of this entity (including the name of this one);
encoding is the externally specified encoding,
or null if there is no externally specified encoding.
This can be called at any point after the first call to an ExternalEntityRefHandler
so longer as the parser has not yet been freed.
The new parser is completely independent and may safely be used in a separate thread.
The handlers and userData are initialized from the parser argument.
Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */
XML_Parser XMLPARSEAPI
XML_ExternalEntityParserCreate(XML_Parser parser,
const char *openEntityNames,
const char *encoding);
/* If XML_Parser or XML_ParseEnd have returned 0, then XML_GetError*
returns information about the error. */
@@ -111,7 +174,8 @@ enum XML_Error {
XML_ERROR_MISPLACED_XML_PI,
XML_ERROR_UNKNOWN_ENCODING,
XML_ERROR_INCORRECT_ENCODING,
XML_ERROR_UNCLOSED_CDATA_SECTION
XML_ERROR_UNCLOSED_CDATA_SECTION,
XML_ERROR_EXTERNAL_ENTITY_HANDLING
};
int XMLPARSEAPI XML_GetErrorCode(XML_Parser parser);
+35
View File
@@ -240,6 +240,35 @@ static const struct normal_encoding latin1_encoding = {
#define latin1tab (latin1_encoding.type)
static
int ascii_encode(const ENCODING *enc, int c, char *buf)
{
if (c < 0)
return 0;
if (c <= 0x7F) {
buf[0] = (char)c;
return 1;
}
return 0;
}
static
void ascii_toUtf8(const ENCODING *enc,
const char **fromP, const char *fromLim,
char **toP, const char *toLim)
{
while (*fromP != fromLim && *toP != toLim)
*(*toP)++ = *(*fromP)++;
}
static const struct normal_encoding ascii_encoding = {
{ VTABLE1, ascii_encode, { ascii_toUtf8 }, 1 },
{
#include "asciitab.h"
/* BT_NONXML == 0 */
}
};
#undef PREFIX
static int unicode_byte_type(char hi, char lo)
@@ -514,6 +543,10 @@ int XmlInitEncoding(INIT_ENCODING *p, const ENCODING **encPtr, const char *name)
*encPtr = &utf8_encoding.enc;
return 1;
}
if (streqci(name, "US-ASCII")) {
*encPtr = &ascii_encoding.enc;
return 1;
}
if (!streqci(name, "UTF-16"))
return 0;
}
@@ -653,6 +686,8 @@ const ENCODING *findEncoding(const ENCODING *enc, const char *ptr, const char *e
return &utf8_encoding.enc;
if (streqci(buf, "ISO-8859-1"))
return &latin1_encoding.enc;
if (streqci(buf, "US-ASCII"))
return &ascii_encoding.enc;
if (streqci(buf, "UTF-16")) {
static const unsigned short n = 1;
if (enc->minBytesPerChar == 2)
+85 -1
View File
@@ -164,6 +164,60 @@ void processFile(const void *data, size_t size, const char *filename, void *args
*retPtr = 1;
}
static
int isAsciiLetter(char c)
{
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
}
static
const char *resolveSystemId(const char *base, const char *systemId, char **toFree)
{
char *s;
*toFree = 0;
if (!base
|| *systemId == '/'
#ifdef WIN32
|| *systemId == '\\'
|| (isAsciiLetter(systemId[0]) && systemId[1] == ':')
#endif
)
return systemId;
*toFree = (char *)malloc(strlen(base) + strlen(systemId) + 2);
if (!*toFree)
return systemId;
strcpy(*toFree, base);
s = *toFree;
if (strrchr(s, '/'))
s = strrchr(s, '/') + 1;
#ifdef WIN32
if (strrchr(s, '\\'))
s = strrchr(s, '\\') + 1;
#endif
strcpy(s, systemId);
return *toFree;
}
static
int externalEntityRefFilemap(XML_Parser parser,
const char *openEntityNames,
const char *base,
const char *systemId,
const char *publicId)
{
int result;
char *s;
XML_Parser entParser = XML_ExternalEntityParserCreate(parser, openEntityNames, 0);
PROCESS_ARGS args;
args.retPtr = &result;
args.parser = entParser;
if (!filemap(resolveSystemId(base, systemId, &s), processFile, &args))
result = 0;
free(s);
XML_ParserFree(entParser);
return result;
}
static
int processStream(const char *filename, XML_Parser parser)
{
@@ -199,10 +253,25 @@ int processStream(const char *filename, XML_Parser parser)
return 1;
}
static
int externalEntityRefStream(XML_Parser parser,
const char *openEntityNames,
const char *base,
const char *systemId,
const char *publicId)
{
char *s;
XML_Parser entParser = XML_ExternalEntityParserCreate(parser, openEntityNames, 0);
int ret = processStream(resolveSystemId(base, systemId, &s), entParser);
free(s);
XML_ParserFree(entParser);
return ret;
}
static
void usage(const char *prog)
{
fprintf(stderr, "usage: %s [-r] [-d output-dir] [-e encoding] file ...\n", prog);
fprintf(stderr, "usage: %s [-r] [-x] [-d output-dir] [-e encoding] file ...\n", prog);
exit(1);
}
@@ -212,6 +281,7 @@ int main(int argc, char **argv)
const char *outputDir = 0;
const char *encoding = 0;
int useFilemap = 1;
int processExternalEntities = 0;
#ifdef _MSC_VER
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
@@ -229,6 +299,10 @@ int main(int argc, char **argv)
useFilemap = 0;
j++;
}
if (argv[i][j] == 'x') {
processExternalEntities = 1;
j++;
}
if (argv[i][j] == 'd') {
if (argv[i][j + 1] == '\0') {
if (++i == argc)
@@ -283,6 +357,16 @@ int main(int argc, char **argv)
XML_SetCharacterDataHandler(parser, characterData);
XML_SetProcessingInstructionHandler(parser, processingInstruction);
}
if (processExternalEntities) {
if (!XML_SetBase(parser, argv[i])) {
fprintf(stderr, "%s: out of memory", argv[0]);
exit(1);
}
XML_SetExternalEntityRefHandler(parser,
useFilemap
? externalEntityRefFilemap
: externalEntityRefStream);
}
if (useFilemap) {
PROCESS_ARGS args;
args.retPtr = &result;