2005-05-08 Helge Hess <helge.hess@opengroupware.org>
+ * more work on vCard parsing (v4.5.53)
+
* work on vCard objects (incomplete) (v4.5.52)
2005-04-25 Helge Hess <helge.hess@opengroupware.org>
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 \
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
NGVCard
Represents a vCard object.
+
+ XML DTD in Dawson-03 Draft:
+ <!ELEMENT vCard (%prop.man;, (%prop.opt;)*)>
+
+ <!ATTLIST vCard
+ %attr.lang;
+ xmlns CDATA #FIXED
+ 'http://www.ietf.org/internet-drafts/draft-dawson-vcard-xml-dtd-02.txt'
+ xmlns:vcf CDATA #FIXED
+ 'http://www.ietf.org/internet-drafts/draft-dawson-vcard-xml-dtd-02.txt'
+ version CDATA #REQUIRED
+ rev CDATA #IMPLIED
+ uid CDATA #IMPLIED
+ prodid CDATA #IMPLIED
+ class (PUBLIC | PRIVATE | CONFIDENTIAL) "PUBLIC"
+ value NOTATION (VCARD) #IMPLIED>
+ <!-- version - Must be "3.0" if document conforms to this spec -->
+ <!-- rev - ISO 8601 formatted date or date/time string -->
+ <!-- uid - UID associated with the object described by the vCard -->
+ <!-- prodid - ISO 9070 FPI for product that generated vCard -->
+ <!-- class - Security classification for vCard information -->
+
+ 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__ */
*/
#include "NGVCard.h"
+#include "NGVCardSaxHandler.h"
+#include <SaxObjC/SaxXMLReader.h>
+#include <SaxObjC/SaxXMLReaderFactory.h>
#include "common.h"
@implementation NGVCard
+static id<NSObject,SaxXMLReader> parser = nil; // THREAD
+static NGVCardSaxHandler *sax = nil; // THREAD
+
++ (id<NSObject,SaxXMLReader>)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<NSObject,SaxXMLReader> 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 */
NSString *country;
}
+- (id)initWithPropertyList:(id)_plist group:(NSString *)_group
+ types:(NSArray *)_types arguments:(NSDictionary *)_args;
+
/* accessors */
- (NSString *)pobox;
@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];
return self;
}
+/* description */
+
+- (void)appendAttributesToDescription:(NSMutableString *)_ms {
+ [super appendAttributesToDescription:_ms];
+ [_ms appendFormat:@" vcard=%@", [self vCardString]];
+}
+
@end /* NGVCardAddress */
--- /dev/null
+/*
+ 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 <NGiCal/NGVCardValue.h>
+
+/*
+ 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__ */
02111-1307, USA.
*/
-#include "NGVCardValue.h"
+#include "NGVCardCategories.h"
#include "common.h"
@implementation NGVCardCategories
return [self categories];
}
+- (NSArray *)asArray {
+ return self->categories;
+}
+
/* fake being an array */
- (id)objectAtIndex:(unsigned)_idx {
return self;
}
+/* description */
+
+- (void)appendAttributesToDescription:(NSMutableString *)_ms {
+ [super appendAttributesToDescription:_ms];
+ [_ms appendFormat:@" vcard=%@", [self vCardString]];
+}
+
@end /* NGVCardCategories */
@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];
return self;
}
+/* description */
+
+- (void)appendAttributesToDescription:(NSMutableString *)_ms {
+ [super appendAttributesToDescription:_ms];
+ [_ms appendFormat:@" vcard=%@", [self vCardString]];
+}
+
@end /* NGVCardName */
--- /dev/null
+/*
+ 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 <NGiCal/NGVCardValue.h>
+
+@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__ */
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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 <NGiCal/NGVCardSimpleValue.h>
+
+/*
+ NGVCardPhone
+
+ Represents a phone value as transmitted by the 'tel' tag in vCard.
+*/
+
+@interface NGVCardPhone : NGVCardSimpleValue
+@end
+
+#endif /* __NGiCal_NGVCardPhone_H__ */
02111-1307, USA.
*/
-#include "NGVCardValue.h"
+#include "NGVCardPhone.h"
#include "common.h"
@implementation NGVCardPhone
*/
@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;
*/
#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;
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;
}
- (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<SaxAttributes>)_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 {
}
- (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<SaxAttributes>)_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<SaxAttributes>)_attrs {
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<SaxAttributes>)_attrs {
+ [self startValueTag:@"tel" attributes:_attrs];
+ [self startCollectingContent];
+}
+- (void)endTel {
+ [self endBaseContentTagWithClass:[NGVCardPhone class] andAddTo:self->tel];
+}
+
+- (void)startAdr:(id<SaxAttributes>)_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<SaxAttributes>)_attrs {
+ [self startValueTag:@"email" attributes:_attrs];
+ [self startCollectingContent];
+}
+- (void)endEmail {
+ [self endBaseContentTagWithClass:[NGVCardSimpleValue class]
+ andAddTo:self->email];
+}
+
+- (void)startLabel:(id<SaxAttributes>)_attrs {
+ [self startValueTag:@"LABEL" attributes:_attrs];
+ [self startCollectingContent];
+}
+- (void)endLabel {
+ [self endBaseContentTagWithClass:[NGVCardSimpleValue class]
+ andAddTo:self->label];
+}
+
+- (void)startURL:(id<SaxAttributes>)_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<SaxAttributes>)_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<SaxAttributes>)_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
rawName:(NSString *)_rawName
attributes:(id<SaxAttributes>)_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);
}
}
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 */
--- /dev/null
+/*
+ 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 <NGiCal/NGVCardValue.h>
+
+#import <Foundation/NSString.h>
+
+/*
+ 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__ */
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];
return self;
}
+/* description */
+
+- (void)appendAttributesToDescription:(NSMutableString *)_ms {
+ if (self->value != nil) [_ms appendFormat:@" value='%@'", self->value];
+ [super appendAttributesToDescription:_ms];
+}
+
@end /* NGVCardSimpleValue */
/*
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.
NSDictionary *arguments;
}
+- (id)initWithGroup:(NSString *)_group types:(NSArray *)_types
+ arguments:(NSDictionary *)_a;
+
/* accessors */
- (NSString *)group;
to:(NSMutableString *)_ms;
- (void)appendVCardValue:(NSString *)_val to:(NSMutableString *)_ms;
-@end
-
-#import <Foundation/NSString.h>
-
-@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
@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];
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 */
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
-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
--- /dev/null
+/*
+ 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 <Foundation/Foundation.h>
+
+@interface vcsparsetest : NSObject
+{
+}
+
+- (int)runWithArguments:(NSArray *)_args;
+
+@end
+
+#include <NGiCal/NGVCard.h>
+
+@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;
+}