mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-05 22:20:59 +00:00
Updates to handle entity resolution for libxml2-2.13.?
This commit is contained in:
parent
da9dc23a89
commit
b5e0ef1514
3 changed files with 86 additions and 107 deletions
|
@ -195,10 +195,11 @@ GS_EXPORT_CLASS
|
||||||
GS_EXPORT_CLASS
|
GS_EXPORT_CLASS
|
||||||
@interface GSXMLParser : NSObject
|
@interface GSXMLParser : NSObject
|
||||||
{
|
{
|
||||||
id src; /* source for parsing */
|
id src; /* source for parsing */
|
||||||
void *lib; /* parser context */
|
void *lib; /* parser context */
|
||||||
GSSAXHandler *saxHandler; /* handler for parsing */
|
GSSAXHandler *saxHandler; /* handler for parsing */
|
||||||
NSMutableString *messages; /* append messages here */
|
NSMutableString *messages; /* append messages here */
|
||||||
|
BOOL resolve;
|
||||||
}
|
}
|
||||||
+ (NSString*) loadEntity: (NSString*)publicId at: (NSString*)location;
|
+ (NSString*) loadEntity: (NSString*)publicId at: (NSString*)location;
|
||||||
+ (GSXMLParser*) parser;
|
+ (GSXMLParser*) parser;
|
||||||
|
|
|
@ -205,12 +205,10 @@ static xmlParserInputPtr
|
||||||
loadEntityFunction(const unsigned char *url, const unsigned char *eid,
|
loadEntityFunction(const unsigned char *url, const unsigned char *eid,
|
||||||
void *ctx);
|
void *ctx);
|
||||||
static xmlParserInputPtr
|
static xmlParserInputPtr
|
||||||
resolveEntityFunction(void *ctx, const unsigned char *eid,
|
resolveEntityFunction(void *ctx,
|
||||||
const unsigned char *url);
|
const unsigned char *eid, const unsigned char *url);
|
||||||
static xmlEntityPtr
|
static xmlEntityPtr
|
||||||
getEntityIgnoreExternal(void *ctx, const xmlChar *name);
|
getEntityDefault(void *ctx, const xmlChar *name);
|
||||||
static xmlEntityPtr
|
|
||||||
getEntityResolveExternal(void *ctx, const xmlChar *name);
|
|
||||||
|
|
||||||
@interface GSXPathObject(Private)
|
@interface GSXPathObject(Private)
|
||||||
+ (id) _newWithNativePointer: (xmlXPathObject *)lib
|
+ (id) _newWithNativePointer: (xmlXPathObject *)lib
|
||||||
|
@ -234,6 +232,7 @@ getEntityResolveExternal(void *ctx, const xmlChar *name);
|
||||||
- (BOOL) _initLibXML;
|
- (BOOL) _initLibXML;
|
||||||
- (NSMutableString*) _messages;
|
- (NSMutableString*) _messages;
|
||||||
- (void) _parseChunk: (NSData*)data;
|
- (void) _parseChunk: (NSData*)data;
|
||||||
|
- (BOOL) _resolves;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface GSSAXHandler (Private)
|
@interface GSSAXHandler (Private)
|
||||||
|
@ -2402,28 +2401,9 @@ static NSString *endMarker = @"At end of incremental parse";
|
||||||
|
|
||||||
- (BOOL) resolveEntities: (BOOL)yesno
|
- (BOOL) resolveEntities: (BOOL)yesno
|
||||||
{
|
{
|
||||||
BOOL old;
|
BOOL old = resolve;;
|
||||||
|
|
||||||
if (yesno) yesno = YES;
|
resolve = yesno;
|
||||||
if ((((xmlParserCtxtPtr)lib)->sax)->getEntity
|
|
||||||
== (void*)getEntityIgnoreExternal)
|
|
||||||
{
|
|
||||||
old = NO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
old = YES;
|
|
||||||
}
|
|
||||||
if (YES == yesno)
|
|
||||||
{
|
|
||||||
(((xmlParserCtxtPtr)lib)->sax)->getEntity
|
|
||||||
= (void*)getEntityResolveExternal;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
(((xmlParserCtxtPtr)lib)->sax)->getEntity
|
|
||||||
= (void*)getEntityIgnoreExternal;
|
|
||||||
}
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2434,14 +2414,11 @@ static NSString *endMarker = @"At end of incremental parse";
|
||||||
*/
|
*/
|
||||||
- (BOOL) substituteEntities: (BOOL)yesno
|
- (BOOL) substituteEntities: (BOOL)yesno
|
||||||
{
|
{
|
||||||
BOOL old;
|
xmlParserCtxtPtr context = (xmlParserCtxtPtr)lib;
|
||||||
|
BOOL old;
|
||||||
|
|
||||||
if (yesno) yesno = YES;
|
old = context->replaceEntities ? YES : NO;
|
||||||
old = (((xmlParserCtxtPtr)lib)->replaceEntities) ? YES : NO;
|
context->replaceEntities = (yesno ? 1 : 0);
|
||||||
if (old != yesno)
|
|
||||||
{
|
|
||||||
((xmlParserCtxtPtr)lib)->replaceEntities = (yesno ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
@ -2494,16 +2471,15 @@ static NSString *endMarker = @"At end of incremental parse";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/* Put saxHandler address in _private member, so we can retrieve
|
||||||
* Put saxHandler address in _private member, so we can retrieve
|
|
||||||
* the GSSAXHandler to use in our SAX C Functions.
|
* the GSSAXHandler to use in our SAX C Functions.
|
||||||
*/
|
*/
|
||||||
((xmlParserCtxtPtr)lib)->_private = saxHandler;
|
((xmlParserCtxtPtr)lib)->_private = saxHandler;
|
||||||
|
|
||||||
/*
|
/* Set the entity loading function for this parser to be our one.
|
||||||
* Set the entity loading function for this parser to be our one.
|
|
||||||
*/
|
*/
|
||||||
((xmlParserCtxtPtr)lib)->sax->resolveEntity = resolveEntityFunction;
|
((xmlParserCtxtPtr)lib)->sax->resolveEntity = resolveEntityFunction;
|
||||||
|
[self resolveEntities: NO]; // Off by default
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
@ -2523,6 +2499,10 @@ static NSString *endMarker = @"At end of incremental parse";
|
||||||
xmlParseChunk(lib, [data bytes], [data length], data == nil);
|
xmlParseChunk(lib, [data bytes], [data length], data == nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) _resolves
|
||||||
|
{
|
||||||
|
return resolve;
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2623,11 +2603,12 @@ static NSString *endMarker = @"At end of incremental parse";
|
||||||
#define HANDLER ((GSSAXHandler*)(((xmlParserCtxtPtr)ctx)->_private))
|
#define HANDLER ((GSSAXHandler*)(((xmlParserCtxtPtr)ctx)->_private))
|
||||||
|
|
||||||
static xmlEntityPtr
|
static xmlEntityPtr
|
||||||
getEntityDefault(void *ctx, const xmlChar *name, BOOL resolve)
|
getEntityDefault(void *ctx, const xmlChar *name)
|
||||||
{
|
{
|
||||||
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
|
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
|
||||||
xmlEntityPtr ret = NULL;
|
xmlEntityPtr ret = NULL;
|
||||||
|
|
||||||
|
// NSLog(@"getEntityDefault called for '%s'", name);
|
||||||
if (ctx != 0)
|
if (ctx != 0)
|
||||||
{
|
{
|
||||||
if (0 == ctxt->inSubset)
|
if (0 == ctxt->inSubset)
|
||||||
|
@ -2666,70 +2647,55 @@ getEntityDefault(void *ctx, const xmlChar *name, BOOL resolve)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = xmlGetDocEntity(ctxt->myDoc, name);
|
ret = xmlGetDocEntity(ctxt->myDoc, name);
|
||||||
}
|
}
|
||||||
|
#if LIBXML_VERSION < 21300
|
||||||
|
/* In older versions we may need to parse the entity content.
|
||||||
|
*/
|
||||||
if ((ret != NULL)
|
if ((ret != NULL)
|
||||||
&& ((ctxt->validate) || (ctxt->replaceEntities))
|
&& ((ctxt->validate) || (ctxt->replaceEntities))
|
||||||
&& (ret->children == NULL)
|
&& (ret->children == NULL)
|
||||||
&& (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))
|
&& (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))
|
||||||
{
|
{
|
||||||
if (YES == resolve)
|
xmlNodePtr children;
|
||||||
{
|
int val;
|
||||||
xmlNodePtr children;
|
|
||||||
int val;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for validation purposes we really need to fetch and
|
* for validation purposes we really need to fetch and
|
||||||
* parse the external entity
|
* parse the external entity
|
||||||
*/
|
*/
|
||||||
val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
|
val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
|
||||||
ret->ExternalID, &children);
|
ret->ExternalID, &children);
|
||||||
if (val == 0)
|
if (val == 0)
|
||||||
{
|
{
|
||||||
xmlAddChildList((xmlNodePtr) ret, children);
|
xmlAddChildList((xmlNodePtr) ret, children);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
((((xmlParserCtxtPtr)ctxt)->sax)->fatalError)(ctxt,
|
((((xmlParserCtxtPtr)ctxt)->sax)->fatalError)(ctxt,
|
||||||
"Failure to process entity %s\n", name);
|
"Failure to process entity %s\n", name);
|
||||||
xmlStopParser(ctxt);
|
xmlStopParser(ctxt);
|
||||||
ctxt->validate = 0;
|
ctxt->validate = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ret->owner = 1;
|
ret->owner = 1;
|
||||||
#if LIBXML_VERSION < 21100
|
#if LIBXML_VERSION < 21100
|
||||||
if (ret->checked == 0)
|
/* Set old flag ... not prent/needed in cewlater versions.
|
||||||
{
|
*/
|
||||||
ret->checked = 1;
|
if (ret->checked == 0)
|
||||||
}
|
{
|
||||||
#endif
|
ret->checked = 1;
|
||||||
}
|
}
|
||||||
}
|
#endif /* LIBXML_VERSION < 21100 */
|
||||||
|
}
|
||||||
|
#endif /* LIBXML_VERSION < 21300 */
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static xmlEntityPtr
|
|
||||||
getEntityIgnoreExternal(void *ctx, const xmlChar *name)
|
|
||||||
{
|
|
||||||
return getEntityDefault(ctx, name, NO);
|
|
||||||
}
|
|
||||||
|
|
||||||
static xmlEntityPtr
|
|
||||||
getEntityResolveExternal(void *ctx, const xmlChar *name)
|
|
||||||
{
|
|
||||||
return getEntityDefault(ctx, name, YES);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* WARNING ... as far as I can tell libxml2 never uses the resolveEntity
|
/* WARNING ... as far as I can tell libxml2 never uses the resolveEntity
|
||||||
* callback, so this function is never called via that route.
|
* callback, so this function is never called via that route.
|
||||||
* We therefore also set this as the global default entity loading
|
* We therefore also set this as the global default entity loading
|
||||||
* function (in [GSXMLParser+initialize] and [GSSAXHandler+initialize]).
|
* function (in [GSXMLParser+initialize] and [GSSAXHandler+initialize]).
|
||||||
*
|
|
||||||
* To implement the -resolveEntities method we must permit/deny any attempt
|
|
||||||
* to load an entity (before the function to resolve is even called),
|
|
||||||
* We therefore intercept the getEntity callback (using getEntityDefault()),
|
|
||||||
* re-implementing some of the code inside libxml2 to avoid attempts to
|
|
||||||
* load/parse external entities unless we have specifically enabled it.
|
|
||||||
*/
|
*/
|
||||||
static xmlParserInputPtr
|
static xmlParserInputPtr
|
||||||
loadEntityFunction(const unsigned char *url,
|
loadEntityFunction(const unsigned char *url,
|
||||||
|
@ -2741,6 +2707,7 @@ loadEntityFunction(const unsigned char *url,
|
||||||
NSString *location;
|
NSString *location;
|
||||||
NSArray *components;
|
NSArray *components;
|
||||||
NSMutableString *local;
|
NSMutableString *local;
|
||||||
|
GSXMLParser *parser;
|
||||||
unsigned count;
|
unsigned count;
|
||||||
unsigned index;
|
unsigned index;
|
||||||
|
|
||||||
|
@ -2748,6 +2715,12 @@ loadEntityFunction(const unsigned char *url,
|
||||||
if (url == NULL)
|
if (url == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
parser = [HANDLER parser];
|
||||||
|
if (NO == [parser _resolves])
|
||||||
|
{
|
||||||
|
return xmlNewStringInputStream(ctx, (const xmlChar *)"");
|
||||||
|
}
|
||||||
|
|
||||||
entityId = (eid != NULL) ? (id)UTF8Str(eid) : nil;
|
entityId = (eid != NULL) ? (id)UTF8Str(eid) : nil;
|
||||||
location = UTF8Str(url);
|
location = UTF8Str(url);
|
||||||
components = [location pathComponents];
|
components = [location pathComponents];
|
||||||
|
@ -2942,6 +2915,7 @@ static xmlParserInputPtr
|
||||||
resolveEntityFunction(void *ctx,
|
resolveEntityFunction(void *ctx,
|
||||||
const unsigned char *eid, const unsigned char *url)
|
const unsigned char *eid, const unsigned char *url)
|
||||||
{
|
{
|
||||||
|
NSLog(@"resolveEntityFunction called for %s %s", url, eid);
|
||||||
return loadEntityFunction(url, eid, ctx);
|
return loadEntityFunction(url, eid, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3729,7 +3703,7 @@ fatalErrorFunction(void *ctx, const unsigned char *msg, ...)
|
||||||
LIB->hasInternalSubset = (void*) hasInternalSubsetFunction;
|
LIB->hasInternalSubset = (void*) hasInternalSubsetFunction;
|
||||||
LIB->hasExternalSubset = (void*) hasExternalSubsetFunction;
|
LIB->hasExternalSubset = (void*) hasExternalSubsetFunction;
|
||||||
LIB->resolveEntity = (void*) resolveEntityFunction;
|
LIB->resolveEntity = (void*) resolveEntityFunction;
|
||||||
LIB->getEntity = (void*) getEntityIgnoreExternal;
|
LIB->getEntity = (void*) getEntityDefault;
|
||||||
LIB->entityDecl = (void*) entityDeclFunction;
|
LIB->entityDecl = (void*) entityDeclFunction;
|
||||||
LIB->notationDecl = (void*) notationDeclFunction;
|
LIB->notationDecl = (void*) notationDeclFunction;
|
||||||
LIB->attributeDecl = (void*) attributeDeclFunction;
|
LIB->attributeDecl = (void*) attributeDeclFunction;
|
||||||
|
@ -3852,7 +3826,7 @@ fatalErrorFunction(void *ctx, const unsigned char *msg, ...)
|
||||||
SETCB(getEntity, getEntity:);
|
SETCB(getEntity, getEntity:);
|
||||||
if (LIB->getEntity != getEntityFunction)
|
if (LIB->getEntity != getEntityFunction)
|
||||||
{
|
{
|
||||||
LIB->getEntity = getEntityIgnoreExternal;
|
LIB->getEntity = getEntityDefault;
|
||||||
}
|
}
|
||||||
SETCB(entityDecl, entityDecl:type:public:system:content:);
|
SETCB(entityDecl, entityDecl:type:public:system:content:);
|
||||||
SETCB(notationDecl, notationDecl:public:system:);
|
SETCB(notationDecl, notationDecl:public:system:);
|
||||||
|
@ -3898,7 +3872,11 @@ fatalErrorFunction(void *ctx, const unsigned char *msg, ...)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if LIBXML_VERSION < 21100
|
||||||
memcpy(lib, &htmlDefaultSAXHandler, sizeof(htmlSAXHandler));
|
memcpy(lib, &htmlDefaultSAXHandler, sizeof(htmlSAXHandler));
|
||||||
|
#else
|
||||||
|
xmlSAX2InitHtmlDefaultSAXHandler(lib);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LIB ((htmlSAXHandlerPtr)lib)
|
#define LIB ((htmlSAXHandlerPtr)lib)
|
||||||
LIB->internalSubset = (void*)internalSubsetFunction;
|
LIB->internalSubset = (void*)internalSubsetFunction;
|
||||||
|
|
|
@ -15,6 +15,7 @@ int main()
|
||||||
NSMutableArray *oparams;
|
NSMutableArray *oparams;
|
||||||
GSXMLNode *node;
|
GSXMLNode *node;
|
||||||
GSXMLRPC *rpc;
|
GSXMLRPC *rpc;
|
||||||
|
NSString *xml;
|
||||||
NSString *str;
|
NSString *str;
|
||||||
NSString *testPath;
|
NSString *testPath;
|
||||||
NSString *absolutePath;
|
NSString *absolutePath;
|
||||||
|
@ -155,44 +156,43 @@ int main()
|
||||||
stringByAppendingPathComponent: @"GNUmakefile"];
|
stringByAppendingPathComponent: @"GNUmakefile"];
|
||||||
absolutePath = [[NSURL fileURLWithPath: testPath] absoluteString];
|
absolutePath = [[NSURL fileURLWithPath: testPath] absoluteString];
|
||||||
|
|
||||||
str = [NSString stringWithFormat:
|
xml = [NSString stringWithFormat:
|
||||||
@"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
@"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
||||||
@"<!DOCTYPE foo [\n"
|
@"<!DOCTYPE foo [\n"
|
||||||
@"<!ENTITY foo SYSTEM \"%@\">\n"
|
@"<!ENTITY foo SYSTEM \"%@\">\n"
|
||||||
@"]>\n"
|
@"]>\n"
|
||||||
@"<file>&&foo;A</file>", absolutePath];
|
@"<file>&&foo;A</file>", absolutePath];
|
||||||
|
dat = [xml dataUsingEncoding: NSUTF8StringEncoding];
|
||||||
|
|
||||||
parser = [GSXMLParser parserWithData:
|
parser = [GSXMLParser parserWithData: dat];
|
||||||
[str dataUsingEncoding: NSUTF8StringEncoding]];
|
|
||||||
[parser substituteEntities: YES];
|
[parser substituteEntities: YES];
|
||||||
[parser parse];
|
[parser parse];
|
||||||
PASS_EQUAL([[[parser document] root] content], @"&A",
|
str = [[[parser document] root] content];
|
||||||
"external entity is ignored")
|
PASS_EQUAL(str, @"&A", "external entity is ignored")
|
||||||
|
|
||||||
parser = [GSXMLParser parserWithData:
|
parser = [GSXMLParser parserWithData: dat];
|
||||||
[str dataUsingEncoding: NSUTF8StringEncoding]];
|
|
||||||
[parser substituteEntities: YES];
|
[parser substituteEntities: YES];
|
||||||
[parser resolveEntities: YES];
|
[parser resolveEntities: YES];
|
||||||
[parser parse];
|
[parser parse];
|
||||||
str = [[[parser document] root] content];
|
str = [[[parser document] root] content];
|
||||||
PASS([str rangeOfString: @"MAKEFILES"].length > 0,
|
PASS(str != nil && [str rangeOfString: @"MAKEFILES"].length > 0,
|
||||||
"external entity is resolved")
|
"external entity is resolved")
|
||||||
|
|
||||||
str = @"<!DOCTYPE plist PUBLIC \"-//GNUstep//DTD plist 0.9//EN\""
|
xml = @"<!DOCTYPE plist PUBLIC \"-//GNUstep//DTD plist 0.9//EN\""
|
||||||
@" \"http://www.gnustep.org/plist-0_9.xml\">\n"
|
@" \"http://www.gnustep.org/plist-0_9.xml\">\n"
|
||||||
@"<plist></plist>";
|
@"<plist></plist>";
|
||||||
parser = [GSXMLParser parserWithData:
|
dat = [xml dataUsingEncoding: NSUTF8StringEncoding];
|
||||||
[str dataUsingEncoding: NSUTF8StringEncoding]];
|
parser = [GSXMLParser parserWithData: dat];
|
||||||
[parser substituteEntities: YES];
|
[parser substituteEntities: YES];
|
||||||
[parser resolveEntities: YES];
|
[parser resolveEntities: YES];
|
||||||
[parser doValidityChecking: YES];
|
[parser doValidityChecking: YES];
|
||||||
PASS([parser parse] == NO, "empty plist is not valid")
|
PASS([parser parse] == NO, "empty plist is not valid")
|
||||||
|
|
||||||
str = @"<!DOCTYPE plist PUBLIC \"-//GNUstep//DTD plist 0.9//EN\""
|
xml = @"<!DOCTYPE plist PUBLIC \"-//GNUstep//DTD plist 0.9//EN\""
|
||||||
@" \"http://www.gnustep.org/plist-0_9.xml\">\n"
|
@" \"http://www.gnustep.org/plist-0_9.xml\">\n"
|
||||||
@"<plist><string>xxx</string></plist>";
|
@"<plist><string>xxx</string></plist>";
|
||||||
parser = [GSXMLParser parserWithData:
|
dat = [xml dataUsingEncoding: NSUTF8StringEncoding];
|
||||||
[str dataUsingEncoding: NSUTF8StringEncoding]];
|
parser = [GSXMLParser parserWithData: dat];
|
||||||
[parser substituteEntities: YES];
|
[parser substituteEntities: YES];
|
||||||
[parser resolveEntities: YES];
|
[parser resolveEntities: YES];
|
||||||
[parser doValidityChecking: YES];
|
[parser doValidityChecking: YES];
|
||||||
|
|
Loading…
Reference in a new issue