diff --git a/SoObjects/Contacts/GNUmakefile b/SoObjects/Contacts/GNUmakefile index dd0ae6daa..b452a4176 100644 --- a/SoObjects/Contacts/GNUmakefile +++ b/SoObjects/Contacts/GNUmakefile @@ -12,6 +12,7 @@ Contacts_OBJC_FILES = \ SOGoFolder+CardDAV.m \ SOGoContactFolders.m \ SOGoContactGCSEntry.m \ + SOGoContactGCSList.m \ SOGoContactGCSFolder.m \ SOGoContactLDIFEntry.m \ SOGoContactLDAPFolder.m \ diff --git a/SoObjects/Contacts/SOGoContactGCSEntry.h b/SoObjects/Contacts/SOGoContactGCSEntry.h index 4ebfeac33..fe9b62e06 100644 --- a/SoObjects/Contacts/SOGoContactGCSEntry.h +++ b/SoObjects/Contacts/SOGoContactGCSEntry.h @@ -29,7 +29,8 @@ @class NGVCard; -@interface SOGoContactGCSEntry : SOGoContentObject +@interface SOGoContactGCSEntry + : SOGoContentObject { NGVCard *card; } diff --git a/SoObjects/Contacts/SOGoContactGCSFolder.m b/SoObjects/Contacts/SOGoContactGCSFolder.m index eff8313e9..0c285bae3 100644 --- a/SoObjects/Contacts/SOGoContactGCSFolder.m +++ b/SoObjects/Contacts/SOGoContactGCSFolder.m @@ -29,12 +29,19 @@ #import #import #import +#import #import #import #import -#import +#import +#import +#import +#import + #import "SOGoContactGCSEntry.h" +#import "SOGoContactGCSList.h" + #import "SOGoContactGCSFolder.h" #define folderListingFields [NSArray arrayWithObjects: @"c_name", @"c_cn", \ @@ -59,29 +66,149 @@ return contact; } -- (id) lookupName: (NSString *) _key - inContext: (WOContext *) _ctx - acquire: (BOOL) _flag +- (Class) objectClassForContent: (NSString *) content +{ + CardGroup *cardEntry; + NSString *firstTag; + Class objectClass; + + objectClass = Nil; + + cardEntry = [CardGroup parseSingleFromSource: content]; + if (cardEntry) + { + firstTag = [[cardEntry tag] uppercaseString]; + if ([firstTag isEqualToString: @"VCARD"]) + objectClass = [SOGoContactGCSEntry class]; + else if ([firstTag isEqualToString: @"VLIST"]) + objectClass = [SOGoContactGCSList class]; + } + + return objectClass; +} + +- (Class) objectClassForResourceNamed: (NSString *) name +{ + EOQualifier *qualifier; + NSArray *records; + NSString *component; + Class objectClass; + + qualifier = [EOQualifier qualifierWithQualifierFormat:@"c_name = %@", name]; + records = [[self ocsFolder] fetchFields: [NSArray arrayWithObject: @"c_component"] + matchingQualifier: qualifier]; + + if ([records count]) + { + component = [[records objectAtIndex: 0] valueForKey: @"c_component"]; + if ([component isEqualToString: @"vcard"]) + objectClass = [SOGoContactGCSEntry class]; + else if ([component isEqualToString: @"vlist"]) + objectClass = [SOGoContactGCSList class]; + else + objectClass = Nil; + } + else + objectClass = Nil; + + return objectClass; +} + +- (id) deduceObjectForName: (NSString *)_key + inContext: (id)_ctx +{ + WORequest *request; + NSString *method; + Class objectClass; + id obj; + + request = [_ctx request]; + method = [request method]; + if ([method isEqualToString: @"PUT"]) + objectClass = [self objectClassForContent: [request contentAsString]]; + else + objectClass = [self objectClassForResourceNamed: _key]; + + if (objectClass) + obj = [objectClass objectWithName: _key inContainer: self]; + else + obj = nil; + + return obj; +} + +- (BOOL) requestNamedIsHandledLater: (NSString *) name +{ + return [name isEqualToString: @"OPTIONS"]; +} + +- (id) lookupName: (NSString *)_key + inContext: (id)_ctx + acquire: (BOOL)_flag { id obj; - BOOL isPut; + NSString *url; + BOOL handledLater; - isPut = NO; - obj = [super lookupName:_key inContext:_ctx acquire:NO]; - - if (!obj) + /* first check attributes directly bound to the application */ + handledLater = [self requestNamedIsHandledLater: _key]; + if (handledLater) + obj = nil; + else { - if ([[[_ctx request] method] isEqualToString: @"PUT"]) - { - if ([_key isEqualToString: @"PUT"]) - isPut = YES; - else - obj = [SOGoContactGCSEntry objectWithName: _key - inContainer: self]; - } - else - obj = [self lookupContactWithId: _key]; + obj = [super lookupName:_key inContext:_ctx acquire:NO]; + if (!obj) + { + if ([self isValidContentName: _key]) + { + url = [[[_ctx request] uri] urlWithoutParameters]; + if ([url hasSuffix: @"AsContact"]) + obj = [SOGoContactGCSEntry objectWithName: _key + inContainer: self]; + else if ([url hasSuffix: @"AsList"]) + obj = [SOGoContactGCSList objectWithName: _key + inContainer: self]; + else + obj = [self deduceObjectForName: _key + inContext: _ctx]; + } + } + if (!obj) + obj = [NSException exceptionWithHTTPStatus:404 /* Not Found */]; } + + if (obj) + [[SOGoCache sharedCache] registerObject: obj + withName: _key + inContainer: container]; + + return obj; +} + +// - (id) lookupName: (NSString *) _key +// inContext: (WOContext *) _ctx +// acquire: (BOOL) _flag +// { +// id obj; +// BOOL isPut; + +// isPut = NO; +// obj = [super lookupName:_key inContext:_ctx acquire:NO]; + +// if (!obj) +// { +// if ([[[_ctx request] method] isEqualToString: @"PUT"]) +// { +// if ([_key isEqualToString: @"PUT"]) +// isPut = YES; +// else + +// obj = [SOGoContactGCSEntry objectWithName: _key +// inContainer: self]; +// } +// else +// obj = [self lookupContactWithId: _key]; +// } // if (!(obj || isPut)) // obj = [NSException exceptionWithHTTPStatus:404 /* Not Found */]; @@ -91,9 +218,9 @@ // return [self contactWithName:_key inContext:_ctx]; // } - /* return 404 to stop acquisition */ - return obj; -} +// /* return 404 to stop acquisition */ +// return obj; +// } /* fetching */ - (EOQualifier *) _qualifierForFilter: (NSString *) filter @@ -280,7 +407,6 @@ cardDavCollection = [NSArray arrayWithObjects: @"addressbook", @"urn:ietf:params:xml:ns:carddav", nil]; - resourceType = [NSMutableArray arrayWithArray: [super davResourceType]]; [resourceType addObject: cardDavCollection]; diff --git a/SoObjects/Contacts/SOGoContactGCSList.h b/SoObjects/Contacts/SOGoContactGCSList.h new file mode 100644 index 000000000..5e3cc164d --- /dev/null +++ b/SoObjects/Contacts/SOGoContactGCSList.h @@ -0,0 +1,37 @@ +/* SOGoContactGCSList.h - this file is part of SOGo + * + * Copyright (C) 2008 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef SOGOCONTACTGCSLIST_H +#define SOGOCONTACTGCSLIST_H + +#import + +@class NGVList; + +@interface SOGoContactGCSList : SOGoContentObject +{ + NGVList *list; +} + +@end + +#endif /* SOGOCONTACTGCSLIST_H */ diff --git a/SoObjects/Contacts/SOGoContactGCSList.m b/SoObjects/Contacts/SOGoContactGCSList.m new file mode 100644 index 000000000..2534fc6d2 --- /dev/null +++ b/SoObjects/Contacts/SOGoContactGCSList.m @@ -0,0 +1,92 @@ +/* SOGoContactGCSList.m - this file is part of SOGo + * + * Copyright (C) 2008 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import + +#import + +#import "SOGoContactGCSList.h" + +@implementation SOGoContactGCSList + +- (id) init +{ + if ((self = [super init])) + { + list = nil; + } + + return self; +} + +- (void) dealloc +{ + [list release]; + [super dealloc]; +} + +/* content */ + +- (NGVList *) vList +{ + NSString *content; + + if (!list) + { + content = [record objectForKey: @"c_content"]; + if ([[content uppercaseString] hasPrefix: @"BEGIN:VLIST"]) + list = [NGVList parseSingleFromSource: content]; + else + list = [NGVList listWithUid: [self nameInContainer]]; + [list retain]; + } + + return list; +} + +/* DAV */ + +- (NSString *) davContentType +{ + return @"text/x-vlist"; +} + +/* specialized actions */ + +- (void) save +{ + NGVList *vlist; + + vlist = [self vList]; + + [self saveContentString: [vlist versitString]]; +} + +/* message type */ + +- (NSString *) outlookMessageClass +{ + return @"IPM.Contact"; +} + +@end diff --git a/SoObjects/Contacts/product.plist b/SoObjects/Contacts/product.plist index f30359029..dd5dcd410 100644 --- a/SoObjects/Contacts/product.plist +++ b/SoObjects/Contacts/product.plist @@ -17,6 +17,9 @@ SOGoContactGCSEntry = { superclass = "SOGoContentObject"; }; + SOGoContactGCSList = { + superclass = "SOGoContentObject"; + }; SOGoContactLDAPFolder = { superclass = "SOGoGCSFolder"; protectedBy = "Access Contents Information";