git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25554 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2007-11-05 11:30:23 +00:00
parent 87edda35d7
commit 9bea555194
3 changed files with 79 additions and 20 deletions

View file

@ -1,3 +1,11 @@
2007-11-05 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSXML.m: Make sloppy parser available for internal use when
parsing bad xml produced by Apple tools.
* Source/NSPropertyList.m: Use GSSloppyXMLParser if normal xml2 based
parsing fails due to Ap[ple4's inclusioon of illegal characters in
the XML.
2007-10-31 Richard Frith-Macdonald <rfm@gnu.org> 2007-10-31 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSUserDefaults.m: ([setBoolForKey:]) changed to store YES * Source/NSUserDefaults.m: ([setBoolForKey:]) changed to store YES

View file

@ -44,11 +44,14 @@
#include "Foundation/NSUserDefaults.h" #include "Foundation/NSUserDefaults.h"
#include "Foundation/NSValue.h" #include "Foundation/NSValue.h"
#include "Foundation/NSDebug.h" #include "Foundation/NSDebug.h"
#include "Foundation/NSNull.h"
#include "Foundation/NSXMLParser.h" #include "Foundation/NSXMLParser.h"
#include "GNUstepBase/Unicode.h" #include "GNUstepBase/Unicode.h"
#include "GSPrivate.h" #include "GSPrivate.h"
@class GSSloppyXMLParser;
extern BOOL GSScanDouble(unichar*, unsigned, double*); extern BOOL GSScanDouble(unichar*, unsigned, double*);
@class GSMutableDictionary; @class GSMutableDictionary;
@ -103,7 +106,7 @@ extern BOOL GSScanDouble(unichar*, unsigned, double*);
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
stack = [[NSMutableArray alloc] initWithCapacity: 10]; stack = [[NSMutableArray alloc] initWithCapacity: 10];
theParser = [[NSXMLParser alloc] initWithData: data]; theParser = [[GSSloppyXMLParser alloc] initWithData: data];
[theParser setDelegate: self]; [theParser setDelegate: self];
opts = options; opts = options;
} }
@ -113,11 +116,15 @@ extern BOOL GSScanDouble(unichar*, unsigned, double*);
- (void) parser: (NSXMLParser *)parser - (void) parser: (NSXMLParser *)parser
foundCharacters: (NSString *)string foundCharacters: (NSString *)string
{ {
if (value == nil) string = [string stringByTrimmingSpaces];
if ([string length] > 0)
{ {
value = [[NSMutableString alloc] initWithCapacity: 50]; if (value == nil)
{
value = [[NSMutableString alloc] initWithCapacity: 50];
}
[value appendString: string];
} }
[value appendString: string];
} }
- (void) parser: (NSXMLParser *)parser - (void) parser: (NSXMLParser *)parser
@ -130,6 +137,12 @@ extern BOOL GSScanDouble(unichar*, unsigned, double*);
{ {
NSMutableDictionary *d; NSMutableDictionary *d;
if (key == nil)
{
key = RETAIN([NSNull null]);
}
[stack addObject: key];
DESTROY(key);
d = [[NSMutableDictionary alloc] initWithCapacity: 10]; d = [[NSMutableDictionary alloc] initWithCapacity: 10];
[stack addObject: d]; [stack addObject: d];
RELEASE(d); RELEASE(d);
@ -140,6 +153,12 @@ extern BOOL GSScanDouble(unichar*, unsigned, double*);
{ {
NSMutableArray *a; NSMutableArray *a;
if (key == nil)
{
key = RETAIN([NSNull null]);
}
[stack addObject: key];
DESTROY(key);
a = [[NSMutableArray alloc] initWithCapacity: 10]; a = [[NSMutableArray alloc] initWithCapacity: 10];
[stack addObject: a]; [stack addObject: a];
RELEASE(a); RELEASE(a);
@ -174,13 +193,19 @@ extern BOOL GSScanDouble(unichar*, unsigned, double*);
{ {
ASSIGN(plist, [[stack lastObject] makeImmutableCopyOnFail: NO]); ASSIGN(plist, [[stack lastObject] makeImmutableCopyOnFail: NO]);
} }
[stack removeLastObject];
inArray = NO; inArray = NO;
inDictionary = NO; inDictionary = NO;
ASSIGN(key, [stack lastObject]);
[stack removeLastObject];
if ((id)key == (id)[NSNull null])
{
DESTROY(key);
}
if ([stack count] > 0) if ([stack count] > 0)
{ {
id last; id last;
[stack removeLastObject];
last = [stack lastObject]; last = [stack lastObject];
if ([last isKindOfClass: [NSArray class]] == YES) if ([last isKindOfClass: [NSArray class]] == YES)
{ {
@ -2584,6 +2609,7 @@ GSPropertyListMake(id obj, NSDictionary *loc, BOOL xml,
parser = [GSXMLParser parser]; parser = [GSXMLParser parser];
[parser substituteEntities: YES]; [parser substituteEntities: YES];
[parser doValidityChecking: YES]; [parser doValidityChecking: YES];
[parser saveMessages: YES];
if ([parser parse: data] == NO || [parser parse: nil] == NO) if ([parser parse: data] == NO || [parser parse: nil] == NO)
{ {
error = @"failed to parse as valid XML matching DTD"; error = @"failed to parse as valid XML matching DTD";

View file

@ -33,7 +33,15 @@
NSString* const NSXMLParserErrorDomain = @"NSXMLParserErrorDomain"; NSString* const NSXMLParserErrorDomain = @"NSXMLParserErrorDomain";
#ifdef HAVE_LIBXML #if defined(HAVE_LIBXML)
/* We support a strict libxml2 based parser ... but sometimes we need a
* sloppier parser which copes with bad XML generated by Apple's software,
* so we call the sloppy parser GSSloppyXMLParser.
*/
#define SloppyXMLParser GSSloppyXMLParser
@interface GSSloppyXMLParser : NSXMLParser
@end
#include <Additions/GNUstepBase/GSXML.h> #include <Additions/GNUstepBase/GSXML.h>
@ -442,6 +450,18 @@ NSString* const NSXMLParserErrorDomain = @"NSXMLParserErrorDomain";
#else #else
/* We have no strict libxml based parser, so we use the sloppy parser
* as the normal NSXMLParser and create a GSSloppyXMLParser subclass
* so that we can still specify GSSloppyXMLParser in other files.
*/
#define SloppyXMLParser NSXMLParser
@interface GSSloppyXMLParser : NSXMLParser
@end
@implementation GSSloppyXMLParser
@end
#endif
@implementation NSString (NSXMLParser) @implementation NSString (NSXMLParser)
- (NSString *) _stringByExpandingXMLEntities - (NSString *) _stringByExpandingXMLEntities
@ -485,8 +505,13 @@ typedef struct NSXMLParserIvarsType
BOOL acceptHTML; // be lazy with bad tag nesting BOOL acceptHTML; // be lazy with bad tag nesting
} NSXMLParserIvars; } NSXMLParserIvars;
@implementation NSXMLParser @implementation SloppyXMLParser
#define EXTRA_DEBUG 0
typedef struct { @defs(NSXMLParser) } *xp;
#define _parser (((xp)self)->_parser)
#define _handler (((xp)self)->_handler)
#define this ((NSXMLParserIvars*)_parser) #define this ((NSXMLParserIvars*)_parser)
#define _del ((id)_handler) #define _del ((id)_handler)
@ -508,6 +533,8 @@ typedef struct NSXMLParserIvarsType
RELEASE(this->error); RELEASE(this->error);
RELEASE(this->tagPath); RELEASE(this->tagPath);
NSZoneFree([self zone], this); NSZoneFree([self zone], this);
_parser = 0;
_handler = 0;
} }
[super dealloc]; [super dealloc];
} }
@ -568,7 +595,7 @@ typedef struct NSXMLParserIvarsType
- (BOOL) _parseError: (NSString *)message - (BOOL) _parseError: (NSString *)message
{ {
#if 0 #if EXTRA_DEBUG
NSLog(@"XML parseError: %@", message); NSLog(@"XML parseError: %@", message);
#endif #endif
NSError *err = nil; NSError *err = nil;
@ -590,7 +617,7 @@ typedef struct NSXMLParserIvarsType
{ {
if ([tag isEqualToString: @"?xml"]) if ([tag isEqualToString: @"?xml"])
{ {
#if 0 #if EXTRA_DEBUG
NSLog(@"parserDidStartDocument: "); NSLog(@"parserDidStartDocument: ");
#endif #endif
if ([_del respondsToSelector: @selector(parserDidStartDocument:)]) if ([_del respondsToSelector: @selector(parserDidStartDocument:)])
@ -599,7 +626,7 @@ NSLog(@"parserDidStartDocument: ");
} }
if ([tag hasPrefix: @"?"]) if ([tag hasPrefix: @"?"])
{ {
#if 0 #if EXTRA_DEBUG
NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes); NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
#endif #endif
// parser: foundProcessingInstructionWithTarget: data: // parser: foundProcessingInstructionWithTarget: data:
@ -607,14 +634,14 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
} }
if ([tag isEqualToString: @"!DOCTYPE"]) if ([tag isEqualToString: @"!DOCTYPE"])
{ {
#if 0 #if EXTRA_DEBUG
NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes); NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
#endif #endif
return; return;
} }
if ([tag isEqualToString: @"!ENTITY"]) if ([tag isEqualToString: @"!ENTITY"])
{ {
#if 0 #if EXTRA_DEBUG
NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes); NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
#endif #endif
return; return;
@ -623,7 +650,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
{ {
// pass through as NSData // pass through as NSData
// parser: foundCDATA: // parser: foundCDATA:
#if 0 #if EXTRA_DEBUG
NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes); NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
#endif #endif
return; return;
@ -729,7 +756,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
const unsigned char *ap = --this->cp; // argument start pointer const unsigned char *ap = --this->cp; // argument start pointer
int c = cget(); // refetch first character int c = cget(); // refetch first character
#if 0 #if EXTRA_DEBUG
NSLog(@"_qarg: %02x %c", c, isprint(c)?c: ' '); NSLog(@"_qarg: %02x %c", c, isprint(c)?c: ' ');
#endif #endif
if (c == '\"') if (c == '\"')
@ -777,7 +804,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
while (!this->abort) while (!this->abort)
{ {
// parse next element // parse next element
#if 0 #if EXTRA_DEBUG
NSLog(@"_nextelement %02x %c", c, isprint(c)?c: ' '); NSLog(@"_nextelement %02x %c", c, isprint(c)?c: ' ');
#endif #endif
switch(c) switch(c)
@ -821,7 +848,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
[this->tagPath removeLastObject]; // pop from stack [this->tagPath removeLastObject]; // pop from stack
} }
} }
#if 0 #if EXTRA_DEBUG
NSLog(@"parserDidEndDocument: "); NSLog(@"parserDidEndDocument: ");
#endif #endif
@ -878,7 +905,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
tag = UTF8STR(tp + 1, this->cp - tp - 2); // don't include / and delimiting character tag = UTF8STR(tp + 1, this->cp - tp - 2); // don't include / and delimiting character
else else
tag = UTF8STR(tp, this->cp - tp - 1); // don't include delimiting character tag = UTF8STR(tp, this->cp - tp - 1); // don't include delimiting character
#if 0 #if EXTRA_DEBUG
NSLog(@"tag=%@ - %02x %c", tag, c, isprint(c)?c: ' '); NSLog(@"tag=%@ - %02x %c", tag, c, isprint(c)?c: ' ');
#endif #endif
parameters=[NSMutableDictionary dictionaryWithCapacity: 5]; parameters=[NSMutableDictionary dictionaryWithCapacity: 5];
@ -913,7 +940,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
break; break;
} }
arg=[self _qarg]; // get next argument (eats up to /, ?, >, =, space) arg=[self _qarg]; // get next argument (eats up to /, ?, >, =, space)
#if 0 #if EXTRA_DEBUG
NSLog(@"arg=%@", arg); NSLog(@"arg=%@", arg);
#endif #endif
if (!this->acceptHTML && [arg length] == 0) if (!this->acceptHTML && [arg length] == 0)
@ -989,8 +1016,6 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
@end @end
#endif
@implementation NSObject (NSXMLParserDelegateEventAdditions) @implementation NSObject (NSXMLParserDelegateEventAdditions)
- (NSData*) parser: (NSXMLParser*)aParser - (NSData*) parser: (NSXMLParser*)aParser
resolveExternalEntityName: (NSString*)aName resolveExternalEntityName: (NSString*)aName