From de0f75656e1621807f18d1550f39f179a43b37a7 Mon Sep 17 00:00:00 2001 From: helge Date: Thu, 5 May 2005 17:49:23 +0000 Subject: [PATCH] improved input processing of sax driver git-svn-id: http://svn.opengroupware.org/SOPE/trunk@797 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-ical/versitSaxDriver/ChangeLog | 5 + sope-ical/versitSaxDriver/VSSaxDriver.h | 14 +- sope-ical/versitSaxDriver/VSSaxDriver.m | 208 +++++++++++------- sope-ical/versitSaxDriver/VSStringFormatter.h | 2 +- sope-ical/versitSaxDriver/VSStringFormatter.m | 35 ++- sope-ical/versitSaxDriver/VSiCalSaxDriver.h | 2 +- sope-ical/versitSaxDriver/VSiCalSaxDriver.m | 2 +- sope-ical/versitSaxDriver/Version | 2 +- 8 files changed, 159 insertions(+), 111 deletions(-) diff --git a/sope-ical/versitSaxDriver/ChangeLog b/sope-ical/versitSaxDriver/ChangeLog index 939a5452..734d2b2f 100644 --- a/sope-ical/versitSaxDriver/ChangeLog +++ b/sope-ical/versitSaxDriver/ChangeLog @@ -1,3 +1,8 @@ +2005-05-05 Helge Hess + + * VSSaxDriver.m: improved parsing entry methods, added support for SAX + error handlers (v4.5.13) + 2005-04-25 Helge Hess * VSSaxDriver.m: fixed a gcc 4.0 warning (v4.5.12) diff --git a/sope-ical/versitSaxDriver/VSSaxDriver.h b/sope-ical/versitSaxDriver/VSSaxDriver.h index 7a1e078b..48ad72ec 100644 --- a/sope-ical/versitSaxDriver/VSSaxDriver.h +++ b/sope-ical/versitSaxDriver/VSSaxDriver.h @@ -1,6 +1,6 @@ /* Copyright (C) 2003-2004 Max Berger - Copyright (C) 2004 OpenGroupware.org + Copyright (C) 2004-2005 OpenGroupware.org This file is part of versitSaxDriver, written for the OpenGroupware.org project (OGo). @@ -24,13 +24,15 @@ #ifndef __versitSaxDriver_VSSaxDriver_H__ #define __versitSaxDriver_VSSaxDriver_H__ -#import - +#import #include +@class NSString, NSSet, NSDictionary, NSMutableArray, NSMutableDictionary; + @interface VSSaxDriver : NSObject < SaxXMLReader > { id contentHandler; + id errorHandler; NSString *prefixURI; NSMutableArray *cardStack; NSMutableArray *elementList; @@ -42,14 +44,14 @@ NSMutableDictionary *subItemMapping; } -- (NSSet *)attributeElements; +- (void)setElementMapping:(NSDictionary *)_mapping; - (void)setAttributeElements:(NSSet *)_elements; +- (NSSet *)attributeElements; - (NSDictionary *)elementMapping; -- (void)setElementMapping:(NSDictionary *)_mapping; -- (NSString *)prefixURI; - (void)setPrefixURI:(NSString*)_uri; +- (NSString *)prefixURI; - (void)setAttributeMapping:(NSDictionary *)_mapping; - (void)setAttributeMapping:(NSDictionary *)_mapping diff --git a/sope-ical/versitSaxDriver/VSSaxDriver.m b/sope-ical/versitSaxDriver/VSSaxDriver.m index ee219cc5..e740f5bd 100644 --- a/sope-ical/versitSaxDriver/VSSaxDriver.m +++ b/sope-ical/versitSaxDriver/VSSaxDriver.m @@ -1,6 +1,6 @@ /* Copyright (C) 2003-2004 Max Berger - Copyright (C) 2004 OpenGroupware.org + Copyright (C) 2004-2005 OpenGroupware.org This file is part of versitSaxDriver, written for the OpenGroupware.org project (OGo). @@ -23,6 +23,7 @@ #include "VSSaxDriver.h" #include "VSStringFormatter.h" +#include #include "common.h" @implementation VSSaxDriver @@ -42,7 +43,7 @@ static VSStringFormatter *stringFormatter = nil; static BOOL didInit = NO; NSUserDefaults *ud; - if(didInit) + if (didInit) return; didInit = YES; @@ -69,16 +70,17 @@ static VSStringFormatter *stringFormatter = nil; - (id)init { if ((self = [super init])) { self->prefixURI = @""; - self->cardStack = [[NSMutableArray alloc] init]; - self->elementList = [[NSMutableArray alloc] init]; - self->attributeMapping = [[NSMutableDictionary alloc] init]; - self->subItemMapping = [[NSMutableDictionary alloc] init]; + self->cardStack = [[NSMutableArray alloc] initWithCapacity:4]; + self->elementList = [[NSMutableArray alloc] initWithCapacity:8]; + self->attributeMapping = [[NSMutableDictionary alloc] initWithCapacity:8]; + self->subItemMapping = [[NSMutableDictionary alloc] initWithCapacity:8]; } return self; } - (void)dealloc { [self->contentHandler release]; + [self->errorHandler release]; [self->prefixURI release]; [self->cardStack release]; [self->elementList release]; @@ -106,7 +108,7 @@ static VSStringFormatter *stringFormatter = nil; /* handlers */ - (void)setContentHandler:(id)_handler { - ASSIGN(self->contentHandler,_handler); + ASSIGN(self->contentHandler, _handler); } - (void)setDTDHandler:(id)_handler { @@ -114,7 +116,7 @@ static VSStringFormatter *stringFormatter = nil; } - (void)setErrorHandler:(id)_handler { - // FIXME + ASSIGN(self->errorHandler, _handler); } - (void)setEntityResolver:(id)_handler { // FIXME @@ -126,16 +128,15 @@ static VSStringFormatter *stringFormatter = nil; - (id)dtdHandler { // FIXME - return NULL; + return nil; } - (id)errorHandler { - // FIXME - return NULL; + return self->errorHandler; } - (id)entityResolver { // FIXME - return NULL; + return nil; } - (void)setPrefixURI:(NSString *)_uri { @@ -166,14 +167,12 @@ static VSStringFormatter *stringFormatter = nil; - (void)setAttributeMapping:(NSDictionary *)_mapping forElement:(NSString *)_element { - if (!_element) + if (_element == nil) _element = @""; [attributeMapping setObject:_mapping forKey:_element]; } -- (void)setSubItemMapping:(NSArray *)_mapping - forElement:(NSString *)_element -{ +- (void)setSubItemMapping:(NSArray *)_mapping forElement:(NSString *)_element { [subItemMapping setObject:_mapping forKey:_element]; } @@ -252,8 +251,8 @@ static VSStringFormatter *stringFormatter = nil; attrName = [[_attr substringToIndex:r.location] uppercaseString]; left = NSMaxRange(r); right = [_attr length] - 1; - if(left < right) { - if(([_attr characterAtIndex:left] == '"') && + if (left < right) { + if (([_attr characterAtIndex:left] == '"') && ([_attr characterAtIndex:right] == '"')) { left += 1; @@ -264,7 +263,7 @@ static VSStringFormatter *stringFormatter = nil; attrValue = [_attr substringFromIndex:left]; } } - else if(left == right) { + else if (left == right) { attrValue = [_attr substringFromIndex:left]; } else { @@ -368,14 +367,15 @@ static VSStringFormatter *stringFormatter = nil; andContent:(NSString *)_content { NSArray *subItems; - + _content = [stringFormatter stringByUnescapingRFC2445Text:_content]; if ([self->attributeElements containsObject:_tagName]) { [self _addAttribute:_tagName value:_content]; + return; } - else { - [self _beginTag:_tagName withAttrs:_attrs]; - if ([_content length] > 0) { + + [self _beginTag:_tagName withAttrs:_attrs]; + if ([_content length] > 0) { if ((subItems = [self->subItemMapping objectForKey:_tagName])) { [self _addSubItems:subItems withData:_content]; } @@ -383,21 +383,21 @@ static VSStringFormatter *stringFormatter = nil; [self->elementList addObject: [NSArray arrayWithObjects:@"DATA", _content, nil]]; } - } - [self _endTag:_tagName]; } + [self _endTag:_tagName]; } - (void)_eventsForElements { NSEnumerator *enu; NSArray *obj; - NSString *type; - NSString *name; - unichar *chardata; - id attrs; enu = [elementList objectEnumerator]; - while ((obj = [enu nextObject])) { + while ((obj = [enu nextObject]) != nil) { + id attrs; + NSString *type; + NSString *name; + unichar *chardata; + type = [obj objectAtIndex:0]; name = [obj objectAtIndex:1]; @@ -441,8 +441,8 @@ static VSStringFormatter *stringFormatter = nil; options:0 range:todoRange]; /* is line well-formed? */ - if(r.length == 0) { - if(debugOn) { + if (r.length == 0) { + if (debugOn) { NSLog(@"%s got an improper content line! ->\n%@", __PRETTY_FUNCTION__, _line); @@ -456,7 +456,7 @@ static VSStringFormatter *stringFormatter = nil; /* possible shortcut: if we spotted a ':', we don't have to do "expensive" argument scanning/processing. */ - if([_line characterAtIndex:r.location] != ':') { + if ([_line characterAtIndex:r.location] != ':') { BOOL isAtEnd = NO, isInDquote = NO; unsigned start = NSMaxRange(r); @@ -469,8 +469,8 @@ static VSStringFormatter *stringFormatter = nil; options:0 range:todoRange]; /* is line well-formed? */ - if(r.length == 0 || r.location == 0) { - if(debugOn) { + if (r.length == 0 || r.location == 0) { + if (debugOn) { NSLog(@"%s got an improper content line! ->\n%@", __PRETTY_FUNCTION__, _line); @@ -479,25 +479,25 @@ static VSStringFormatter *stringFormatter = nil; return; } /* first check if delimiter candidate is escaped */ - if([_line characterAtIndex:(r.location - 1)] != '\\') { + if ([_line characterAtIndex:(r.location - 1)] != '\\') { unichar delimiter; NSRange copyRange; delimiter = [_line characterAtIndex:r.location]; - if(delimiter == '\"') { + if (delimiter == '\"') { /* not a real delimiter - toggle isInDquote for proper escaping */ isInDquote = !isInDquote; } else { - if(!isInDquote) { + if (!isInDquote) { /* is a delimiter, which one? */ skip = NO; - if(delimiter == ':') { + if (delimiter == ':') { isAtEnd = YES; } copyRange = NSMakeRange(start, r.location - start); [tagAttributes addObject:[_line substringWithRange:copyRange]]; - if(!isAtEnd) { + if (!isAtEnd) { /* adjust start, todoRange */ start = NSMaxRange(r); todoRange = NSMakeRange(start, length - start); @@ -505,7 +505,7 @@ static VSStringFormatter *stringFormatter = nil; } } } - if(skip) { + if (skip) { /* adjust todoRange */ unsigned offset = NSMaxRange(r); todoRange = NSMakeRange(offset, length - offset); @@ -525,12 +525,12 @@ static VSStringFormatter *stringFormatter = nil; NSString *mtName; mtName = [self _mapTagName:tagValue]; - if([self->cardStack count] > 0) { + if ([self->cardStack count] > 0) { NSString *expectedName; expectedName = [[self->cardStack lastObject] objectAtIndex:1]; - if(![expectedName isEqualToString:mtName]) { - if(debugOn) { + if (![expectedName isEqualToString:mtName]) { + if (debugOn) { NSLog(@"%s found end tag '%@' which doesn't match expected name " @"'%@'! Tag '%@' hasn't been closed properly. Given iCal " @"document contains errors!", @@ -540,7 +540,7 @@ static VSStringFormatter *stringFormatter = nil; expectedName); } /* probably futile attempt to parse anyways */ - if(debugOn) { + if (debugOn) { NSLog(@"%s trying to fix previous error by inserting bogus end " @"tag.", __PRETTY_FUNCTION__); @@ -550,7 +550,7 @@ static VSStringFormatter *stringFormatter = nil; } } else { - if(debugOn) { + if (debugOn) { NSLog(@"%s found end tag '%@' without any open tags left?!", __PRETTY_FUNCTION__, mtName); @@ -590,18 +590,18 @@ static VSStringFormatter *stringFormatter = nil; for(pos = 0; pos < length; pos++) { unichar c = [_rawString characterAtIndex:pos]; - if(c == '\r') { - if(((length - 1) - pos) >= 1) { - if([_rawString characterAtIndex:pos + 1] == '\n') { + if (c == '\r') { + if (((length - 1) - pos) >= 1) { + if ([_rawString characterAtIndex:pos + 1] == '\n') { BOOL isAtEndOfLine = YES; /* test for folding first */ - if(((length - 1) - pos) >= 2) { + if (((length - 1) - pos) >= 2) { unichar ws = [_rawString characterAtIndex:pos + 2]; isAtEndOfLine = [whitespaceCharSet characterIsMember:ws] ? NO : YES; - if(!isAtEndOfLine) { + if (!isAtEndOfLine) { /* assemble part of line up to pos */ - if(r.length > 0) { + if (r.length > 0) { [line appendString:[_rawString substringWithRange:r]]; } /* unfold */ @@ -609,9 +609,9 @@ static VSStringFormatter *stringFormatter = nil; r = NSMakeRange(pos + 1, 0); /* begin new range */ } } - if(isAtEndOfLine) { + if (isAtEndOfLine) { /* assemble part of line up to pos */ - if(r.length > 0) { + if (r.length > 0) { [line appendString:[_rawString substringWithRange:r]]; } [self _parseLine:line]; @@ -624,22 +624,22 @@ static VSStringFormatter *stringFormatter = nil; } else { /* garbled last line! */ - if(debugOn) { + if (debugOn) { NSLog(@"%s Last line is truncated, trying to parse anyways!", __PRETTY_FUNCTION__); } } } - else if(c == '\n') { /* broken, non-standard */ + else if (c == '\n') { /* broken, non-standard */ BOOL isAtEndOfLine = YES; /* test for folding first */ - if(((length - 1) - pos) >= 1) { + if (((length - 1) - pos) >= 1) { unichar ws = [_rawString characterAtIndex:pos + 1]; isAtEndOfLine = [whitespaceCharSet characterIsMember:ws] ? NO : YES; - if(!isAtEndOfLine) { + if (!isAtEndOfLine) { /* assemble part of line up to pos */ - if(r.length > 0) { + if (r.length > 0) { [line appendString:[_rawString substringWithRange:r]]; } /* unfold */ @@ -647,9 +647,9 @@ static VSStringFormatter *stringFormatter = nil; r = NSMakeRange(pos + 1, 0); /* begin new range */ } } - if(isAtEndOfLine) { + if (isAtEndOfLine) { /* assemble part of line up to pos */ - if(r.length > 0) { + if (r.length > 0) { [line appendString:[_rawString substringWithRange:r]]; } [self _parseLine:line]; @@ -662,8 +662,8 @@ static VSStringFormatter *stringFormatter = nil; r.length += 1; } } - if(r.length > 0) { - if(debugOn) { + if (r.length > 0) { + if (debugOn) { NSLog(@"%s Last line of iCal string is not properly terminated!", __PRETTY_FUNCTION__); } @@ -671,8 +671,8 @@ static VSStringFormatter *stringFormatter = nil; [self _parseLine:line]; } - if([self->cardStack count] != 0) { - if(debugOn) { + if ([self->cardStack count] != 0) { + if (debugOn) { NSLog(@"%s found elements on cardStack. This indicates an improper " @"iCal structure! Not all required events will have been " @"generated, leading to unpredictable results!", @@ -685,46 +685,88 @@ static VSStringFormatter *stringFormatter = nil; [self->contentHandler endDocument]; } -- (void)parseFromSource:(id)_source { +/* main entry functions */ + +- (void)parseFromSource:(id)_source systemId:(NSString *)_sysId { if (debugOn) - NSLog(@"%s: parse: %@", __PRETTY_FUNCTION__, _source); + NSLog(@"%s: parse: %@ (sysid=%@)", __PRETTY_FUNCTION__, _source, _sysId); if ([_source isKindOfClass:[NSURL class]]) { - if (debugOn) - NSLog(@"%s: trying to load URL...",__PRETTY_FUNCTION__); + if (_sysId == nil) _sysId = [_source absoluteString]; + + if (debugOn) { + NSLog(@"%s: trying to load URL: %@ (sysid=%@)",__PRETTY_FUNCTION__, + _source, _sysId); + } + + // TODO: remember encoding of source _source = [_source resourceDataUsingCache:NO]; } if ([_source isKindOfClass:[NSData class]]) { + if (debugOn) { + NSLog(@"%s: trying to decode data (0x%08X,len=%d) ...", + __PRETTY_FUNCTION__, _source, [_source length]); + } + if (_sysId == nil) _sysId = @""; + // FIXME: Data is not always utf-8..... - if (debugOn) - NSLog(@"%s: trying to decode data...",__PRETTY_FUNCTION__); _source = [[[NSString alloc] initWithData:_source encoding:NSUTF8StringEncoding] autorelease]; } - - if ([_source isKindOfClass:[NSString class]]) { - if (debugOn) - NSLog(@"%s: trying to parse string...",__PRETTY_FUNCTION__); - [self _parseString:_source]; - } - else { + + if (![_source isKindOfClass:[NSString class]]) { + SaxParseException *e; + if (debugOn) NSLog(@"%s: unrecognizable source: %@", __PRETTY_FUNCTION__,_source); - // FIXME: Return Error + + e = (id)[SaxParseException exceptionWithName:@"SaxIOException" + reason:@"cannot handle data-source" + userInfo:nil]; + + [self->errorHandler fatalError:e]; + return; } + + /* start parsing */ + + if (debugOn) { + NSLog(@"%s: trying to parse string (0x%08X,len=%d) ...", + __PRETTY_FUNCTION__, _source, [_source length]); + } + if (_sysId == nil) _sysId = @""; + [self _parseString:_source]; } -- (void)parseFromSource:(id)_source systemId:(NSString *)_sysId { - [self parseFromSource:_source]; +- (void)parseFromSource:(id)_source { + [self parseFromSource:_source systemId:nil]; } - (void)parseFromSystemId:(NSString *)_sysId { NSURL *url; - if ((url = [NSURL URLWithString:_sysId])) - [self parseFromSource:url systemId:_sysId]; + if ([_sysId rangeOfString:@"://"].length == 0) { + /* seems to be a path, path to be a proper URL */ + url = [NSURL fileURLWithPath:_sysId]; + } + else { + /* Note: Cocoa NSURL doesn't complain on "/abc/def" like input! */ + url = [NSURL URLWithString:_sysId]; + } + + if (url == nil) { + SaxParseException *e; + + e = (id)[SaxParseException exceptionWithName:@"SaxIOException" + reason:@"cannot handle system-id" + userInfo:nil]; + [self->errorHandler fatalError:e]; + return; + } + + [self parseFromSource:url systemId:_sysId]; } /* debugging */ diff --git a/sope-ical/versitSaxDriver/VSStringFormatter.h b/sope-ical/versitSaxDriver/VSStringFormatter.h index df0fc16d..734b475d 100644 --- a/sope-ical/versitSaxDriver/VSStringFormatter.h +++ b/sope-ical/versitSaxDriver/VSStringFormatter.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 OpenGroupware.org + Copyright (C) 2004-2005 OpenGroupware.org This file is part of versitSaxDriver, written for the OpenGroupware.org project (OGo). diff --git a/sope-ical/versitSaxDriver/VSStringFormatter.m b/sope-ical/versitSaxDriver/VSStringFormatter.m index a116bea4..7f8dcae2 100644 --- a/sope-ical/versitSaxDriver/VSStringFormatter.m +++ b/sope-ical/versitSaxDriver/VSStringFormatter.m @@ -1,25 +1,24 @@ /* - Copyright (C) 2004 OpenGroupware.org + Copyright (C) 2004-2005 OpenGroupware.org - This file is part of versitSaxDriver, written for the OpenGroupware.org - project (OGo). + This file is part of versitSaxDriver, written for the OpenGroupware.org + project (OGo). - SOPE is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. + SOPE is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. - SOPE is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. + SOPE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. - You should have received a copy of the GNU Lesser General Public - License along with SOPE; see the file COPYING. If not, write to the - Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. - */ - + You should have received a copy of the GNU Lesser General Public + License along with SOPE; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ #include "VSStringFormatter.h" #include "common.h" @@ -92,4 +91,4 @@ static NSCharacterSet *escSet = nil; return safeString; } -@end +@end /* VSStringFormatter */ diff --git a/sope-ical/versitSaxDriver/VSiCalSaxDriver.h b/sope-ical/versitSaxDriver/VSiCalSaxDriver.h index f1e67cea..a70793ee 100644 --- a/sope-ical/versitSaxDriver/VSiCalSaxDriver.h +++ b/sope-ical/versitSaxDriver/VSiCalSaxDriver.h @@ -1,6 +1,6 @@ /* Copyright (C) 2003-2004 Max Berger - Copyright (C) 2004 OpenGroupware.org + Copyright (C) 2004-2005 OpenGroupware.org This file is part of versitSaxDriver, written for the OpenGroupware.org project (OGo). diff --git a/sope-ical/versitSaxDriver/VSiCalSaxDriver.m b/sope-ical/versitSaxDriver/VSiCalSaxDriver.m index 7c5bed0d..79f3c1a0 100644 --- a/sope-ical/versitSaxDriver/VSiCalSaxDriver.m +++ b/sope-ical/versitSaxDriver/VSiCalSaxDriver.m @@ -1,6 +1,6 @@ /* Copyright (C) 2003-2004 Max Berger - Copyright (C) 2004 OpenGroupware.org + Copyright (C) 2004-2005 OpenGroupware.org This file is part of versitSaxDriver, written for the OpenGroupware.org project (OGo). diff --git a/sope-ical/versitSaxDriver/Version b/sope-ical/versitSaxDriver/Version index cda34ac9..76aa6eb9 100644 --- a/sope-ical/versitSaxDriver/Version +++ b/sope-ical/versitSaxDriver/Version @@ -1,3 +1,3 @@ # Version file -SUBMINOR_VERSION:=12 +SUBMINOR_VERSION:=13 -- 2.39.5