From eb3ec572d9fe1516cb59db8ed7712570249835fc Mon Sep 17 00:00:00 2001 From: helge Date: Sun, 8 May 2005 23:02:51 +0000 Subject: [PATCH] more work on vCard parsing git-svn-id: http://svn.opengroupware.org/SOPE/trunk@805 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-ical/NGiCal/ChangeLog | 2 + sope-ical/NGiCal/GNUmakefile | 19 +- sope-ical/NGiCal/NGVCard.h | 66 +++++ sope-ical/NGiCal/NGVCard.m | 142 ++++++++++ sope-ical/NGiCal/NGVCardAddress.h | 3 + sope-ical/NGiCal/NGVCardAddress.m | 38 +++ sope-ical/NGiCal/NGVCardCategories.h | 56 ++++ sope-ical/NGiCal/NGVCardCategories.m | 13 +- sope-ical/NGiCal/NGVCardName.m | 30 +++ sope-ical/NGiCal/NGVCardOrg.h | 60 +++++ sope-ical/NGiCal/NGVCardOrg.m | 138 ++++++++++ sope-ical/NGiCal/NGVCardPhone.h | 36 +++ sope-ical/NGiCal/NGVCardPhone.m | 2 +- sope-ical/NGiCal/NGVCardSaxHandler.h | 22 +- sope-ical/NGiCal/NGVCardSaxHandler.m | 366 ++++++++++++++++++++++++-- sope-ical/NGiCal/NGVCardSimpleValue.h | 50 ++++ sope-ical/NGiCal/NGVCardSimpleValue.m | 27 +- sope-ical/NGiCal/NGVCardValue.h | 33 +-- sope-ical/NGiCal/NGVCardValue.m | 51 ++++ sope-ical/NGiCal/Version | 2 +- sope-ical/samples/GNUmakefile | 8 +- sope-ical/samples/vcfparsetest.m | 126 +++++++++ 22 files changed, 1231 insertions(+), 59 deletions(-) create mode 100644 sope-ical/NGiCal/NGVCardCategories.h create mode 100644 sope-ical/NGiCal/NGVCardOrg.h create mode 100644 sope-ical/NGiCal/NGVCardOrg.m create mode 100644 sope-ical/NGiCal/NGVCardPhone.h create mode 100644 sope-ical/NGiCal/NGVCardSimpleValue.h create mode 100644 sope-ical/samples/vcfparsetest.m diff --git a/sope-ical/NGiCal/ChangeLog b/sope-ical/NGiCal/ChangeLog index 716f419a..cf4d0931 100644 --- a/sope-ical/NGiCal/ChangeLog +++ b/sope-ical/NGiCal/ChangeLog @@ -1,5 +1,7 @@ 2005-05-08 Helge Hess + * more work on vCard parsing (v4.5.53) + * work on vCard objects (incomplete) (v4.5.52) 2005-04-25 Helge Hess diff --git a/sope-ical/NGiCal/GNUmakefile b/sope-ical/NGiCal/GNUmakefile index b05baa16..09c626e6 100644 --- a/sope-ical/NGiCal/GNUmakefile +++ b/sope-ical/NGiCal/GNUmakefile @@ -35,9 +35,14 @@ libNGiCal_HEADER_FILES = \ NSCalendarDate+ICal.h \ \ NGVCard.h \ - NGVCardValue.h \ - NGVCardName.h \ NGVCardAddress.h \ + NGVCardCategories.h \ + NGVCardName.h \ + NGVCardOrg.h \ + NGVCardPhone.h \ + NGVCardSaxHandler.h \ + NGVCardSimpleValue.h \ + NGVCardValue.h \ # IcalResponse.h \ @@ -65,14 +70,16 @@ libNGiCal_OBJC_FILES = \ iCalRecurrenceCalculator.m \ \ NGICalSaxHandler.m \ - NGVCardSaxHandler.m \ + \ NGVCard.m \ - NGVCardValue.m \ - NGVCardSimpleValue.m \ NGVCardAddress.m \ - NGVCardPhone.m \ NGVCardCategories.m \ NGVCardName.m \ + NGVCardOrg.m \ + NGVCardPhone.m \ + NGVCardSaxHandler.m \ + NGVCardSimpleValue.m \ + NGVCardValue.m \ # NSString+ICal.m \ # IcalElements.m diff --git a/sope-ical/NGiCal/NGVCard.h b/sope-ical/NGiCal/NGVCard.h index c84df571..f6fa1661 100644 --- a/sope-ical/NGiCal/NGVCard.h +++ b/sope-ical/NGiCal/NGVCard.h @@ -28,12 +28,78 @@ NGVCard Represents a vCard object. + + XML DTD in Dawson-03 Draft: + + + + + + + + + + Mandatory elements: + n + fn */ +@class NSString, NSArray, NSDictionary; + @interface NGVCard : NSObject { + NSString *uid; + NSString *version; + NSString *vClass; + NSString *prodID; + // TODO: 'rev' (datetime) + + NSArray *tel; + NSArray *adr; + NSArray *email; + NSArray *label; + NSDictionary *x; } ++ (NSArray *)parseVCardsFromSource:(id)_src; + +- (id)initWithUid:(NSString *)_uid version:(NSString *)_version; + +/* accessors */ + +- (NSString *)version; + +- (void)setUid:(NSString *)_uid; +- (NSString *)uid; + +- (void)setVClass:(NSString *)_s; +- (NSString *)vClass; +- (void)setProdID:(NSString *)_s; +- (NSString *)prodID; + +- (void)setTel:(NSArray *)_tel; +- (NSArray *)tel; +- (void)setAdr:(NSArray *)_adr; +- (NSArray *)adr; +- (void)setEmail:(NSArray *)_array; +- (NSArray *)email; +- (void)setLabel:(NSArray *)_array; +- (NSArray *)label; + +- (void)setX:(NSDictionary *)_dict; +- (NSDictionary *)x; + @end #endif /* __NGiCal_NGVCard_H__ */ diff --git a/sope-ical/NGiCal/NGVCard.m b/sope-ical/NGiCal/NGVCard.m index 268d5c90..f1de3bcf 100644 --- a/sope-ical/NGiCal/NGVCard.m +++ b/sope-ical/NGiCal/NGVCard.m @@ -20,12 +20,154 @@ */ #include "NGVCard.h" +#include "NGVCardSaxHandler.h" +#include +#include #include "common.h" @implementation NGVCard +static id parser = nil; // THREAD +static NGVCardSaxHandler *sax = nil; // THREAD + ++ (id)vCardParser { + if (sax == nil) + sax = [[NGVCardSaxHandler alloc] init]; + + if (parser == nil) { + parser = + [[[SaxXMLReaderFactory standardXMLReaderFactory] + createXMLReaderForMimeType:@"text/x-vcard"] + retain]; + if (parser == nil) { + NSLog(@"%s: did not find a parser for text/x-vcard !", + __PRETTY_FUNCTION__); + return nil; + } + + [parser setContentHandler:sax]; + [parser setErrorHandler:sax]; + } + + return parser; +} + ++ (NSArray *)parseVCardsFromSource:(id)_src { + static id parser; + + if ((parser = [self vCardParser]) == nil) + return nil; + + [parser parseFromSource:_src]; + return [sax vCards]; +} + +- (id)initWithUid:(NSString *)_uid version:(NSString *)_version { + if ((self = [super init]) != nil) { + self->uid = [_uid copy]; + self->version = [_version copy]; + } + return self; +} +- (id)init { + return [self initWithUid:nil version:@"3.0"]; +} + - (void)dealloc { + [self->vClass release]; + [self->prodID release]; + [self->x release]; + [self->tel release]; + [self->adr release]; + [self->email release]; + [self->label release]; + [self->version release]; + [self->uid release]; [super dealloc]; } +/* accessors */ + +- (NSString *)version { + return self->version; +} + +- (void)setUid:(NSString *)_uid { + ASSIGNCOPY(self->uid, _uid); +} +- (NSString *)uid { + return self->uid; +} + +- (void)setVClass:(NSString *)_vClass { + ASSIGNCOPY(self->vClass, _vClass); +} +- (NSString *)vClass { + return self->vClass; +} + +- (void)setProdID:(NSString *)_prodID { + ASSIGNCOPY(self->prodID, _prodID); +} +- (NSString *)prodID { + return self->prodID; +} + +- (void)setTel:(NSArray *)_tel { + ASSIGNCOPY(self->tel, _tel); +} +- (NSArray *)tel { + return self->tel; +} + +- (void)setAdr:(NSArray *)_adr { + ASSIGNCOPY(self->adr, _adr); +} +- (NSArray *)adr { + return self->adr; +} + +- (void)setEmail:(NSArray *)_email { + ASSIGNCOPY(self->email, _email); +} +- (NSArray *)email { + return self->email; +} + +- (void)setLabel:(NSArray *)_label { + ASSIGNCOPY(self->label, _label); +} +- (NSArray *)label { + return self->label; +} + +- (void)setX:(NSDictionary *)_dict { + ASSIGNCOPY(self->x, _dict); +} +- (NSDictionary *)x { + return self->x; +} + +/* description */ + +- (void)appendAttributesToDescription:(NSMutableString *)_ms { + if (self->uid != nil) [_ms appendFormat:@" uid='%@'", self->uid]; + + if ([self->tel count] > 0) [_ms appendFormat:@" tel=%@", self->tel]; + if ([self->adr count] > 0) [_ms appendFormat:@" adr=%@", self->adr]; + if ([self->email count] > 0) [_ms appendFormat:@" email=%@", self->email]; + if ([self->label count] > 0) [_ms appendFormat:@" label=%@", self->label]; + if ([self->x count] > 0) [_ms appendFormat:@" x=%@", self->x]; +} + +- (NSString *)description { + NSMutableString *str = nil; + + str = [NSMutableString stringWithCapacity:64]; + [str appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])]; + [self appendAttributesToDescription:str]; + [str appendString:@">"]; + return str; +} + @end /* NGVCard */ diff --git a/sope-ical/NGiCal/NGVCardAddress.h b/sope-ical/NGiCal/NGVCardAddress.h index 6953a995..44f04f47 100644 --- a/sope-ical/NGiCal/NGVCardAddress.h +++ b/sope-ical/NGiCal/NGVCardAddress.h @@ -43,6 +43,9 @@ NSString *country; } +- (id)initWithPropertyList:(id)_plist group:(NSString *)_group + types:(NSArray *)_types arguments:(NSDictionary *)_args; + /* accessors */ - (NSString *)pobox; diff --git a/sope-ical/NGiCal/NGVCardAddress.m b/sope-ical/NGiCal/NGVCardAddress.m index 227c07d3..3cfc7b22 100644 --- a/sope-ical/NGiCal/NGVCardAddress.m +++ b/sope-ical/NGiCal/NGVCardAddress.m @@ -24,6 +24,37 @@ @implementation NGVCardAddress +- (id)initWithDictionary:(NSDictionary *)_plist group:(NSString *)_group + types:(NSArray *)_types arguments:(NSDictionary *)_a +{ + if ((self = [super initWithGroup:_group types:_types arguments:_a]) != nil) { + self->pobox = [[_plist objectForKey:@"pobox"] copy]; + self->extadd = [[_plist objectForKey:@"extadd"] copy]; + self->street = [[_plist objectForKey:@"street"] copy]; + self->locality = [[_plist objectForKey:@"locality"] copy]; + self->region = [[_plist objectForKey:@"region"] copy]; + self->pcode = [[_plist objectForKey:@"pcode"] copy]; + self->country = [[_plist objectForKey:@"country"] copy]; + } + return self; +} +- (id)initWithPropertyList:(id)_plist group:(NSString *)_group + types:(NSArray *)_types arguments:(NSDictionary *)_a +{ + return [self initWithDictionary:_plist + group:_group types:_types arguments:_a]; +} + +- (id)initWithGroup:(NSString *)_group types:(NSArray *)_types + arguments:(NSDictionary *)_a +{ + return [self initWithPropertyList:nil + group:_group types:_types arguments:_a]; +} +- (id)init { + return [self initWithPropertyList:nil group:nil types:nil arguments:nil]; +} + - (void)dealloc { [self->pobox release]; [self->extadd release]; @@ -172,4 +203,11 @@ return self; } +/* description */ + +- (void)appendAttributesToDescription:(NSMutableString *)_ms { + [super appendAttributesToDescription:_ms]; + [_ms appendFormat:@" vcard=%@", [self vCardString]]; +} + @end /* NGVCardAddress */ diff --git a/sope-ical/NGiCal/NGVCardCategories.h b/sope-ical/NGiCal/NGVCardCategories.h new file mode 100644 index 00000000..05935df5 --- /dev/null +++ b/sope-ical/NGiCal/NGVCardCategories.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2005 Helge Hess + + This file is part of SOPE. + + 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. + + 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. +*/ + +#ifndef __NGiCal_NGVCardCategories_H__ +#define __NGiCal_NGVCardCategories_H__ + +#include + +/* + NGVCardCategories + + Note: vCard apparently cannot represent categories which contain commas. + At least Kontact and Evolution do not (no escaping of commas). +*/ + +@class NSArray; + +@interface NGVCardCategories : NGVCardValue +{ + NSArray *categories; +} + +/* accessors */ + +- (NSArray *)categories; + +/* values */ + +- (NSArray *)asArray; + +/* fake being an array */ + +- (id)objectAtIndex:(unsigned)_idx; +- (unsigned)count; + +@end + +#endif /* __NGiCal_NGVCardCategories_H__ */ diff --git a/sope-ical/NGiCal/NGVCardCategories.m b/sope-ical/NGiCal/NGVCardCategories.m index c87710eb..6e50b692 100644 --- a/sope-ical/NGiCal/NGVCardCategories.m +++ b/sope-ical/NGiCal/NGVCardCategories.m @@ -19,7 +19,7 @@ 02111-1307, USA. */ -#include "NGVCardValue.h" +#include "NGVCardCategories.h" #include "common.h" @implementation NGVCardCategories @@ -53,6 +53,10 @@ return [self categories]; } +- (NSArray *)asArray { + return self->categories; +} + /* fake being an array */ - (id)objectAtIndex:(unsigned)_idx { @@ -84,4 +88,11 @@ return self; } +/* description */ + +- (void)appendAttributesToDescription:(NSMutableString *)_ms { + [super appendAttributesToDescription:_ms]; + [_ms appendFormat:@" vcard=%@", [self vCardString]]; +} + @end /* NGVCardCategories */ diff --git a/sope-ical/NGiCal/NGVCardName.m b/sope-ical/NGiCal/NGVCardName.m index b40d590d..897e2ac3 100644 --- a/sope-ical/NGiCal/NGVCardName.m +++ b/sope-ical/NGiCal/NGVCardName.m @@ -24,6 +24,29 @@ @implementation NGVCardName +- (id)initWithPropertyList:(id)_plist group:(NSString *)_group + types:(NSArray *)_types arguments:(NSDictionary *)_a +{ + if ((self = [super initWithGroup:_group types:_types arguments:_a]) != nil) { + self->family = [[_plist objectForKey:@"family"] copy]; + self->given = [[_plist objectForKey:@"given"] copy]; + self->other = [[_plist objectForKey:@"other"] copy]; + self->prefix = [[_plist objectForKey:@"prefix"] copy]; + self->suffix = [[_plist objectForKey:@"suffix"] copy]; + } + return self; +} + +- (id)initWithGroup:(NSString *)_group types:(NSArray *)_types + arguments:(NSDictionary *)_a +{ + return [self initWithPropertyList:nil + group:_group types:_types arguments:_a]; +} +- (id)init { + return [self initWithPropertyList:nil group:nil types:nil arguments:nil]; +} + - (void)dealloc { [self->family release]; [self->given release]; @@ -157,4 +180,11 @@ return self; } +/* description */ + +- (void)appendAttributesToDescription:(NSMutableString *)_ms { + [super appendAttributesToDescription:_ms]; + [_ms appendFormat:@" vcard=%@", [self vCardString]]; +} + @end /* NGVCardName */ diff --git a/sope-ical/NGiCal/NGVCardOrg.h b/sope-ical/NGiCal/NGVCardOrg.h new file mode 100644 index 00000000..b21ab0e7 --- /dev/null +++ b/sope-ical/NGiCal/NGVCardOrg.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2005 Helge Hess + + This file is part of SOPE. + + 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. + + 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. +*/ + +#ifndef __NGiCal_NGVCardOrg_H__ +#define __NGiCal_NGVCardOrg_H__ + +#include + +@class NSDictionary; + +/* + NGVCardOrg + + Represents an organization as transported in the 'ORG' vCard tag. +*/ + +@class NSString, NSArray; + +@interface NGVCardOrg : NGVCardValue +{ + NSString *orgnam; // incorrect in dawson draft? (example mismatch) + NSArray *orgunits; +} + +/* accessors */ + +- (NSString *)orgnam; +- (NSArray *)orgunits; + +/* values */ + +- (NSDictionary *)asDictionary; +- (NSArray *)asArray; + +/* fake being an array */ + +- (id)objectAtIndex:(unsigned)_idx; +- (unsigned)count; + +@end + +#endif /* __NGiCal_NGVCardOrg_H__ */ diff --git a/sope-ical/NGiCal/NGVCardOrg.m b/sope-ical/NGiCal/NGVCardOrg.m new file mode 100644 index 00000000..e76e56b5 --- /dev/null +++ b/sope-ical/NGiCal/NGVCardOrg.m @@ -0,0 +1,138 @@ +/* + Copyright (C) 2005 Helge Hess + + This file is part of SOPE. + + 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. + + 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 "NGVCardOrg.h" +#include "common.h" + +@implementation NGVCardOrg + +- (void)dealloc { + [self->orgnam release]; + [self->orgunits release]; + [super dealloc]; +} + +/* accessors */ + +- (NSString *)orgnam { + return self->orgnam; +} +- (NSArray *)orgunits { + return self->orgunits; +} + +/* fake being an array */ + +- (id)objectAtIndex:(unsigned)_idx { + NSString *s; + + if (_idx == 0) + return (s = [self orgnam]) ? s : (NSString *)[NSNull null]; + + return [self->orgunits objectAtIndex:(_idx - 1)]; +} +- (unsigned)count { + return 1 + [self->orgunits count]; +} + +/* values */ + +- (NSString *)stringValue { + return [self vCardString]; +} + +- (NSString *)xmlString { + NSMutableString *ms; + NSString *s; + unsigned i; + + ms = [[NSMutableString alloc] initWithCapacity:256]; + [self appendXMLTag:@"orgnam" value:[self orgnam] to:ms]; + + for (i = 0; i < [self->orgunits count]; i++) { + [self appendXMLTag:@"orgunit" value:[self->orgunits objectAtIndex:i] + to:ms]; + } + s = [[ms copy] autorelease]; + [ms release]; + return s; +} + +- (NSString *)vCardString { + NSMutableString *ms; + NSString *s; + unsigned i; + + ms = [[NSMutableString alloc] initWithCapacity:64]; + [self appendVCardValue:[self orgnam] to:ms]; + for (i = 0; i < [self->orgunits count]; i++) { + [ms appendString:@";"]; + [self appendVCardValue:[self->orgunits objectAtIndex:i] to:ms]; + } + s = [[ms copy] autorelease]; + [ms release]; + return s; +} + +- (NSDictionary *)asDictionary { + static NSString *keys[2] = { @"orgnam", @"orgunits" }; + id values[2]; + + values[0] = [self orgnam]; + values[1] = [self orgunits]; + + return [NSDictionary dictionaryWithObjects:values forKeys:keys + count:[self count]]; +} + +- (NSArray *)asArray { + id values[[self count] + 1]; + unsigned i; + + for (i = 0; i < [self count]; i++) + values[i] = [self objectAtIndex:i]; + + return [NSArray arrayWithObjects:values count:[self count]]; +} + +/* NSCoding */ + +- (void)encodeWithCoder:(NSCoder *)_coder { + [super encodeWithCoder:_coder]; + + [_coder encodeObject:self->orgnam]; + [_coder encodeObject:self->orgunits]; +} +- (id)initWithCoder:(NSCoder *)_coder { + if ((self = [super initWithCoder:_coder]) != nil) { + self->orgnam = [[_coder decodeObject] copy]; + self->orgunits = [[_coder decodeObject] copy]; + } + return self; +} + +/* description */ + +- (void)appendAttributesToDescription:(NSMutableString *)_ms { + [super appendAttributesToDescription:_ms]; +} + +@end /* NGVCardOrg */ diff --git a/sope-ical/NGiCal/NGVCardPhone.h b/sope-ical/NGiCal/NGVCardPhone.h new file mode 100644 index 00000000..922cc45e --- /dev/null +++ b/sope-ical/NGiCal/NGVCardPhone.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 2005 Helge Hess + + This file is part of SOPE. + + 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. + + 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. +*/ + +#ifndef __NGiCal_NGVCardPhone_H__ +#define __NGiCal_NGVCardPhone_H__ + +#include + +/* + NGVCardPhone + + Represents a phone value as transmitted by the 'tel' tag in vCard. +*/ + +@interface NGVCardPhone : NGVCardSimpleValue +@end + +#endif /* __NGiCal_NGVCardPhone_H__ */ diff --git a/sope-ical/NGiCal/NGVCardPhone.m b/sope-ical/NGiCal/NGVCardPhone.m index 2342feb2..1707609a 100644 --- a/sope-ical/NGiCal/NGVCardPhone.m +++ b/sope-ical/NGiCal/NGVCardPhone.m @@ -19,7 +19,7 @@ 02111-1307, USA. */ -#include "NGVCardValue.h" +#include "NGVCardPhone.h" #include "common.h" @implementation NGVCardPhone diff --git a/sope-ical/NGiCal/NGVCardSaxHandler.h b/sope-ical/NGiCal/NGVCardSaxHandler.h index 98fe3da2..bbfa2c87 100644 --- a/sope-ical/NGiCal/NGVCardSaxHandler.h +++ b/sope-ical/NGiCal/NGVCardSaxHandler.h @@ -32,26 +32,44 @@ */ @class NSString, NSMutableString, NSMutableArray; +@class NSDictionary, NSMutableDictionary; +@class NGVCard; @interface NGVCardSaxHandler : SaxDefaultHandler { NSMutableArray *vCards; - id vCard; + NGVCard *vCard; NSString *currentGroup; unichar *content; unsigned contentLength; + + NSMutableDictionary *xtags; + NSMutableDictionary *subvalues; + NSMutableArray *types; + NSMutableDictionary *args; + NSMutableArray *tel; + NSMutableArray *adr; + NSMutableArray *email; + NSMutableArray *label; + NSMutableArray *url; struct { int isInVCardSet:1; int isInVCard:1; int isInN:1; + int isInAdr:1; + int isInOrg:1; int isInGroup:1; int collectContent:1; - int reserved:27; + int reserved:25; } vcs; } +/* results */ + +- (NSArray *)vCards; + /* content */ - (void)startCollectingContent; diff --git a/sope-ical/NGiCal/NGVCardSaxHandler.m b/sope-ical/NGiCal/NGVCardSaxHandler.m index 71ccd1cf..1c0dd60d 100644 --- a/sope-ical/NGiCal/NGVCardSaxHandler.m +++ b/sope-ical/NGiCal/NGVCardSaxHandler.m @@ -20,24 +20,58 @@ */ #include "NGVCardSaxHandler.h" +#include "NGVCard.h" +#include "NGVCardValue.h" +#include "NGVCardSimpleValue.h" +#include "NGVCardAddress.h" +#include "NGVCardPhone.h" +#include "NGVCardName.h" +#include "NGVCardOrg.h" +#include "NGVCardCategories.h" #include "common.h" +#ifndef XMLNS_VCARD_XML_03 +# define XMLNS_VCARD_XML_03 \ + @"http://www.ietf.org/internet-drafts/draft-dawson-vcard-xml-dtd-03.txt" +#endif + @implementation NGVCardSaxHandler - (void)dealloc { if (self->content != NULL) free(self->content); + [self->subvalues release]; + [self->xtags release]; + [self->tel release]; + [self->adr release]; + [self->email release]; + [self->label release]; + [self->types release]; + [self->args release]; [self->vCards release]; [self->vCard release]; [self->currentGroup release]; [super dealloc]; } +/* results */ + +- (NSArray *)vCards { + return self->vCards; +} + /* state */ - (void)resetExceptResult { [self->currentGroup release]; self->currentGroup = nil; [self->vCard release]; self->vCard = nil; + [self->tel removeAllObjects]; + [self->adr removeAllObjects]; + [self->email removeAllObjects]; + [self->label removeAllObjects]; + [self->types removeAllObjects]; + [self->args removeAllObjects]; + if (self->content != NULL) { free(self->content); self->content = NULL; @@ -46,6 +80,8 @@ self->vcs.isInVCardSet = 0; self->vcs.isInVCard = 0; self->vcs.isInN = 0; + self->vcs.isInAdr = 0; + self->vcs.isInOrg = 0; self->vcs.isInGroup = 0; self->vcs.collectContent = 0; } @@ -59,13 +95,60 @@ - (void)startDocument { [self reset]; + if (self->vCards == nil) self->vCards = [[NSMutableArray alloc] initWithCapacity:16]; + + if (self->tel == nil) + self->tel = [[NSMutableArray alloc] initWithCapacity:8]; + if (self->adr == nil) + self->adr = [[NSMutableArray alloc] initWithCapacity:8]; + if (self->email == nil) + self->email = [[NSMutableArray alloc] initWithCapacity:8]; + if (self->label == nil) + self->label = [[NSMutableArray alloc] initWithCapacity:8]; + + if (self->types == nil) + self->types = [[NSMutableArray alloc] initWithCapacity:4]; + if (self->args == nil) + self->args = [[NSMutableDictionary alloc] initWithCapacity:8]; + + if (self->subvalues == nil) + self->subvalues = [[NSMutableDictionary alloc] initWithCapacity:16]; + if (self->xtags == nil) + self->xtags = [[NSMutableDictionary alloc] initWithCapacity:32]; } - (void)endDocument { [self resetExceptResult]; } +/* common tags */ + +- (void)startValueTag:(NSString *)_tag attributes:(id)_attrs { + unsigned i, count; + + [self->types removeAllObjects]; + [self->args removeAllObjects]; + + for (i = 0, count = [_attrs count]; i < count; i++) { + NSString *n, *v; + + n = [_attrs nameAtIndex:i]; + v = [_attrs valueAtIndex:i]; + + if ([n hasSuffix:@".type"] || [n isEqualToString:@"TYPE"]) { + if (![self->types containsObject:v]) + [self->types addObjectsFromArray:[v componentsSeparatedByString:@" "]]; + } + else + [self->args setObject:v forKey:n]; + } +} +- (void)endValueTag { + [self->types removeAllObjects]; + [self->args removeAllObjects]; +} + /* handle elements */ - (void)startGroup:(NSString *)_name { @@ -78,17 +161,96 @@ } - (void)startN { + [self->subvalues removeAllObjects]; self->vcs.isInN = 1; } - (void)endN { + NGVCardName *n; + self->vcs.isInN = 0; + + n = [[NGVCardName alloc] initWithPropertyList:self->subvalues + group:self->currentGroup + types:self->types arguments:self->args]; + NSLog(@"N: %@", n); + + [self->subvalues removeAllObjects]; + [n release]; +} + +- (void)startOrg { + [self->subvalues removeAllObjects]; + self->vcs.isInOrg = 1; +} +- (void)endOrg { + NGVCardOrg *o; + + self->vcs.isInOrg = 0; + + o = [[NGVCardOrg alloc] initWithGroup:self->currentGroup + types:self->types arguments:self->args]; + + NSLog(@"O: %@: %@", o, self->subvalues); + + [self->subvalues removeAllObjects]; } - (void)startVCard:(id)_attrs { + NSString *uid, *version; + NSString *t; + + [self->tel removeAllObjects]; + [self->adr removeAllObjects]; + [self->email removeAllObjects]; + [self->label removeAllObjects]; + [self->xtags removeAllObjects]; + self->vcs.isInVCard = 1; + if (self->vCard != nil) { + [self->vCards addObject:self->vCard]; + [self logWithFormat:@"ERROR: vCard nesting not supported!"]; + [self->vCard release]; self->vCard = nil; + } + + if ((uid = [_attrs valueForName:@"uid" uri:XMLNS_VCARD_XML_03]) == nil) + uid = [_attrs valueForName:@"X-ABUID" uri:XMLNS_VCARD_XML_03]; + + version = [_attrs valueForName:@"version" uri:XMLNS_VCARD_XML_03]; + + self->vCard = [[NGVCard alloc] initWithUid:uid version:version]; + + if ((t = [_attrs valueForName:@"class" uri:XMLNS_VCARD_XML_03]) != nil) + [self->vCard setVClass:t]; + if ((t = [_attrs valueForName:@"rev" uri:XMLNS_VCARD_XML_03]) != nil) { + [self logWithFormat:@"WARNING: vCard revision not yet supported!"]; + // TODO + } + if ((t = [_attrs valueForName:@"prodid" uri:XMLNS_VCARD_XML_03]) != nil) + [self->vCard setProdID:t]; + + [self debugWithFormat:@"started vCard: %@", self->vCard]; } - (void)endVCard { self->vcs.isInVCard = 0; + + /* fill collected objects */ + + if ([self->tel count] > 0) [self->vCard setTel:self->tel]; + if ([self->adr count] > 0) [self->vCard setAdr:self->adr]; + if ([self->email count] > 0) [self->vCard setEmail:self->email]; + if ([self->label count] > 0) [self->vCard setLabel:self->label]; + if ([self->xtags count] > 0) [self->vCard setX:self->xtags]; + [self->tel removeAllObjects]; + [self->adr removeAllObjects]; + [self->email removeAllObjects]; + [self->label removeAllObjects]; + [self->xtags removeAllObjects]; + + /* finish vCard, add to results */ + + [self debugWithFormat:@"finished vCard: %@", self->vCard]; + [self->vCards addObject:self->vCard]; + [self->vCard release]; self->vCard = nil; } - (void)startVCardSet:(id)_attrs { @@ -98,6 +260,144 @@ self->vcs.isInVCardSet = 0; } +- (void)endBaseContentTagWithClass:(Class)_clazz andAddTo:(NSMutableArray*)_a { + NGVCardSimpleValue *v; + + v = [[_clazz alloc] initWithValue:[self finishCollectingContent] + group:self->currentGroup + types:self->types arguments:self->args]; + [_a addObject:v]; + + [self endValueTag]; + [v release]; +} + +- (void)startTel:(id)_attrs { + [self startValueTag:@"tel" attributes:_attrs]; + [self startCollectingContent]; +} +- (void)endTel { + [self endBaseContentTagWithClass:[NGVCardPhone class] andAddTo:self->tel]; +} + +- (void)startAdr:(id)_attrs { + [self->subvalues removeAllObjects]; + + self->vcs.isInAdr = 1; + [self startValueTag:@"adr" attributes:_attrs]; +} +- (void)endAdr { + NGVCardAddress *address; + + self->vcs.isInAdr = 0; + + address = [[NGVCardAddress alloc] initWithPropertyList:self->subvalues + group:self->currentGroup + types:self->types arguments:self->args]; + NSLog(@"A: %@", address); + [self->adr addObject:address]; + + [self->subvalues removeAllObjects]; + [self endValueTag]; + [address release]; +} + +- (void)startEmail:(id)_attrs { + [self startValueTag:@"email" attributes:_attrs]; + [self startCollectingContent]; +} +- (void)endEmail { + [self endBaseContentTagWithClass:[NGVCardSimpleValue class] + andAddTo:self->email]; +} + +- (void)startLabel:(id)_attrs { + [self startValueTag:@"LABEL" attributes:_attrs]; + [self startCollectingContent]; +} +- (void)endLabel { + [self endBaseContentTagWithClass:[NGVCardSimpleValue class] + andAddTo:self->label]; +} + +- (void)startURL:(id)_attrs { + [self startValueTag:@"url" attributes:_attrs]; + [self startCollectingContent]; +} +- (void)endURL { + // TODO: use special URL class? + [self endBaseContentTagWithClass:[NGVCardSimpleValue class] + andAddTo:self->url]; +} + +- (void)startSubContentTag:(id)_attrs { + if ([_attrs count] > 0) + [self logWithFormat:@"WARNING: loosing attrs of subtag: %@", _attrs]; + + [self startCollectingContent]; +} +- (void)endSubContentTag:(NSString *)_key { + NSString *s; + id o; + + if ((s = [[self finishCollectingContent] copy]) == nil) + return; + + if ((o = [self->subvalues objectForKey:_key]) == nil) { + [self->subvalues setObject:s forKey:_key]; + } + else { + /* multivalue (eg 'org') */ + if ([o isKindOfClass:[NSMutableArray class]]) { + [o addObject:s]; + } + else { + NSMutableArray *a; + + a = [[NSMutableArray alloc] initWithCapacity:4]; + [a addObject:o]; + [a addObject:s]; + [self->subvalues setObject:a forKey:_key]; + [a release]; a = nil; + } + } + [s release]; +} + + +- (void)startX:(NSString *)_name attributes:(id)_attrs { + [self startValueTag:_name attributes:_attrs]; + [self startCollectingContent]; +} +- (void)endX:(NSString *)_name { + NGVCardSimpleValue *v; + NSString *s; + id o; + + s = [self finishCollectingContent]; + v = [[NGVCardSimpleValue alloc] initWithValue:s + group:self->currentGroup + types:self->types arguments:self->args]; + + if ((o = [self->xtags objectForKey:_name]) == nil) + [self->xtags setObject:v forKey:_name]; + else if ([o isKindOfClass:[NSMutableArray class]]) + [o addObject:v]; + else { + NSMutableArray *a; + + a = [[NSMutableArray alloc] initWithCapacity:4]; + [a addObject:o]; + [a addObject:v]; + [self->xtags setObject:a forKey:_name]; + [a release]; + } + + [v release]; + [self endValueTag]; +} + + /* element events */ - (void)startElement:(NSString *)_localName @@ -105,18 +405,35 @@ rawName:(NSString *)_rawName attributes:(id)_attrs { - if ([_localName isEqualToString:@"group"]) + unichar c0 = [_localName characterAtIndex:0]; + + if (c0 == 'g' && [_localName isEqualToString:@"group"]) [self startGroup:[_attrs valueForName:@"name" uri:_ns]]; - else if ([_localName isEqualToString:@"n"]) + else if (c0 == 'n' && [_localName length] == 1) [self startN]; - else if ([_localName isEqualToString:@"tel"]) - ; - else if ([_localName isEqualToString:@"vCard"]) + else if (c0 == 'o' && [_localName isEqualToString:@"org"]) + [self startOrg]; + else if (c0 == 't' && [_localName isEqualToString:@"tel"]) + [self startTel:_attrs]; + else if (c0 == 'u' && [_localName isEqualToString:@"url"]) + [self startURL:_attrs]; + else if (c0 == 'a' && [_localName isEqualToString:@"adr"]) + [self startAdr:_attrs]; + else if (c0 == 'e' && [_localName isEqualToString:@"email"]) + [self startEmail:_attrs]; + else if (c0 == 'L' && [_localName isEqualToString:@"LABEL"]) + [self startLabel:_attrs]; + else if (c0 == 'v' && [_localName isEqualToString:@"vCard"]) [self startVCard:_attrs]; - else if ([_localName isEqualToString:@"vCardSet"]) + else if (c0 == 'v' && [_localName isEqualToString:@"vCardSet"]) [self startVCardSet:_attrs]; - - if (self->vcs.isInN) { + else { + if (self->vcs.isInN || self->vcs.isInOrg || self->vcs.isInAdr) + [self startSubContentTag:_attrs]; + else if (c0 == 'X') + [self startX:_localName attributes:_attrs]; + else + NSLog(@"U: %@", _localName); } } @@ -124,19 +441,34 @@ namespace:(NSString *)_ns rawName:(NSString *)_rawName { - if (self->vcs.isInN) { - } - - if ([_localName isEqualToString:@"group"]) + unichar c0 = [_localName characterAtIndex:0]; + + if (c0 == 'g' && [_localName isEqualToString:@"group"]) [self endGroup]; - else if ([_localName isEqualToString:@"n"]) + else if (c0 == 'n' && [_localName isEqualToString:@"n"]) [self endN]; - else if ([_localName isEqualToString:@"tel"]) - ; - else if ([_localName isEqualToString:@"vCard"]) + else if (c0 == 'o' && [_localName isEqualToString:@"org"]) + [self endOrg]; + else if (c0 == 't' && [_localName isEqualToString:@"tel"]) + [self endTel]; + else if (c0 == 'u' && [_localName isEqualToString:@"url"]) + [self endURL]; + else if (c0 == 'a' && [_localName isEqualToString:@"adr"]) + [self endAdr]; + else if (c0 == 'e' && [_localName isEqualToString:@"email"]) + [self endEmail]; + else if (c0 == 'L' && [_localName isEqualToString:@"LABEL"]) + [self endLabel]; + else if (c0 == 'v' && [_localName isEqualToString:@"vCard"]) [self endVCard]; - else if ([_localName isEqualToString:@"vCardSet"]) + else if (c0 == 'v' && [_localName isEqualToString:@"vCardSet"]) [self endVCardSet]; + else { + if (self->vcs.isInN || self->vcs.isInOrg || self->vcs.isInAdr) + [self endSubContentTag:_localName]; + else if (c0 == 'X') + [self endX:_localName]; + } } /* content */ diff --git a/sope-ical/NGiCal/NGVCardSimpleValue.h b/sope-ical/NGiCal/NGVCardSimpleValue.h new file mode 100644 index 00000000..6465a1de --- /dev/null +++ b/sope-ical/NGiCal/NGVCardSimpleValue.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2005 Helge Hess + + This file is part of SOPE. + + 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. + + 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. +*/ + +#ifndef __NGiCal_NGVCardSimpleValue_H__ +#define __NGiCal_NGVCardSimpleValue_H__ + +#include + +#import + +/* + NGVCardSimpleValue + + An object to represent simple vCard string values. +*/ + +@interface NGVCardSimpleValue : NGVCardValue +{ + NSString *value; +} + +- (id)initWithValue:(NSString *)_value group:(NSString *)_group + types:(NSArray *)_types arguments:(NSDictionary *)_args; + +/* fake being an NSString */ + +- (unsigned int)length; +- (unichar)characterAtIndex:(unsigned)_idx; + +@end + +#endif /* __NGiCal_NGVCardSimpleValue_H__ */ diff --git a/sope-ical/NGiCal/NGVCardSimpleValue.m b/sope-ical/NGiCal/NGVCardSimpleValue.m index f4505ecb..05fcc077 100644 --- a/sope-ical/NGiCal/NGVCardSimpleValue.m +++ b/sope-ical/NGiCal/NGVCardSimpleValue.m @@ -19,11 +19,29 @@ 02111-1307, USA. */ -#include "NGVCardValue.h" +#include "NGVCardSimpleValue.h" #include "common.h" @implementation NGVCardSimpleValue +- (id)initWithValue:(NSString *)_value group:(NSString *)_group + types:(NSArray *)_types arguments:(NSDictionary *)_a +{ + if ((self = [super initWithGroup:_group types:_types arguments:_a]) != nil) { + self->value = [_value copy]; + } + return self; +} + +- (id)initWithGroup:(NSString *)_group types:(NSArray *)_types + arguments:(NSDictionary *)_a +{ + return [self initWithValue:nil group:_group types:_types arguments:_a]; +} +- (id)init { + return [self initWithValue:nil group:nil types:nil arguments:nil]; +} + - (void)dealloc { [self->value release]; [super dealloc]; @@ -61,4 +79,11 @@ return self; } +/* description */ + +- (void)appendAttributesToDescription:(NSMutableString *)_ms { + if (self->value != nil) [_ms appendFormat:@" value='%@'", self->value]; + [super appendAttributesToDescription:_ms]; +} + @end /* NGVCardSimpleValue */ diff --git a/sope-ical/NGiCal/NGVCardValue.h b/sope-ical/NGiCal/NGVCardValue.h index bd5fbed9..89727c10 100644 --- a/sope-ical/NGiCal/NGVCardValue.h +++ b/sope-ical/NGiCal/NGVCardValue.h @@ -27,7 +27,7 @@ /* NGVCardValue - Represents a value in a vCard object. + An abstract superclass to represents a value in a vCard object. Note: all NGVCardValue's are treated as immutable objects. @@ -44,6 +44,9 @@ NSDictionary *arguments; } +- (id)initWithGroup:(NSString *)_group types:(NSArray *)_types + arguments:(NSDictionary *)_a; + /* accessors */ - (NSString *)group; @@ -64,33 +67,9 @@ to:(NSMutableString *)_ms; - (void)appendVCardValue:(NSString *)_val to:(NSMutableString *)_ms; -@end - -#import - -@interface NGVCardSimpleValue : NGVCardValue -{ - NSString *value; -} - -/* fake being an NSString */ - -- (unsigned int)length; -- (unichar)characterAtIndex:(unsigned)_idx; - -@end - -@interface NGVCardPhone : NGVCardSimpleValue -@end - -@interface NGVCardCategories : NGVCardValue -{ - NSArray *categories; -} - -/* accessors */ +/* description */ -- (NSArray *)categories; +- (void)appendAttributesToDescription:(NSMutableString *)_ms; @end diff --git a/sope-ical/NGiCal/NGVCardValue.m b/sope-ical/NGiCal/NGVCardValue.m index dd4457b9..b5476a8e 100644 --- a/sope-ical/NGiCal/NGVCardValue.m +++ b/sope-ical/NGiCal/NGVCardValue.m @@ -25,6 +25,20 @@ @implementation NGVCardValue +- (id)initWithGroup:(NSString *)_group types:(NSArray *)_types + arguments:(NSDictionary *)_a +{ + if ((self = [super init]) != nil) { + self->group = [_group copy]; + self->types = [_types copy]; + self->arguments = [_a copy]; + } + return self; +} +- (id)init { + return [self initWithGroup:nil types:nil arguments:nil]; +} + - (void)dealloc { [self->group release]; [self->types release]; @@ -108,4 +122,41 @@ return self; } +/* description */ + +- (void)appendDictionary:(NSDictionary *)_d compactTo:(NSMutableString *)_s { + NSEnumerator *keys; + NSString *k; + + keys = [_d keyEnumerator]; + while ((k = [keys nextObject]) != nil) { + NSString *v; + + v = [_d objectForKey:k]; + [_s appendFormat:@"%@='%@';", k, v]; + } +} + +- (void)appendAttributesToDescription:(NSMutableString *)_ms { + if (self->group != nil) [_ms appendFormat:@" group='%@'", self->group]; + if ([self->types count] > 0) { + [_ms appendFormat:@" types=%@", + [self->types componentsJoinedByString:@","]]; + } + if ([self->arguments count] > 0) { + [_ms appendString:@" args="]; + [self appendDictionary:self->arguments compactTo:_ms]; + } +} + +- (NSString *)description { + NSMutableString *str = nil; + + str = [NSMutableString stringWithCapacity:64]; + [str appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])]; + [self appendAttributesToDescription:str]; + [str appendString:@">"]; + return str; +} + @end /* NGVCardValue */ diff --git a/sope-ical/NGiCal/Version b/sope-ical/NGiCal/Version index 3a758962..d2b964f0 100644 --- a/sope-ical/NGiCal/Version +++ b/sope-ical/NGiCal/Version @@ -2,7 +2,7 @@ MAJOR_VERSION=4 MINOR_VERSION=5 -SUBMINOR_VERSION:=52 +SUBMINOR_VERSION:=53 # v4.5.40 requires NGExtensions v4.5.145 # v4.5.37 requires NGExtensions v4.5.140 diff --git a/sope-ical/samples/GNUmakefile b/sope-ical/samples/GNUmakefile index e26d78bd..c3a3fbef 100644 --- a/sope-ical/samples/GNUmakefile +++ b/sope-ical/samples/GNUmakefile @@ -3,15 +3,17 @@ -include ../../config.make include $(GNUSTEP_MAKEFILES)/common.make -TOOL_NAME = icalparsetest icalds vcf2xml +TOOL_NAME = icalparsetest icalds vcf2xml vcfparsetest icalparsetest_OBJC_FILES = icalparsetest.m icalds_OBJC_FILES = icalds.m vcf2xml_OBJC_FILES = vcf2xml.m +vcfparsetest_OBJC_FILES = vcfparsetest.m icalparsetest_TOOL_LIBS += -lNGiCal -lSaxObjC -icalds_TOOL_LIBS += -lNGiCal -lSaxObjC -vcf2xml_TOOL_LIBS += -lSaxObjC +icalds_TOOL_LIBS += -lNGiCal -lSaxObjC +vcf2xml_TOOL_LIBS += -lSaxObjC +vcfparsetest_TOOL_LIBS += -lNGiCal -lSaxObjC -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/tool.make diff --git a/sope-ical/samples/vcfparsetest.m b/sope-ical/samples/vcfparsetest.m new file mode 100644 index 00000000..26289af2 --- /dev/null +++ b/sope-ical/samples/vcfparsetest.m @@ -0,0 +1,126 @@ +/* + Copyright (C) 2005 Helge Hess + + This file is part of SOPE. + + 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. + + 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. +*/ + +#import + +@interface vcsparsetest : NSObject +{ +} + +- (int)runWithArguments:(NSArray *)_args; + +@end + +#include + +@implementation vcsparsetest + +- (id)init { + if ((self = [super init])) { + } + return self; +} +- (void)dealloc { + [super dealloc]; +} + +/* parsing */ + +- (id)parseFile:(NSString *)_path { + if ([_path length] == 0) return nil; + return [NGVCard parseVCardsFromSource:[NSURL fileURLWithPath:_path]]; +} + +- (void)printParsedObject:(NSArray *)_cards { + NSLog(@"cards: %@", _cards); + +#if 0 + NSLog(@" subcomponents: %@", [_object subComponents]); + + printf("%s", [[_object icalString] cString]); +#endif +} + +/* run */ + +- (int)runWithArguments:(NSArray *)_args { + NSEnumerator *args; + NSString *arg; + + args = [_args objectEnumerator]; + [args nextObject]; // process name ... + + while ((arg = [args nextObject])) { + NSAutoreleasePool *pool2; + + if ([arg hasPrefix:@"-"]) { /* consume defaults */ + [args nextObject]; + continue; + } + + pool2 = [[NSAutoreleasePool alloc] init]; + { + NSArray *cards; + + NS_DURING + cards = [self parseFile:arg]; + NS_HANDLER + abort(); + NS_ENDHANDLER; + + if (cards == nil) + NSLog(@"could not parse file: '%@'", arg); + else + [self printParsedObject:cards]; + } + [pool2 release]; + } + return 0; +} + +@end /* vcsparsetest */ + +int main(int argc, char **argv, char **env) { + NSAutoreleasePool *pool; + vcsparsetest *tool; + int rc; + +#if LIB_FOUNDATION_LIBRARY + [NSProcessInfo initializeWithArguments:argv count:argc environment:env]; +#endif + + pool = [[NSAutoreleasePool alloc] init]; + + if ((tool = [[vcsparsetest alloc] init])) { + NS_DURING + rc = [tool runWithArguments:[[NSProcessInfo processInfo] arguments]]; + NS_HANDLER + abort(); + NS_ENDHANDLER; + + [tool release]; + } + else + rc = 1; + + [pool release]; + return rc; +} -- 2.39.5