From dd0bea0dc9ecc5c7a82d86d43ff3a99bd279aefe Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Thu, 24 Feb 2011 20:32:27 +0000 Subject: [PATCH] Monotone-Parent: 17790db0c2368364683e4074a491e7107c6cf071 Monotone-Revision: 96b5a2580e3b0b6ba57af91d0fed6f513f8e13f0 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2011-02-24T20:32:27 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 7 +- OpenChange/MAPIStoreCalendarContext.m | 129 +- OpenChange/MAPIStoreCalendarFolder.h | 32 + OpenChange/MAPIStoreCalendarFolder.m | 124 ++ OpenChange/MAPIStoreContactsContext.m | 55 +- OpenChange/MAPIStoreContactsFolder.h | 32 + OpenChange/MAPIStoreContactsFolder.m | 126 ++ OpenChange/MAPIStoreContext.h | 47 +- OpenChange/MAPIStoreContext.m | 1063 ++++++----------- OpenChange/MAPIStoreDeletedItemsContext.h | 4 +- OpenChange/MAPIStoreDeletedItemsContext.m | 45 +- OpenChange/MAPIStoreDraftsContext.h | 4 +- OpenChange/MAPIStoreDraftsContext.m | 56 +- OpenChange/MAPIStoreFSBaseContext.m | 32 +- OpenChange/MAPIStoreFSFolder.h | 33 + OpenChange/MAPIStoreFSFolder.m | 128 ++ OpenChange/MAPIStoreFolder.h | 84 ++ OpenChange/MAPIStoreFolder.m | 356 ++++++ OpenChange/MAPIStoreFreebusyContext.m | 24 +- OpenChange/MAPIStoreGCSFolder.h | 35 + OpenChange/MAPIStoreGCSFolder.m | 82 ++ OpenChange/MAPIStoreInboxContext.h | 32 + OpenChange/MAPIStoreInboxContext.m | 50 + ...ilContext.h => MAPIStoreMailBaseContext.h} | 4 +- OpenChange/MAPIStoreMailBaseContext.m | 32 + OpenChange/MAPIStoreMailContext.m | 159 --- OpenChange/MAPIStoreMailFolder.h | 57 + OpenChange/MAPIStoreMailFolder.m | 306 +++++ OpenChange/MAPIStoreNotesContext.m | 8 +- OpenChange/MAPIStoreNotesFolder.h | 31 + OpenChange/MAPIStoreNotesFolder.m | 43 + OpenChange/MAPIStoreOutboxContext.h | 4 +- OpenChange/MAPIStoreOutboxContext.m | 92 +- OpenChange/MAPIStoreSentItemsContext.h | 4 +- OpenChange/MAPIStoreSentItemsContext.m | 47 +- OpenChange/MAPIStoreTasksContext.m | 69 +- OpenChange/MAPIStoreTasksFolder.h | 32 + OpenChange/MAPIStoreTasksFolder.m | 125 ++ 38 files changed, 2275 insertions(+), 1318 deletions(-) create mode 100644 OpenChange/MAPIStoreCalendarFolder.h create mode 100644 OpenChange/MAPIStoreCalendarFolder.m create mode 100644 OpenChange/MAPIStoreContactsFolder.h create mode 100644 OpenChange/MAPIStoreContactsFolder.m create mode 100644 OpenChange/MAPIStoreFSFolder.h create mode 100644 OpenChange/MAPIStoreFSFolder.m create mode 100644 OpenChange/MAPIStoreFolder.h create mode 100644 OpenChange/MAPIStoreFolder.m create mode 100644 OpenChange/MAPIStoreGCSFolder.h create mode 100644 OpenChange/MAPIStoreGCSFolder.m create mode 100644 OpenChange/MAPIStoreInboxContext.h create mode 100644 OpenChange/MAPIStoreInboxContext.m rename OpenChange/{MAPIStoreMailContext.h => MAPIStoreMailBaseContext.h} (89%) create mode 100644 OpenChange/MAPIStoreMailBaseContext.m delete mode 100644 OpenChange/MAPIStoreMailContext.m create mode 100644 OpenChange/MAPIStoreMailFolder.h create mode 100644 OpenChange/MAPIStoreMailFolder.m create mode 100644 OpenChange/MAPIStoreNotesFolder.h create mode 100644 OpenChange/MAPIStoreNotesFolder.m create mode 100644 OpenChange/MAPIStoreTasksFolder.h create mode 100644 OpenChange/MAPIStoreTasksFolder.m diff --git a/ChangeLog b/ChangeLog index e95dabf85..ca17501cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ 2011-02-24 Wolfgang Sourdeau - * OpenChange/MAPIStoreMessage.m: new super class used as for + * OpenChange/MAPIStoreFolder.m: new super class used as wrapper + around SOGoFolder objects, by decoupling the code previously found + in the SOGo*Context classes and which implement basic and uniform + content key facilities. + + * OpenChange/MAPIStoreMessage.m: new super class used for wrapper objects replacing the category modules on the SOGoObject. * OpenChange/MAPIStoreObject.m: new super class used as base the diff --git a/OpenChange/MAPIStoreCalendarContext.m b/OpenChange/MAPIStoreCalendarContext.m index fbe26b3b2..6a5665b68 100644 --- a/OpenChange/MAPIStoreCalendarContext.m +++ b/OpenChange/MAPIStoreCalendarContext.m @@ -20,31 +20,12 @@ * Boston, MA 02111-1307, USA. */ -#import +#import -#import - -#import - -#import -#import -#import - -#import - -#import "MAPIApplication.h" -#import "MAPIStoreAuthenticator.h" -#import "MAPIStoreCalendarMessageTable.h" #import "MAPIStoreMapping.h" -#import "MAPIStoreTypes.h" -#import "SOGoGCSFolder+MAPIStore.h" +#import "MAPIStoreCalendarFolder.h" #import "MAPIStoreCalendarContext.h" -#import "NSString+MAPIStore.h" - -#undef DEBUG -#include -#include @implementation MAPIStoreCalendarContext @@ -59,107 +40,19 @@ withID: 0x190001]; } -- (void) setupModuleFolder +- (void) setupBaseFolder: (NSURL *) newURL { - SOGoUserFolder *userFolder; - SOGoAppointmentFolders *parentFolder; - - userFolder = [SOGoUserFolder objectWithName: [authenticator username] - inContainer: MAPIApp]; - [parentFoldersBag addObject: userFolder]; - [woContext setClientObject: userFolder]; - - parentFolder = [userFolder lookupName: @"Calendar" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: parentFolder]; - [woContext setClientObject: parentFolder]; - - moduleFolder = [parentFolder lookupName: @"personal" - inContext: woContext - acquire: NO]; - [moduleFolder retain]; + baseFolder = [MAPIStoreCalendarFolder baseFolderWithURL: newURL + inContext: self]; + [baseFolder retain]; } -- (id) createMessageOfClass: (NSString *) messageClass - inFolderAtURL: (NSString *) folderURL; + +- (int) readCount: (uint32_t *) rowCount + ofTableType: (uint8_t) tableType + inFID: (uint64_t) fid { - SOGoAppointmentFolder *parentFolder; - SOGoAppointmentObject *newEntry; - NSString *name; - - parentFolder = [self lookupObject: folderURL]; - name = [NSString stringWithFormat: @"%@.ics", - [SOGoObject globallyUniqueObjectId]]; - newEntry = [SOGoAppointmentObject objectWithName: name - inContainer: parentFolder]; - [newEntry setIsNew: YES]; - - return newEntry; -} - -- (Class) messageTableClass -{ - return [MAPIStoreCalendarMessageTable class]; -} - -- (int) openMessage: (struct mapistore_message *) msg - forKey: (NSString *) childKey - inTable: (MAPIStoreTable *) table -{ - NSString *name, *email; - NSArray *attendees; - iCalPerson *person; - id event; - struct SRowSet *recipients; - int count, max, rc; - - rc = [super openMessage: msg forKey: childKey inTable: table]; - - if (rc == MAPI_E_SUCCESS && table == messageTable) - { - event = [[table lookupChild: childKey] component: NO secure: NO]; - attendees = [event attendees]; - max = [attendees count]; - - recipients = msg->recipients; - recipients->cRows = max; - recipients->aRow = talloc_array (recipients, struct SRow, max); - - for (count = 0; count < max; count++) - { - recipients->aRow[count].ulAdrEntryPad = 0; - recipients->aRow[count].cValues = 3; - recipients->aRow[count].lpProps = talloc_array (recipients->aRow, - struct SPropValue, - 3); - - // TODO (0x01 = primary recipient) - set_SPropValue_proptag (&(recipients->aRow[count].lpProps[0]), - PR_RECIPIENT_TYPE, - MAPILongValue (memCtx, 0x01)); - - person = [attendees objectAtIndex: count]; - - name = [person cn]; - if (!name) - name = @""; - - email = [person email]; - if (!email) - email = @""; - - set_SPropValue_proptag (&(recipients->aRow[count].lpProps[1]), - PR_DISPLAY_NAME, - [name asUnicodeInMemCtx: recipients->aRow[count].lpProps]); - set_SPropValue_proptag (&(recipients->aRow[count].lpProps[2]), - PR_EMAIL_ADDRESS, - [email asUnicodeInMemCtx: recipients->aRow[count].lpProps]); - - } - } - - return rc; + return [super readCount: rowCount ofTableType: tableType inFID: fid]; } @end diff --git a/OpenChange/MAPIStoreCalendarFolder.h b/OpenChange/MAPIStoreCalendarFolder.h new file mode 100644 index 000000000..8c483f9c9 --- /dev/null +++ b/OpenChange/MAPIStoreCalendarFolder.h @@ -0,0 +1,32 @@ +/* MAPIStoreCalendarFolder.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 MAPISTORECALENDARFOLDER_H +#define MAPISTORECALENDARFOLDER_H + +#import "MAPIStoreGCSFolder.h" + +@interface MAPIStoreCalendarFolder : MAPIStoreGCSFolder + +@end + +#endif /* MAPISTORECALENDARFOLDER_H */ diff --git a/OpenChange/MAPIStoreCalendarFolder.m b/OpenChange/MAPIStoreCalendarFolder.m new file mode 100644 index 000000000..0be936e40 --- /dev/null +++ b/OpenChange/MAPIStoreCalendarFolder.m @@ -0,0 +1,124 @@ +/* MAPIStoreCalendarFolder.m - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 +#import +#import +#import +#import + +#import "MAPIApplication.h" +#import "MAPIStoreCalendarContext.h" +#import "MAPIStoreCalendarMessage.h" +#import "MAPIStoreCalendarMessageTable.h" + +#import "MAPIStoreCalendarFolder.h" + +static Class MAPIStoreCalendarMessageK; + +@implementation MAPIStoreCalendarFolder + ++ (void) initialize +{ + MAPIStoreCalendarMessageK = [MAPIStoreCalendarMessage class]; +} + +- (id) initWithURL: (NSURL *) newURL + inContext: (MAPIStoreContext *) newContext +{ + SOGoUserFolder *userFolder; + SOGoAppointmentFolders *parentFolder; + WOContext *woContext; + + if ((self = [super initWithURL: newURL + inContext: newContext])) + { + woContext = [newContext woContext]; + userFolder = [SOGoUserFolder objectWithName: [newURL user] + inContainer: MAPIApp]; + [parentContainersBag addObject: userFolder]; + [woContext setClientObject: userFolder]; + + parentFolder = [userFolder lookupName: @"Calendar" + inContext: woContext + acquire: NO]; + [parentContainersBag addObject: parentFolder]; + [woContext setClientObject: parentFolder]; + + sogoObject = [parentFolder lookupName: @"personal" + inContext: woContext + acquire: NO]; + [sogoObject retain]; + } + + return self; +} + +- (Class) messageClass +{ + return MAPIStoreCalendarMessageK; +} + +- (MAPIStoreMessageTable *) messageTable +{ + if (!messageTable) + ASSIGN (messageTable, + [MAPIStoreCalendarMessageTable tableForContainer: self]); + + return messageTable; +} + +- (EOQualifier *) componentQualifier +{ + static EOQualifier *componentQualifier = nil; + + if (!componentQualifier) + componentQualifier + = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" + operatorSelector: EOQualifierOperatorEqual + value: @"vevent"]; + + return componentQualifier; +} + +- (MAPIStoreMessage *) createMessage +{ + MAPIStoreMessage *newMessage; + SOGoAppointmentObject *newEntry; + NSString *name; + + name = [NSString stringWithFormat: @"%@.ics", + [SOGoObject globallyUniqueObjectId]]; + newEntry = [SOGoAppointmentObject objectWithName: name + inContainer: sogoObject]; + [newEntry setIsNew: YES]; + newMessage = [MAPIStoreCalendarMessage mapiStoreObjectWithSOGoObject: newEntry + inContainer: self]; + + + return newMessage; +} + +@end diff --git a/OpenChange/MAPIStoreContactsContext.m b/OpenChange/MAPIStoreContactsContext.m index 63abb3031..079564270 100644 --- a/OpenChange/MAPIStoreContactsContext.m +++ b/OpenChange/MAPIStoreContactsContext.m @@ -22,15 +22,7 @@ #import -#import - -#import -#import -#import - -#import "MAPIApplication.h" -#import "MAPIStoreAuthenticator.h" -#import "MAPIStoreContactsMessageTable.h" +#import "MAPIStoreContactsFolder.h" #import "MAPIStoreMapping.h" #import "MAPIStoreContactsContext.h" @@ -48,48 +40,11 @@ withID: 0x1a0001]; } -- (void) setupModuleFolder +- (void) setupBaseFolder: (NSURL *) newURL { - SOGoUserFolder *userFolder; - SOGoContactFolders *parentFolder; - - userFolder = [SOGoUserFolder objectWithName: [authenticator username] - inContainer: MAPIApp]; - [parentFoldersBag addObject: userFolder]; - [woContext setClientObject: userFolder]; - - parentFolder = [userFolder lookupName: @"Contacts" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: parentFolder]; - [woContext setClientObject: parentFolder]; - - moduleFolder = [parentFolder lookupName: @"personal" - inContext: woContext - acquire: NO]; - [moduleFolder retain]; -} - -- (Class) messageTableClass -{ - return [MAPIStoreContactsMessageTable class]; -} - -- (id) createMessageOfClass: (NSString *) messageClass - inFolderAtURL: (NSString *) folderURL; -{ - SOGoContactGCSFolder *parentFolder; - SOGoContactGCSEntry *newEntry; - NSString *name; - - parentFolder = [self lookupObject: folderURL]; - name = [NSString stringWithFormat: @"%@.vcf", - [SOGoObject globallyUniqueObjectId]]; - newEntry = [SOGoContactGCSEntry objectWithName: name - inContainer: parentFolder]; - [newEntry setIsNew: YES]; - - return newEntry; + baseFolder = [MAPIStoreContactsFolder baseFolderWithURL: newURL + inContext: self]; + [baseFolder retain]; } @end diff --git a/OpenChange/MAPIStoreContactsFolder.h b/OpenChange/MAPIStoreContactsFolder.h new file mode 100644 index 000000000..c269a6cfc --- /dev/null +++ b/OpenChange/MAPIStoreContactsFolder.h @@ -0,0 +1,32 @@ +/* MAPIStoreContactsFolder.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 MAPISTORECONTACTSFOLDER_H +#define MAPISTORECONTACTSFOLDER_H + +#import "MAPIStoreGCSFolder.h" + +@interface MAPIStoreContactsFolder : MAPIStoreGCSFolder + +@end + +#endif /* MAPISTORECONTACTSFOLDER_H */ diff --git a/OpenChange/MAPIStoreContactsFolder.m b/OpenChange/MAPIStoreContactsFolder.m new file mode 100644 index 000000000..0c6c3b162 --- /dev/null +++ b/OpenChange/MAPIStoreContactsFolder.m @@ -0,0 +1,126 @@ +/* MAPIStoreContactsFolder.m - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 +#import + +#import "MAPIApplication.h" +#import "MAPIStoreContactsContext.h" +#import "MAPIStoreContactsMessage.h" +#import "MAPIStoreContactsMessageTable.h" + +#import "MAPIStoreContactsFolder.h" + +static Class MAPIStoreContactsMessageK; + +@implementation MAPIStoreContactsFolder + ++ (void) initialize +{ + MAPIStoreContactsMessageK = [MAPIStoreContactsMessage class]; +} + +- (void) dealloc +{ + [super dealloc]; +} + +- (id) initWithURL: (NSURL *) newURL + inContext: (MAPIStoreContext *) newContext +{ + SOGoUserFolder *userFolder; + SOGoContactFolders *parentFolder; + WOContext *woContext; + + if ((self = [super initWithURL: newURL + inContext: newContext])) + { + woContext = [newContext woContext]; + userFolder = [SOGoUserFolder objectWithName: [newURL user] + inContainer: MAPIApp]; + [parentContainersBag addObject: userFolder]; + [woContext setClientObject: userFolder]; + + parentFolder = [userFolder lookupName: @"Contacts" + inContext: woContext + acquire: NO]; + [parentContainersBag addObject: parentFolder]; + [woContext setClientObject: parentFolder]; + + sogoObject = [parentFolder lookupName: @"personal" + inContext: woContext + acquire: NO]; + [sogoObject retain]; + } + + return self; +} + +- (Class) messageClass +{ + return MAPIStoreContactsMessageK; +} + +- (MAPIStoreMessageTable *) messageTable +{ + if (!messageTable) + ASSIGN (messageTable, + [MAPIStoreContactsMessageTable tableForContainer: self]); + + return messageTable; +} + +- (EOQualifier *) componentQualifier +{ + static EOQualifier *componentQualifier = nil; + + /* TODO: we need to support vlist as well */ + if (!componentQualifier) + componentQualifier + = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" + operatorSelector: EOQualifierOperatorEqual + value: @"vcard"]; + + return componentQualifier; +} + +- (MAPIStoreMessage *) createMessage +{ + MAPIStoreMessage *newMessage; + SOGoContactGCSEntry *newEntry; + NSString *name; + + name = [NSString stringWithFormat: @"%@.vcf", + [SOGoObject globallyUniqueObjectId]]; + newEntry = [SOGoContactGCSEntry objectWithName: name + inContainer: sogoObject]; + [newEntry setIsNew: YES]; + newMessage = [MAPIStoreContactsMessage mapiStoreObjectWithSOGoObject: newEntry + inContainer: self]; + + return newMessage; +} + +@end diff --git a/OpenChange/MAPIStoreContext.h b/OpenChange/MAPIStoreContext.h index cbaf4a276..e0a6f2191 100644 --- a/OpenChange/MAPIStoreContext.h +++ b/OpenChange/MAPIStoreContext.h @@ -30,6 +30,7 @@ @class NSMutableArray; @class NSMutableDictionary; @class NSString; +@class NSURL; @class EOQualifier; @@ -40,6 +41,7 @@ @class SOGoObject; @class MAPIStoreAuthenticator; +@class MAPIStoreFolder; @class MAPIStoreMapping; @class MAPIStoreTable; @@ -49,17 +51,10 @@ NSString *uri; - NSMutableArray *parentFoldersBag; - MAPIStoreAuthenticator *authenticator; WOContext *woContext; - id moduleFolder; - SOGoMAPIFSFolder *faiModuleFolder; - - MAPIStoreTable *folderTable; - MAPIStoreTable *messageTable; - MAPIStoreTable *faiTable; + MAPIStoreFolder *baseFolder; /* for active messages (NSDictionary instances) */ NSMutableDictionary *messages; @@ -71,15 +66,15 @@ - (void) setURI: (NSString *) newUri andMemCtx: (struct mapistore_context *) newMemCtx; -- (void) setupModuleFolder; - - (void) setAuthenticator: (MAPIStoreAuthenticator *) newAuthenticator; - (MAPIStoreAuthenticator *) authenticator; +- (WOContext *) woContext; + - (void) setupRequest; - (void) tearDownRequest; -- (id) lookupObject: (NSString *) objectURLString; +// - (id) lookupObject: (NSString *) objectURLString; /* backend methods */ - (int) getPath: (char **) path @@ -119,9 +114,9 @@ - (int) openMessage: (struct mapistore_message *) msg withMID: (uint64_t) mid inFID: (uint64_t) fid; -- (int) createMessagePropertiesWithMID: (uint64_t) mid - inFID: (uint64_t) fid - isAssociated: (BOOL) isAssociated; +- (int) createMessageWithMID: (uint64_t) mid + inFID: (uint64_t) fid + isAssociated: (BOOL) isAssociated; - (int) saveChangesInMessageWithMID: (uint64_t) mid andFlags: (uint8_t) flags; - (int) submitMessageWithMID: (uint64_t) mid @@ -152,28 +147,30 @@ - (int) getFoldersList: (struct indexing_folders_list **) folders_list withFMID: (uint64_t) fmid; - /* util methods */ - (NSString *) extractChildNameFromURL: (NSString *) childURL andFolderURLAt: (NSString **) folderURL; -- (void) registerValue: (id) value - asProperty: (enum MAPITAGS) property - forURL: (NSString *) url; +- (uint64_t) idForObjectWithKey: (NSString *) key + inFolderURL: (NSString *) folderURL; /* subclass methods */ + (NSString *) MAPIModuleName; + (void) registerFixedMappings: (MAPIStoreMapping *) storeMapping; +- (void) setupBaseFolder: (NSURL *) newURL; -- (Class) messageTableClass; -- (Class) folderTableClass; +/* proof of concept */ +- (int) getAttachmentTable: (void **) table + andRowCount: (uint32_t *) count + withMID: (uint64_t) mid; +- (int) getAttachment: (void **) attachment + withAID: (uint32_t) aid + inMID: (uint64_t) mid; -- (id) createMessageOfClass: (NSString *) messageClass - inFolderAtURL: (NSString *) folderURL; -- (int) openMessage: (struct mapistore_message *) msg - forKey: (NSString *) childKey - inTable: (MAPIStoreTable *) table; +- (int) createAttachment: (void **) attachmentPtr + inAID: (uint32_t *) aid + withMessage: (uint64_t) mid; @end diff --git a/OpenChange/MAPIStoreContext.m b/OpenChange/MAPIStoreContext.m index 5cffeacf0..d4f926e20 100644 --- a/OpenChange/MAPIStoreContext.m +++ b/OpenChange/MAPIStoreContext.m @@ -29,21 +29,21 @@ #import #import -#import #import -#import -#import -#import - #import "SOGoMAPIFSFolder.h" #import "SOGoMAPIFSMessage.h" #import "MAPIApplication.h" +#import "MAPIStoreAttachment.h" +// #import "MAPIStoreAttachmentTable.h" #import "MAPIStoreAuthenticator.h" +#import "MAPIStoreFolder.h" #import "MAPIStoreFolderTable.h" -#import "MAPIStoreFAIMessageTable.h" #import "MAPIStoreMapping.h" +#import "MAPIStoreMessage.h" +#import "MAPIStoreMessageTable.h" +#import "MAPIStoreFSMessageTable.h" #import "MAPIStoreTypes.h" #import "NSArray+MAPIStore.h" #import "NSObject+MAPIStore.h" @@ -52,36 +52,27 @@ #import "MAPIStoreContext.h" #undef DEBUG +#include +#include +#include #include #include +#include +#include /* TODO: homogenize method names and order of parameters */ -@interface SOGoFolder (MAPIStoreProtocol) - -- (BOOL) create; -- (NSException *) delete; - -@end - -@interface SOGoObject (MAPIStoreProtocol) - -- (void) setMAPIProperties: (NSDictionary *) properties; -- (void) MAPISave; -- (void) MAPISubmit; - -@end - @implementation MAPIStoreContext : NSObject /* sogo://username:password@{contacts,calendar,tasks,journal,notes,mail}/dossier/id */ -static Class SOGoObjectK, SOGoMailAccountK, SOGoMailFolderK; -static Class NSArrayK, NSDataK, NSStringK; +static Class NSDataK, NSStringK; static MAPIStoreMapping *mapping; static NSMutableDictionary *contextClassMapping; +static void *ldbCtx = NULL; + + (void) initialize { NSArray *classes; @@ -89,10 +80,6 @@ static NSMutableDictionary *contextClassMapping; NSUInteger count, max; NSString *moduleName; - SOGoObjectK = [SOGoObject class]; - SOGoMailAccountK = [SOGoMailAccount class]; - SOGoMailFolderK = [SOGoMailFolder class]; - NSArrayK = [NSArray class]; NSDataK = [NSData class]; NSStringK = [NSString class]; @@ -115,37 +102,13 @@ static NSMutableDictionary *contextClassMapping; } } -+ (NSString *) MAPIModuleName -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -+ (void) registerFixedMappings: (MAPIStoreMapping *) storeMapping -{ -} - -- (Class) messageTableClass -{ - [self subclassResponsibility: _cmd]; - - return Nil; -} - -- (Class) folderTableClass -{ - return [MAPIStoreFolderTable class]; -} - static inline MAPIStoreContext * _prepareContextClass (struct mapistore_context *newMemCtx, - Class contextClass, NSString *completeURLString, - NSString *username, NSString *password) + Class contextClass, NSURL *url) { + static NSMutableDictionary *registration = nil; MAPIStoreContext *context; MAPIStoreAuthenticator *authenticator; - static NSMutableDictionary *registration = nil; if (!registration) registration = [NSMutableDictionary new]; @@ -158,17 +121,17 @@ _prepareContextClass (struct mapistore_context *newMemCtx, } context = [contextClass new]; - [context setURI: completeURLString andMemCtx: newMemCtx]; + [context setURI: [url absoluteString] andMemCtx: newMemCtx]; [context autorelease]; authenticator = [MAPIStoreAuthenticator new]; - [authenticator setUsername: username]; - [authenticator setPassword: password]; + [authenticator setUsername: [url user]]; + [authenticator setPassword: [url password]]; [context setAuthenticator: authenticator]; [authenticator release]; [context setupRequest]; - [context setupModuleFolder]; + [context setupBaseFolder: url]; [context tearDownRequest]; return context; @@ -202,9 +165,7 @@ _prepareContextClass (struct mapistore_context *newMemCtx, if (contextClass) context = _prepareContextClass (newMemCtx, contextClass, - completeURLString, - [baseURL user], - [baseURL password]); + baseURL); else NSLog (@"ERROR: unrecognized module name '%@'", module); } @@ -225,13 +186,8 @@ _prepareContextClass (struct mapistore_context *newMemCtx, messages = [NSMutableDictionary new]; woContext = [WOContext contextWithRequest: nil]; [woContext retain]; - parentFoldersBag = [NSMutableArray new]; - moduleFolder = nil; - faiModuleFolder = nil; + baseFolder = nil; uri = nil; - messageTable = nil; - faiTable = nil; - folderTable = nil; } [self logWithFormat: @"-init"]; @@ -243,16 +199,9 @@ _prepareContextClass (struct mapistore_context *newMemCtx, { [self logWithFormat: @"-dealloc"]; - [parentFoldersBag release]; - - [messageTable release]; - [faiTable release]; - [folderTable release]; - [messages release]; - [moduleFolder release]; - [faiModuleFolder release]; + [baseFolder release]; [woContext release]; [authenticator release]; @@ -264,12 +213,21 @@ _prepareContextClass (struct mapistore_context *newMemCtx, - (void) setURI: (NSString *) newUri andMemCtx: (struct mapistore_context *) newMemCtx { + struct loadparm_context *lpCtx; + + if (!ldbCtx) + { + lpCtx = loadparm_init (newMemCtx); + ldbCtx = mapiproxy_server_openchange_ldb_init (lpCtx); + } + ASSIGN (uri, newUri); memCtx = newMemCtx; +} - faiModuleFolder = [SOGoMAPIFSFolder folderWithURL: [NSURL URLWithString: newUri] - andTableType: MAPISTORE_FAI_TABLE]; - [faiModuleFolder retain]; +- (WOContext *) woContext +{ + return woContext; } - (void) setAuthenticator: (MAPIStoreAuthenticator *) newAuthenticator @@ -300,151 +258,10 @@ _prepareContextClass (struct mapistore_context *newMemCtx, [MAPIApp setMAPIStoreContext: nil]; } -- (void) setupModuleFolder +- (MAPIStoreFolder *) lookupFolder: (NSString *) folderURL { - [self subclassResponsibility: _cmd]; -} - -// - (void) _setNewLastObject: (id) newLastObject -// { -// id currentObject, container; - -// if (newLastObject != lastObject) -// { -// currentObject = lastObject; -// while (currentObject) -// { -// container = [currentObject container]; -// [currentObject release]; -// currentObject = container; -// } - -// currentObject = newLastObject; -// while (currentObject) -// { -// [currentObject retain]; -// currentObject = [currentObject container]; -// } - -// lastObject = newLastObject; -// } -// } - - -- (id) _lookupObject: (NSString *) objectURLString - fromBaseFolder: (SOGoFolder *) baseFolder -{ - id object; - NSURL *objectURL; - NSArray *path; - int count, max; - NSString *pathString, *nameInContainer; - - // [self logWithFormat: @"lookup of '%@'", objectURLString]; - objectURL = [NSURL URLWithString: objectURLString]; - if (objectURL) - { - object = baseFolder; - pathString = [objectURL path]; - if ([pathString hasPrefix: @"/"]) - pathString = [pathString substringFromIndex: 1]; - if ([pathString length] > 0) - { - path = [pathString componentsSeparatedByString: @"/"]; - max = [path count]; - if (max > 0) - { - for (count = 0; - object && count < max; - count++) - { - nameInContainer = [[path objectAtIndex: count] - stringByUnescapingURL]; - object = [object lookupName: nameInContainer - inContext: woContext - acquire: NO]; - if ([object isKindOfClass: SOGoObjectK]) - [woContext setClientObject: object]; - else - object = nil; - } - } - } - - // [self _setNewLastObject: object]; - // ASSIGN (lastObjectURL, objectURLString); - } - else - { - object = nil; - [self errorWithFormat: @"url string gave nil NSURL: '%@'", objectURLString]; - } - - [woContext setClientObject: object]; - - return object; -} - -- (id) lookupObject: (NSString *) objectURLString -{ - if (!moduleFolder) - [NSException raise: @"MAPIStoreIOException" - format: @"no moduleFolder set for context"]; - - return [self _lookupObject: objectURLString - fromBaseFolder: moduleFolder]; -} - -- (id) lookupFAIObject: (NSString *) objectURLString -{ - if (!faiModuleFolder) - [NSException raise: @"MAPIStoreIOException" - format: @"no moduleFolder set for context"]; - - return [self _lookupObject: objectURLString - fromBaseFolder: faiModuleFolder]; -} - -- (NSString *) _createFolder: (struct SRow *) aRow - inParentURL: (NSString *) parentFolderURL -{ - NSString *newFolderURL; - NSString *folderName, *nameInContainer; - SOGoFolder *parentFolder, *newFolder; - int i; - - newFolderURL = nil; - - folderName = nil; - for (i = 0; !folderName && i < aRow->cValues; i++) - { - if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME_UNICODE) - folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszW]; - else if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME) - folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszA]; - } - - if (folderName) - { - parentFolder = [self lookupObject: parentFolderURL]; - if (parentFolder) - { - if ([parentFolder isKindOfClass: SOGoMailAccountK] - || [parentFolder isKindOfClass: SOGoMailFolderK]) - { - nameInContainer = [NSString stringWithFormat: @"folder%@", - [folderName asCSSIdentifier]]; - newFolder = [SOGoMailFolderK objectWithName: nameInContainer - inContainer: parentFolder]; - if ([newFolder create]) - newFolderURL = [NSString stringWithFormat: @"%@/%@", - parentFolderURL, - [nameInContainer stringByEscapingURL]]; - } - } - } - - return newFolderURL; + /* TODO hierarchy */ + return baseFolder; } /** @@ -459,7 +276,8 @@ _prepareContextClass (struct mapistore_context *newMemCtx, withFID: (uint64_t) fid inParentFID: (uint64_t) parentFID { - NSString *folderURL, *parentFolderURL; + NSString *folderURL, *folderKey, *parentFolderURL; + MAPIStoreFolder *parentFolder; int rc; [self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__]; @@ -470,23 +288,22 @@ _prepareContextClass (struct mapistore_context *newMemCtx, else { parentFolderURL = [mapping urlFromID: parentFID]; - if (!parentFolderURL) - [self errorWithFormat: @"No url found for FID: %lld", parentFID]; if (parentFolderURL) { - folderURL = [self _createFolder: aRow inParentURL: parentFolderURL]; - if (folderURL) + parentFolder = [self lookupFolder: parentFolderURL]; + folderKey = [parentFolder createFolder: aRow]; + if (folderKey) { + folderURL = [NSString stringWithFormat: @"%@%@", + parentFolderURL, folderKey]; [mapping registerURL: folderURL withID: fid]; - // if ([sogoFolder isKindOfClass: SOGoMailAccountK]) - // [sogoFolder subscribe]; rc = MAPISTORE_SUCCESS; } else - rc = MAPISTORE_ERR_NOT_FOUND; + rc = MAPISTORE_ERROR; } else - rc = MAPISTORE_ERR_NO_DIRECTORY; + rc = MAPISTORE_ERR_NOT_FOUND; } return rc; @@ -547,51 +364,21 @@ _prepareContextClass (struct mapistore_context *newMemCtx, return MAPISTORE_SUCCESS; } -/* TODO: should handle folder hierarchies */ - (MAPIStoreTable *) _tableForFID: (uint64_t) fid andTableType: (uint8_t) tableType { + MAPIStoreFolder *folder; MAPIStoreTable *table; +/* TODO: should handle folder hierarchies */ + folder = baseFolder; + if (tableType == MAPISTORE_MESSAGE_TABLE) - { - if (!messageTable) - { - messageTable = [[self messageTableClass] new]; - [messageTable setContext: self - withMemCtx: memCtx]; - [messageTable setFolder: moduleFolder - withURL: uri - andFID: fid]; - } - table = messageTable; - } + table = [folder messageTable]; else if (tableType == MAPISTORE_FAI_TABLE) - { - if (!faiTable) - { - faiTable = [MAPIStoreFAIMessageTable new]; - [faiTable setContext: self - withMemCtx: memCtx]; - [faiTable setFolder: faiModuleFolder - withURL: uri - andFID: fid]; - } - table = faiTable; - } + table = [folder faiMessageTable]; else if (tableType == MAPISTORE_FOLDER_TABLE) - { - if (!folderTable) - { - folderTable = [[self folderTableClass] new]; - [folderTable setContext: self - withMemCtx: memCtx]; - [folderTable setFolder: moduleFolder - withURL: uri - andFID: fid]; - } - table = folderTable; - } + table = [folder folderTable]; else { table = nil; @@ -613,9 +400,9 @@ _prepareContextClass (struct mapistore_context *newMemCtx, ofTableType: (uint8_t) tableType inFID: (uint64_t) fid { - MAPIStoreTable *table; NSArray *keys; NSString *url; + MAPIStoreFolder *folder; int rc; [self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d", @@ -636,10 +423,23 @@ _prepareContextClass (struct mapistore_context *newMemCtx, url = [mapping urlFromID: fid]; if (url) { - table = [self _tableForFID: fid andTableType: tableType]; - keys = [table cachedChildKeys]; - *rowCount = [keys count]; - rc = MAPI_E_SUCCESS; + folder = [self lookupFolder: url]; + if (folder) + { + if (tableType == MAPISTORE_MESSAGE_TABLE) + keys = [folder messageKeys]; + else if (tableType == MAPISTORE_FOLDER_TABLE) + keys = [folder folderKeys]; + else if (tableType == MAPISTORE_FAI_TABLE) + keys = [folder faiMessageKeys]; + *rowCount = [keys count]; + rc = MAPI_E_SUCCESS; + } + else + { + [self errorWithFormat: @"No folder found for URL: %@", url]; + rc = MAPISTORE_ERR_NOT_FOUND; + } } else { @@ -671,7 +471,9 @@ _prepareContextClass (struct mapistore_context *newMemCtx, table = [self _tableForFID: fid andTableType: tableType]; [table setRestrictions: res]; - + // FIXME: we should not flush the caches if the restrictions matches + [table cleanupCaches]; + return MAPISTORE_SUCCESS; } @@ -679,10 +481,11 @@ _prepareContextClass (struct mapistore_context *newMemCtx, withFID: (uint64_t) fid andTableType: (uint8_t) type getTableStatus: (uint8_t *) tableStatus { - MAPIStoreMessageTable *table; + MAPIStoreTable *table; - table = (MAPIStoreMessageTable *) [self _tableForFID: fid andTableType: type]; + table = [self _tableForFID: fid andTableType: type]; [table setSortOrder: set]; + [table cleanupCaches]; return MAPISTORE_SUCCESS; } @@ -694,15 +497,12 @@ _prepareContextClass (struct mapistore_context *newMemCtx, andQueryType: (enum table_query_type) queryType inFID: (uint64_t) fid { - NSArray *children, *restrictedChildren; - NSString *folderURL, *childKey; + NSString *folderURL; MAPIStoreTable *table; + MAPIStoreMessage *message; const char *propName; int rc; - propName = get_proptag_name (propTag); - if (!propName) - propName = ""; // [self logWithFormat: @"METHOD '%s' (%d) -- proptag: %s (0x%.8x), pos: %.8x," // @" tableType: %d, queryType: %d, fid: %.16x", // __FUNCTION__, __LINE__, propName, proptag, pos, tableType, queryType, fid]; @@ -715,53 +515,30 @@ _prepareContextClass (struct mapistore_context *newMemCtx, folderURL = [mapping urlFromID: fid]; if (folderURL) { - restrictedChildren = nil; table = [self _tableForFID: fid andTableType: tableType]; - if (queryType == MAPISTORE_PREFILTERED_QUERY) - { - children = [table cachedRestrictedChildKeys]; - restrictedChildren = nil; - } + *data = NULL; + message = [table childAtRowID: pos forQueryType: queryType]; + if (message) + { + rc = [message getProperty: data withTag: propTag]; + if (rc == MAPISTORE_ERR_NOT_FOUND) + rc = MAPI_E_NOT_FOUND; + else if (rc == MAPISTORE_ERR_NO_MEMORY) + rc = MAPI_E_NOT_ENOUGH_MEMORY; + else if (rc == MAPISTORE_SUCCESS && *data == NULL) + { + propName = get_proptag_name (propTag); + if (!propName) + propName = ""; + + [self errorWithFormat: @"both 'success' and NULL data" + @" returned for proptag %s(0x%.8x)", + propName, propTag]; + rc = MAPI_E_NOT_FOUND; + } + } else - { - children = [table cachedChildKeys]; - restrictedChildren = [table cachedRestrictedChildKeys]; - } - - if ([children count] > pos) - { - childKey = [children objectAtIndex: pos]; - - // TODO: the use of restrictedChildren might be optimized by - // making it a dictionary (hash versus linear search) - if (queryType == MAPISTORE_PREFILTERED_QUERY - || [restrictedChildren containsObject: childKey]) - { - rc = [table getChildProperty: data - forKey: childKey - withTag: propTag]; - if (rc == MAPI_E_SUCCESS && *data == NULL) - { - [self errorWithFormat: @"both 'success' and NULL data" - @" returned for proptag %s(0x%.8x)", - propName, propTag]; - rc = MAPI_E_NOT_FOUND; - } - } - else - // [self logWithFormat: - // @"child '%@' does not match active restriction", - // childURL]; - rc = MAPI_E_INVALID_OBJECT; - } - else - { - // [self errorWithFormat: - // @"Invalid row position %d for table type %d" - // @" in FID: %lld", - // pos, tableType, fid]; - rc = MAPI_E_INVALID_OBJECT; - } + rc = MAPI_E_INVALID_OBJECT; } else { @@ -772,198 +549,95 @@ _prepareContextClass (struct mapistore_context *newMemCtx, return rc; } -- (int) openMessage: (struct mapistore_message *) msg - forKey: (NSString *) childKey - inTable: (MAPIStoreTable *) table -{ - static enum MAPITAGS tags[] = { PR_SUBJECT_PREFIX_UNICODE, - PR_NORMALIZED_SUBJECT_UNICODE }; - struct SRowSet *recipients; - struct SRow *properties; - NSInteger count, max; - const char *propName; - void *propValue; - - // [self logWithFormat: @"INCOMPLETE METHOD '%s' (%d): no recipient handling", - // __FUNCTION__, __LINE__]; - - recipients = talloc_zero (memCtx, struct SRowSet); - recipients->cRows = 0; - recipients->aRow = NULL; - msg->recipients = recipients; - - max = 2; - properties = talloc_zero (memCtx, struct SRow); - properties->cValues = 0; - properties->ulAdrEntryPad = 0; - properties->lpProps = talloc_array (properties, struct SPropValue, max); - for (count = 0; count < max; count++) - { - if ([table getChildProperty: &propValue - forKey: childKey - withTag: tags[count]] - == MAPI_E_SUCCESS) - { - if (propValue == NULL) - { - propName = get_proptag_name (tags[count]); - if (!propName) - propName = ""; - [self errorWithFormat: @"both 'success' and NULL data" - @" returned for proptag %s(0x%.8x)", - propName, tags[count]]; - } - else - { - set_SPropValue_proptag (properties->lpProps + properties->cValues, - tags[count], - propValue); - properties->cValues++; - } - } - } - msg->properties = properties; - - return MAPI_E_SUCCESS; -} - - (int) openMessage: (struct mapistore_message *) msg withMID: (uint64_t) mid inFID: (uint64_t) fid { - NSString *childURL, *childKey, *folderURL; - MAPIStoreTable *table; - BOOL isAssociated; + NSString *messageKey, *folderURL, *messageURL; + MAPIStoreMessage *message; + MAPIStoreFolder *folder; + NSNumber *midKey; int rc; - childURL = [mapping urlFromID: mid]; - if (childURL) - { - childKey = [self extractChildNameFromURL: childURL - andFolderURLAt: &folderURL]; - table = [self _tableForFID: fid andTableType: MAPISTORE_FAI_TABLE]; - if ([[table cachedChildKeys] containsObject: childKey]) - { - isAssociated = YES; - rc = [self openMessage: msg forKey: childKey inTable: table]; - } - else - { - isAssociated = NO; - table = [self _tableForFID: fid andTableType: MAPISTORE_MESSAGE_TABLE]; - if ([[table cachedChildKeys] containsObject: childKey]) - rc = [self openMessage: msg forKey: childKey inTable: table]; - else - rc = MAPI_E_INVALID_OBJECT; - } - } + midKey = [NSNumber numberWithUnsignedLongLong: mid]; + message = [messages objectForKey: midKey]; + if (message) + rc = MAPISTORE_SUCCESS; else - rc = MAPISTORE_ERR_NOT_FOUND; + { + rc = MAPISTORE_ERR_NOT_FOUND; - if (rc == MAPI_E_SUCCESS) - [self createMessagePropertiesWithMID: mid - inFID: fid - isAssociated: isAssociated]; + messageURL = [mapping urlFromID: mid]; + if (messageURL) + { + messageKey = [self extractChildNameFromURL: messageURL + andFolderURLAt: &folderURL]; + folder = [self lookupFolder: folderURL]; + message = [folder lookupChild: messageKey]; + if (message) + { + [message openMessage: msg]; + [message setMAPIRetainCount: [message mapiRetainCount] + 1]; + [messages setObject: message forKey: midKey]; + rc = MAPISTORE_SUCCESS; + } + } + } + [message setMAPIRetainCount: [message mapiRetainCount] + 1]; return rc; } -- (int) createMessagePropertiesWithMID: (uint64_t) mid - inFID: (uint64_t) fid - isAssociated: (BOOL) isAssociated +- (int) createMessageWithMID: (uint64_t) mid + inFID: (uint64_t) fid + isAssociated: (BOOL) isAssociated { - NSMutableDictionary *messageProperties; - NSNumber *midNbr; - NSUInteger retainCount; + NSNumber *midKey; + NSString *folderURL, *childURL; + MAPIStoreMessage *message; + MAPIStoreFolder *folder; + int rc; - messageProperties = [messages objectForKey: - [NSNumber numberWithUnsignedLongLong: mid]]; - if (messageProperties) - { - [self logWithFormat: - @"METHOD '%s' -- mid: 0x%.16x, fid: 0x%.16x; retainCount++", - __FUNCTION__, mid, fid]; - retainCount = [[messageProperties objectForKey: @"mapiRetainCount"] - unsignedIntValue]; - [messageProperties - setObject: [NSNumber numberWithUnsignedInt: retainCount + 1] - forKey: @"mapiRetainCount"]; - } + [self logWithFormat: @"METHOD '%s' -- mid: 0x%.16x, fid: 0x%.16x, associated: %d", + __FUNCTION__, mid, fid, isAssociated]; + + midKey = [NSNumber numberWithUnsignedLongLong: mid]; + message = [messages objectForKey: midKey]; + if (message) + rc = MAPISTORE_ERR_EXIST; else { - [self logWithFormat: @"METHOD '%s' -- mid: 0x%.16x, fid: 0x%.16x", - __FUNCTION__, mid, fid]; - messageProperties = [NSMutableDictionary new]; - [messageProperties setObject: [NSNumber numberWithUnsignedLongLong: fid] - forKey: @"fid"]; - midNbr = [NSNumber numberWithUnsignedLongLong: mid]; - [messageProperties setObject: midNbr forKey: @"mid"]; - [messageProperties setObject: [NSNumber numberWithBool: isAssociated] - forKey: @"associated"]; - [messageProperties setObject: [NSNumber numberWithInt: 1] - forKey: @"mapiRetainCount"]; + folderURL = [mapping urlFromID: fid]; + if (folderURL) + { + folder = [self lookupFolder: folderURL]; + message = [folder createMessage: isAssociated]; + if (message) + { + [messages setObject: message forKey: midKey]; + [message setMAPIRetainCount: [message mapiRetainCount] + 1]; + childURL = [NSString stringWithFormat: @"%@%@", + folderURL, [message nameInContainer]]; + [mapping registerURL: childURL withID: mid]; + rc = MAPISTORE_SUCCESS; + } + else + rc = MAPISTORE_ERROR; - [messageProperties - setObject: [@"No subject" dataUsingEncoding: NSASCIIStringEncoding] - forKey: MAPIPropertyKey (PR_SEARCH_KEY)]; + // { + // if (![folderURL hasSuffix: @"/"]) + // folderURL = [NSString stringWithFormat: @"%@/", folderURL]; + // messageURL = [NSString stringWithFormat: @"%@%@", folderURL, + // [message nameInContainer]]; + // [mapping registerURL: messageURL withID: mid]; - [messages setObject: messageProperties forKey: midNbr]; - [messageProperties release]; + } + else + rc = MAPISTORE_ERR_NOT_FOUND; } - return MAPISTORE_SUCCESS; -} - -- (id) createMessageOfClass: (NSString *) messageClass - inFolderAtURL: (NSString *) folderURL -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (id) _createMessageOfClass: (NSString *) messageClass - associated: (BOOL) associated - withMID: (uint64_t) mid - inFID: (uint64_t) fid -{ - NSString *folderURL, *messageURL; - id message; - - message = nil; - - folderURL = [mapping urlFromID: fid]; - if (folderURL) - { - if (associated) - { - message = [[self lookupFAIObject: folderURL] newMessage]; - [faiTable cleanupCaches]; - } - else - { - message = [self createMessageOfClass: messageClass - inFolderAtURL: folderURL]; - [messageTable cleanupCaches]; - } - if (message) - { - if (![folderURL hasSuffix: @"/"]) - folderURL = [NSString stringWithFormat: @"%@/", folderURL]; - messageURL = [NSString stringWithFormat: @"%@%@", folderURL, - [message nameInContainer]]; - [mapping registerURL: messageURL withID: mid]; - } - else - [self errorWithFormat: - @"no message created in folder '%.16x' with mid '%.16x'", - fid, mid]; - } - else - [self errorWithFormat: @"registered message without a valid fid (%.16x)", fid]; - - return message; + return rc; } - (int) _saveOrSubmitChangesInMessageWithMID: (uint64_t) mid @@ -971,63 +645,22 @@ _prepareContextClass (struct mapistore_context *newMemCtx, save: (BOOL) isSave { int rc; - id message; - NSMutableDictionary *messageProperties; - NSString *messageURL; - uint64_t fid; - BOOL associated; + MAPIStoreMessage *message; + NSNumber *midKey; - messageProperties = [messages objectForKey: - [NSNumber numberWithUnsignedLongLong: mid]]; - if (messageProperties) + midKey = [NSNumber numberWithUnsignedLongLong: mid]; + message = [messages objectForKey: midKey]; + if (message) { - if ([[messageProperties - objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)] - isEqualToString: @"IPM.Schedule.Meeting.Request"]) - { - /* We silently discard invitation emails since this is already - handled internally by SOGo. */ - rc = MAPISTORE_SUCCESS; - } + rc = MAPISTORE_SUCCESS; + if (isSave) + [message save]; else - { - messageURL = [mapping urlFromID: mid]; - associated = [[messageProperties objectForKey: @"associated"] boolValue]; - if (messageURL) - { - if (associated) - message = [self lookupFAIObject: messageURL]; - else - message = [self lookupObject: messageURL]; - } - else - { - fid = [[messageProperties objectForKey: @"fid"] - unsignedLongLongValue]; - message = [self _createMessageOfClass: [messageProperties objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)] - associated: associated - withMID: mid inFID: fid]; - } - if (message) - { - if (associated) - [faiTable cleanupCaches]; - else - [messageTable cleanupCaches]; - - [message setMAPIProperties: messageProperties]; - if (isSave) - [message MAPISave]; - else - [message MAPISubmit]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERROR; - } + [message submit]; + [[message container] cleanupCaches]; } else - rc = MAPISTORE_ERR_NOT_FOUND; + rc = MAPISTORE_ERROR; return rc; } @@ -1059,47 +692,40 @@ _prepareContextClass (struct mapistore_context *newMemCtx, inRow: (struct SRow *) aRow withMID: (uint64_t) fmid { - MAPIStoreTable *table; - NSArray *children; - NSString *childURL, *folderURL, *childKey; + NSNumber *midKey; + MAPIStoreObject *child; NSInteger count; - NSDictionary *messageProperties; void *propValue; - uint64_t fid; - id valueObject; const char *propName; enum MAPITAGS tag; enum MAPISTATUS propRc; + struct mapistore_property_data *data; int rc; [self logWithFormat: @"METHOD '%s' -- fmid: 0x%.16x, tableType: %d", __FUNCTION__, fmid, tableType]; - childURL = [mapping urlFromID: fmid]; - if (childURL) + midKey = [NSNumber numberWithUnsignedLongLong: fmid]; + child = [messages objectForKey: midKey]; + if (child) { - childKey = [self extractChildNameFromURL: childURL - andFolderURLAt: &folderURL]; - fid = [mapping idFromURL: folderURL]; - if (fid == NSNotFound) - [NSException raise: @"MAPIStoreIOException" - format: @"no fid found for url '%@'", folderURL]; - - table = [self _tableForFID: fid andTableType: tableType]; - children = [table cachedChildKeys]; - if ([children containsObject: childKey]) - { + data = talloc_array (memCtx, struct mapistore_property_data, + sPropTagArray->cValues); + memset (data, 0, + sizeof (struct mapistore_property_data) * sPropTagArray->cValues); + rc = [child getProperties: data + withTags: sPropTagArray->aulPropTag + andCount: sPropTagArray->cValues]; + if (rc == MAPISTORE_SUCCESS) + { aRow->lpProps = talloc_array (aRow, struct SPropValue, sPropTagArray->cValues); aRow->cValues = sPropTagArray->cValues; for (count = 0; count < sPropTagArray->cValues; count++) { tag = sPropTagArray->aulPropTag[count]; - - propValue = NULL; - propRc = [table getChildProperty: &propValue - forKey: childKey - withTag: tag]; + propValue = data[count].data; + propRc = data[count].error; // propName = get_proptag_name (tag); // if (!propName) // propName = ""; @@ -1119,6 +745,10 @@ _prepareContextClass (struct mapistore_context *newMemCtx, if (propRc != MAPI_E_SUCCESS) { + if (propRc == MAPISTORE_ERR_NOT_FOUND) + propRc = MAPI_E_NOT_FOUND; + else if (propRc == MAPISTORE_ERR_NO_MEMORY) + propRc = MAPI_E_NOT_ENOUGH_MEMORY; if (propValue) talloc_free (propValue); propValue = MAPILongValue (memCtx, propRc); @@ -1126,45 +756,13 @@ _prepareContextClass (struct mapistore_context *newMemCtx, } set_SPropValue_proptag (aRow->lpProps + count, tag, propValue); } - rc = MAPI_E_SUCCESS; } - else - rc = MAPI_E_INVALID_OBJECT; + talloc_free (data); } else { - messageProperties = [messages objectForKey: - [NSNumber numberWithUnsignedLongLong: fmid]]; - if (messageProperties) - { - aRow->lpProps = talloc_array (aRow, struct SPropValue, - sPropTagArray->cValues); - aRow->cValues = sPropTagArray->cValues; - for (count = 0; count < sPropTagArray->cValues; count++) - { - tag = sPropTagArray->aulPropTag[count]; - - valueObject - = [messageProperties objectForKey: MAPIPropertyKey (tag)]; - if (valueObject) - propRc = [valueObject getMAPIValue: &propValue - forTag: tag - inMemCtx: memCtx]; - else - { - propValue = MAPILongValue (memCtx, MAPI_E_NOT_FOUND); - tag = (tag & 0xffff0000) | 0x000a; - } - - set_SPropValue_proptag (aRow->lpProps + count, tag, propValue); - } - rc = MAPI_E_SUCCESS; - } - else - { - [self errorWithFormat: @"No url found for FMID: %lld", fmid]; - rc = MAPI_E_INVALID_OBJECT; - } + [self errorWithFormat: @"no message/folder found for fmid %lld", fmid]; + rc = MAPI_E_INVALID_OBJECT; } return rc; @@ -1230,8 +828,9 @@ _prepareContextClass (struct mapistore_context *newMemCtx, ofTableType: (uint8_t) tableType inRow: (struct SRow *) aRow { - NSMutableDictionary *message; - NSNumber *midNbr; + MAPIStoreMessage *message; + NSMutableDictionary *properties; + NSNumber *midKey; struct SPropValue *cValue; NSUInteger counter; int rc; @@ -1242,19 +841,22 @@ _prepareContextClass (struct mapistore_context *newMemCtx, switch (tableType) { case MAPISTORE_MESSAGE: - midNbr = [NSNumber numberWithUnsignedLongLong: fmid]; - message = [messages objectForKey: midNbr]; + midKey = [NSNumber numberWithUnsignedLongLong: fmid]; + message = [messages objectForKey: midKey]; if (message) { + properties + = [NSMutableDictionary dictionaryWithCapacity: aRow->cValues]; [self logWithFormat: @"fmid 0x%.16x found", fmid]; for (counter = 0; counter < aRow->cValues; counter++) { cValue = aRow->lpProps + counter; - [message setObject: NSObjectFromSPropValue (cValue) - forKey: MAPIPropertyKey (cValue->ulPropTag)]; + [properties setObject: NSObjectFromSPropValue (cValue) + forKey: MAPIPropertyKey (cValue->ulPropTag)]; } + [message addNewProperties: properties]; [self logWithFormat: @"(%s) message props after op", __PRETTY_FUNCTION__]; - MAPIStoreDumpMessageProperties (message); + MAPIStoreDumpMessageProperties (properties); rc = MAPISTORE_SUCCESS; } else @@ -1280,7 +882,7 @@ _prepareContextClass (struct mapistore_context *newMemCtx, fromFile: (NSFileHandle *) aFile { NSMutableDictionary *message; - NSNumber *midNbr; + NSNumber *midKey; NSData *fileData; const char *propName; int rc; @@ -1295,8 +897,8 @@ _prepareContextClass (struct mapistore_context *newMemCtx, switch (tableType) { case MAPISTORE_MESSAGE: - midNbr = [NSNumber numberWithUnsignedLongLong: fmid]; - message = [messages objectForKey: midNbr]; + midKey = [NSNumber numberWithUnsignedLongLong: fmid]; + message = [messages objectForKey: midKey]; if (message) { [message setObject: NSObjectFromStreamData (property, fileData) @@ -1323,8 +925,8 @@ _prepareContextClass (struct mapistore_context *newMemCtx, ofTableType: (uint8_t) tableType intoFile: (NSFileHandle *) aFile { - NSMutableDictionary *message; - NSNumber *midNbr; + MAPIStoreMessage *message; + NSNumber *midKey; NSData *fileData; const char *propName; enum MAPISTATUS rc; @@ -1338,11 +940,11 @@ _prepareContextClass (struct mapistore_context *newMemCtx, switch (tableType) { case MAPISTORE_MESSAGE: - midNbr = [NSNumber numberWithUnsignedLongLong: fmid]; - message = [messages objectForKey: midNbr]; + midKey = [NSNumber numberWithUnsignedLongLong: fmid]; + message = [messages objectForKey: midKey]; if (message) { - fileData = [message objectForKey: MAPIPropertyKey (property)]; + fileData = [[message newProperties] objectForKey: MAPIPropertyKey (property)]; if ([fileData isKindOfClass: NSStringK]) fileData = [fileData dataUsingEncoding: NSUTF16LittleEndianStringEncoding]; /* TODO: only NSData is supported right now */ @@ -1439,7 +1041,9 @@ _prepareContextClass (struct mapistore_context *newMemCtx, withCount: (NSUInteger) max { static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" }; - NSMutableDictionary *message, *recipients; + MAPIStoreMessage *message; + NSDictionary *newProperties; + NSMutableDictionary *recipients; NSMutableArray *list; NSString *recType; struct ModifyRecipientRow *currentRow; @@ -1453,7 +1057,8 @@ _prepareContextClass (struct mapistore_context *newMemCtx, if (message) { recipients = [NSMutableDictionary new]; - [message setObject: recipients forKey: @"recipients"]; + newProperties = [NSDictionary dictionaryWithObject: recipients + forKey: @"recipients"]; [recipients release]; for (count = 0; count < max; count++) { @@ -1474,6 +1079,7 @@ _prepareContextClass (struct mapistore_context *newMemCtx, &(currentRow->RecipientRow)]]; } } + [message addNewProperties: newProperties]; rc = MAPISTORE_SUCCESS; } else @@ -1486,9 +1092,9 @@ _prepareContextClass (struct mapistore_context *newMemCtx, inFID: (uint64_t) fid withFlags: (uint8_t) flags { - NSString *childURL, *childKey; - MAPIStoreTable *table; - id message; + NSString *childURL, *folderURL, *childKey; + MAPIStoreFolder *folder; + MAPIStoreMessage *message; int rc; [self logWithFormat: @"-deleteMessageWithMID: mid: 0x%.16x flags: %d", mid, flags]; @@ -1499,22 +1105,12 @@ _prepareContextClass (struct mapistore_context *newMemCtx, [self logWithFormat: @"-deleteMessageWithMID: url (%@) found for object", childURL]; childKey = [self extractChildNameFromURL: childURL - andFolderURLAt: NULL]; - table = [self _tableForFID: fid andTableType: MAPISTORE_FAI_TABLE]; - if ([[table cachedChildKeys] containsObject: childKey]) - message = [self lookupFAIObject: childURL]; - else - { - table = [self _tableForFID: fid andTableType: MAPISTORE_MESSAGE_TABLE]; - if ([[table cachedChildKeys] containsObject: childKey]) - message = [self lookupObject: childURL]; - else - message = nil; - } - + andFolderURLAt: &folderURL]; + folder = [self lookupFolder: folderURL]; + message = [folder lookupChild: childKey]; if (message) { - if ([message delete]) + if ([[message sogoObject] delete]) { rc = MAPISTORE_ERROR; [self logWithFormat: @"ERROR deleting object at URL: %@", childURL]; @@ -1523,7 +1119,6 @@ _prepareContextClass (struct mapistore_context *newMemCtx, { [self logWithFormat: @"sucessfully deleted object at URL: %@", childURL]; [mapping unregisterURLWithID: mid]; - [table cleanupCaches]; rc = MAPISTORE_SUCCESS; } } @@ -1539,8 +1134,8 @@ _prepareContextClass (struct mapistore_context *newMemCtx, - (int) releaseRecordWithFMID: (uint64_t) fmid ofTableType: (uint8_t) tableType { - NSNumber *midNbr; - NSMutableDictionary *messageProperties; + NSNumber *midKey; + MAPIStoreMessage *message; NSUInteger retainCount; int rc; @@ -1548,23 +1143,20 @@ _prepareContextClass (struct mapistore_context *newMemCtx, { case MAPISTORE_MESSAGE_TABLE: rc = MAPISTORE_SUCCESS; - midNbr = [NSNumber numberWithUnsignedLongLong: fmid]; - messageProperties = [messages objectForKey: midNbr]; - if (messageProperties) + midKey = [NSNumber numberWithUnsignedLongLong: fmid]; + message = [messages objectForKey: midKey]; + if (message) { - retainCount = [[messageProperties objectForKey: @"mapiRetainCount"] - unsignedIntValue]; - if (retainCount == 1) + retainCount = [message mapiRetainCount]; + if (retainCount == 0) { [self logWithFormat: @"message with mid %.16x successfully removed" @" from message cache", fmid]; - [messages removeObjectForKey: midNbr]; + [messages removeObjectForKey: midKey]; } else - [messageProperties - setObject: [NSNumber numberWithUnsignedInt: retainCount - 1] - forKey: @"mapiRetainCount"]; + [message setMAPIRetainCount: retainCount - 1]; } else [self warnWithFormat: @"message with mid %.16x not found" @@ -1634,33 +1226,6 @@ _prepareContextClass (struct mapistore_context *newMemCtx, /* utils */ -- (void) registerValue: (id) value - asProperty: (enum MAPITAGS) property - forURL: (NSString *) url -{ - /* TODO: this method is a hack to enable the saving of property values which - need to be passed as streams. Must be removed after the - getProperty/setProperty mechanisms have been rethought. */ - NSMutableDictionary *message; - uint64_t fmid; - NSNumber *midNbr; - - fmid = [mapping idFromURL: url]; - if (fmid != NSNotFound) - { - midNbr = [NSNumber numberWithUnsignedLongLong: fmid]; - message = [messages objectForKey: midNbr]; - if (!message) - { - message = [NSMutableDictionary new]; - [messages setObject: message forKey: midNbr]; - [message release]; - [message setObject: midNbr forKey: @"mid"]; - } - [message setObject: value forKey: MAPIPropertyKey (property)]; - } -} - - (NSString *) extractChildNameFromURL: (NSString *) objectURL andFolderURLAt: (NSString **) folderURL; { @@ -1687,4 +1252,140 @@ _prepareContextClass (struct mapistore_context *newMemCtx, return childKey; } +- (uint64_t) idForObjectWithKey: (NSString *) key + inFolderURL: (NSString *) folderURL +{ + NSString *childURL; + uint64_t mappingId; + uint32_t contextId; + + mapping = [MAPIStoreMapping sharedMapping]; + + if (key) + childURL = [NSString stringWithFormat: @"%@%@", folderURL, key]; + else + childURL = folderURL; + mappingId = [mapping idFromURL: childURL]; + if (mappingId == NSNotFound) + { + openchangedb_get_new_folderID (ldbCtx, &mappingId); + [mapping registerURL: childURL withID: mappingId]; + contextId = 0; + mapistore_search_context_by_uri (memCtx, [folderURL UTF8String] + 7, + &contextId); + mapistore_indexing_record_add_mid (memCtx, contextId, mappingId); + } + + return mappingId; +} + +/* proof of concept */ +- (int) getAttachmentTable: (void **) tablePtr + andRowCount: (uint32_t *) count + withMID: (uint64_t) mid +{ + MAPIStoreAttachmentTable *attTable; + MAPIStoreMessage *message; + NSNumber *midKey; + int rc; + + rc = MAPISTORE_ERR_NOT_FOUND; + + midKey = [NSNumber numberWithUnsignedLongLong: mid]; + message = [messages objectForKey: midKey]; + if (message) + { + *count = [[message childKeysMatchingQualifier: nil + andSortOrderings: nil] count]; + attTable = [message attachmentTable]; + *tablePtr = attTable; + if (attTable) + { + [attTable retain]; + rc = MAPISTORE_SUCCESS; + } + } + + return rc; +} + +- (int) getAttachment: (void **) attachmentPtr + withAID: (uint32_t) aid + inMID: (uint64_t) mid +{ + MAPIStoreMessage *message; + MAPIStoreAttachment *attachment; + NSNumber *midKey; + NSArray *keys; + int rc; + + rc = MAPISTORE_ERR_NOT_FOUND; + + midKey = [NSNumber numberWithUnsignedLongLong: mid]; + message = [messages objectForKey: midKey]; + if (message) + { + keys = [message childKeysMatchingQualifier: nil + andSortOrderings: nil]; + if (aid < [keys count]) + { + attachment = [message lookupChild: [keys objectAtIndex: aid]]; + *attachmentPtr = attachment; + if (attachment) + { + [attachment retain]; + rc = MAPISTORE_SUCCESS; + } + } + } + + return rc; +} + +- (int) createAttachment: (void **) attachmentPtr + inAID: (uint32_t *) aid + withMessage: (uint64_t) mid +{ + MAPIStoreMessage *message; + MAPIStoreAttachment *attachment; + NSNumber *midKey; + int rc; + + rc = MAPISTORE_ERR_NOT_FOUND; + + midKey = [NSNumber numberWithUnsignedLongLong: mid]; + message = [messages objectForKey: midKey]; + if (message) + { + attachment = [message createAttachment]; + if (attachment) + { + [attachment retain]; + *attachmentPtr = attachment; + *aid = [attachment AID]; + rc = MAPISTORE_SUCCESS; + } + } + + return rc; +} + +/* subclasses */ + ++ (NSString *) MAPIModuleName +{ + [self subclassResponsibility: _cmd]; + + return nil; +} + ++ (void) registerFixedMappings: (MAPIStoreMapping *) storeMapping +{ +} + +- (void) setupBaseFolder: (NSURL *) newURL +{ + [self subclassResponsibility: _cmd]; +} + @end diff --git a/OpenChange/MAPIStoreDeletedItemsContext.h b/OpenChange/MAPIStoreDeletedItemsContext.h index 01e265e15..deec0e24b 100644 --- a/OpenChange/MAPIStoreDeletedItemsContext.h +++ b/OpenChange/MAPIStoreDeletedItemsContext.h @@ -23,9 +23,9 @@ #ifndef MAPISTOREDELETEDITEMSCONTEXT_H #define MAPISTOREDELETEDITEMSCONTEXT_H -#import "MAPIStoreMailContext.h" +#import "MAPIStoreMailBaseContext.h" -@interface MAPIStoreDeletedItemsContext : MAPIStoreMailContext +@interface MAPIStoreDeletedItemsContext : MAPIStoreMailBaseContext @end diff --git a/OpenChange/MAPIStoreDeletedItemsContext.m b/OpenChange/MAPIStoreDeletedItemsContext.m index 493a91ed9..fc9751fb4 100644 --- a/OpenChange/MAPIStoreDeletedItemsContext.m +++ b/OpenChange/MAPIStoreDeletedItemsContext.m @@ -22,15 +22,9 @@ #import -#import - +#import "MAPIStoreMailFolder.h" #import "MAPIStoreMapping.h" -#import - -#import "MAPIApplication.h" -#import "MAPIStoreAuthenticator.h" - #import "MAPIStoreDeletedItemsContext.h" @implementation MAPIStoreDeletedItemsContext @@ -46,40 +40,11 @@ withID: 0x170001]; } -- (void) setupModuleFolder +- (void) setupBaseFolder: (NSURL *) newURL { - SOGoUserFolder *userFolder; - SOGoMailAccounts *accountsFolder; - SOGoMailAccount *accountFolder; - SOGoFolder *currentContainer; - - userFolder = [SOGoUserFolder objectWithName: [authenticator username] - inContainer: MAPIApp]; - [parentFoldersBag addObject: userFolder]; - // [self logWithFormat: @"userFolder: %@", userFolder]; - [woContext setClientObject: userFolder]; - - accountsFolder = [userFolder lookupName: @"Mail" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: accountsFolder]; - // [self logWithFormat: @"accountsFolder: %@", accountsFolder]; - [woContext setClientObject: accountsFolder]; - - accountFolder = [accountsFolder lookupName: @"0" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: accountFolder]; - [woContext setClientObject: accountFolder]; - - moduleFolder = [accountFolder trashFolderInContext: nil]; - [moduleFolder retain]; - currentContainer = [moduleFolder container]; - while (currentContainer != (SOGoFolder *) accountFolder) - { - [parentFoldersBag addObject: currentContainer]; - currentContainer = [currentContainer container]; - } + baseFolder = [MAPIStoreDeletedItemsFolder baseFolderWithURL: newURL + inContext: self]; + [baseFolder retain]; } @end diff --git a/OpenChange/MAPIStoreDraftsContext.h b/OpenChange/MAPIStoreDraftsContext.h index fac1494be..4afcbbebd 100644 --- a/OpenChange/MAPIStoreDraftsContext.h +++ b/OpenChange/MAPIStoreDraftsContext.h @@ -23,9 +23,9 @@ #ifndef MAPISTOREDRAFTSCONTEXT_H #define MAPISTOREDRAFTSCONTEXT_H -#import "MAPIStoreMailContext.h" +#import "MAPIStoreMailBaseContext.h" -@interface MAPIStoreDraftsContext : MAPIStoreMailContext +@interface MAPIStoreDraftsContext : MAPIStoreMailBaseContext @end diff --git a/OpenChange/MAPIStoreDraftsContext.m b/OpenChange/MAPIStoreDraftsContext.m index 561132906..3115173c6 100644 --- a/OpenChange/MAPIStoreDraftsContext.m +++ b/OpenChange/MAPIStoreDraftsContext.m @@ -22,16 +22,9 @@ #import -#import - +#import "MAPIStoreMailFolder.h" #import "MAPIStoreMapping.h" -#import -#import - -#import "MAPIApplication.h" -#import "MAPIStoreAuthenticator.h" - #import "MAPIStoreDraftsContext.h" @implementation MAPIStoreDraftsContext @@ -43,50 +36,15 @@ + (void) registerFixedMappings: (MAPIStoreMapping *) mapping { - [mapping registerURL: @"sogo://openchange:openchange@drafts/" - withID: 0x1e0001]; + [mapping registerURL: @"sogo://openchange:openchange@inbox/" + withID: 0x1e0001]; } -- (void) setupModuleFolder +- (void) setupBaseFolder: (NSURL *) newURL { - SOGoUserFolder *userFolder; - SOGoMailAccounts *accountsFolder; - SOGoMailAccount *accountFolder; - SOGoFolder *currentContainer; - - userFolder = [SOGoUserFolder objectWithName: [authenticator username] - inContainer: MAPIApp]; - [parentFoldersBag addObject: userFolder]; - // [self logWithFormat: @"userFolder: %@", userFolder]; - [woContext setClientObject: userFolder]; - - accountsFolder = [userFolder lookupName: @"Mail" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: accountsFolder]; - // [self logWithFormat: @"accountsFolder: %@", accountsFolder]; - [woContext setClientObject: accountsFolder]; - - accountFolder = [accountsFolder lookupName: @"0" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: accountFolder]; - [woContext setClientObject: accountFolder]; - - moduleFolder = [accountFolder draftsFolderInContext: nil]; - [moduleFolder retain]; - currentContainer = [moduleFolder container]; - while (currentContainer != (SOGoFolder *) accountFolder) - { - [parentFoldersBag addObject: currentContainer]; - currentContainer = [currentContainer container]; - } -} - -- (id) createMessageOfClass: (NSString *) messageClass - inFolderAtURL: (NSString *) folderURL; -{ - return [moduleFolder newDraft]; + baseFolder = [MAPIStoreDraftsFolder baseFolderWithURL: newURL + inContext: self]; + [baseFolder retain]; } @end diff --git a/OpenChange/MAPIStoreFSBaseContext.m b/OpenChange/MAPIStoreFSBaseContext.m index e817921ae..d57225056 100644 --- a/OpenChange/MAPIStoreFSBaseContext.m +++ b/OpenChange/MAPIStoreFSBaseContext.m @@ -28,7 +28,7 @@ #import -#import "MAPIStoreFSMessageTable.h" +#import "MAPIStoreFSFolder.h" #import "MAPIStoreMapping.h" #import "SOGoMAPIFSFolder.h" @@ -37,34 +37,26 @@ #undef DEBUG #include +static Class MAPIStoreFSFolderK; + @implementation MAPIStoreFSBaseContext ++ (void) initialize +{ + MAPIStoreFSFolderK = [MAPIStoreFSFolder class]; +} + + (NSString *) MAPIModuleName { return nil; } -- (void) setupModuleFolder +- (void) setupBaseFolder: (NSURL *) newURL { [self logWithFormat: @"invoked %s", __PRETTY_FUNCTION__]; - moduleFolder = [SOGoMAPIFSFolder folderWithURL: [NSURL URLWithString: uri] - andTableType: MAPISTORE_MESSAGE_TABLE]; - [moduleFolder retain]; -} - -- (Class) messageTableClass -{ - return [MAPIStoreFSMessageTable class]; -} - -- (id) createMessageOfClass: (NSString *) messageClass - inFolderAtURL: (NSString *) folderURL; -{ - SOGoMAPIFSFolder *parentFolder; - - parentFolder = [self lookupObject: folderURL]; - - return [parentFolder newMessage]; + baseFolder = [MAPIStoreFSFolderK baseFolderWithURL: newURL + inContext: self]; + [baseFolder retain]; } @end diff --git a/OpenChange/MAPIStoreFSFolder.h b/OpenChange/MAPIStoreFSFolder.h new file mode 100644 index 000000000..75e3f08e5 --- /dev/null +++ b/OpenChange/MAPIStoreFSFolder.h @@ -0,0 +1,33 @@ +/* MAPIStoreFSFolder.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 MAPISTOREFSFOLDER_H +#define MAPISTOREFSFOLDER_H + +#import "MAPIStoreFolder.h" + +@interface MAPIStoreFSFolder : MAPIStoreFolder + +@end + + +#endif /* MAPISTOREFSFOLDER_H */ diff --git a/OpenChange/MAPIStoreFSFolder.m b/OpenChange/MAPIStoreFSFolder.m new file mode 100644 index 000000000..4ce217935 --- /dev/null +++ b/OpenChange/MAPIStoreFSFolder.m @@ -0,0 +1,128 @@ +/* MAPIStoreFSFolder.m - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 "EOQualifier+MAPIFS.h" +#import "MAPIStoreFSMessage.h" +#import "SOGoMAPIFSFolder.h" +#import "SOGoMAPIFSMessage.h" + +#import "MAPIStoreFSFolder.h" + +#undef DEBUG +#include +// #include +// #include +// #include + +static Class MAPIStoreFSMessageK; + +@implementation MAPIStoreFSFolder + ++ (void) initialize +{ + MAPIStoreFSMessageK = [MAPIStoreFSMessage class]; +} + +- (id) initWithURL: (NSURL *) newURL + inContext: (MAPIStoreContext *) newContext +{ + if ((self = [super initWithURL: newURL + inContext: newContext])) + { + sogoObject = [SOGoMAPIFSFolder folderWithURL: newURL + andTableType: MAPISTORE_MESSAGE_TABLE]; + [sogoObject retain]; + } + + return self; +} + +- (MAPIStoreMessageTable *) messageTable +{ + if (!messageTable) + ASSIGN (messageTable, + [MAPIStoreFSMessageTable tableForContainer: self]); + + return messageTable; +} + +- (Class) messageClass +{ + return MAPIStoreFSMessageK; +} + +- (MAPIStoreMessage *) createMessage +{ + MAPIStoreMessage *newMessage; + SOGoMAPIFSMessage *fsObject; + NSString *newKey; + + newKey = [NSString stringWithFormat: @"%@.plist", + [SOGoObject globallyUniqueObjectId]]; + fsObject = [SOGoMAPIFSMessage objectWithName: newKey inContainer: faiFolder]; + newMessage = [MAPIStoreFSMessage mapiStoreObjectWithSOGoObject: fsObject + inContainer: self]; + + + return newMessage; +} + +- (NSArray *) childKeysMatchingQualifier: (EOQualifier *) qualifier + andSortOrderings: (NSArray *) sortOrderings +{ + NSArray *allKeys; + NSMutableArray *keys; + NSUInteger count, max; + NSString *messageKey; + SOGoMAPIFSMessage *message; + + if (sortOrderings) + [self warnWithFormat: @"sorting is not handled yet"]; + + allKeys = [sogoObject toOneRelationshipKeys]; + if (qualifier) + { + [self logWithFormat: @"%s: getting restricted keys", __PRETTY_FUNCTION__]; + max = [allKeys count]; + keys = [NSMutableArray arrayWithCapacity: max]; + for (count = 0; count < max; count++) + { + messageKey = [allKeys objectAtIndex: count]; + message = [sogoObject lookupName: messageKey + inContext: nil + acquire: NO]; + if ([qualifier evaluateMAPIFSMessage: message]) + [keys addObject: messageKey]; + } + [self logWithFormat: @" resulting keys: $$$%@$$$", keys]; + } + else + keys = (NSMutableArray *) allKeys; + + return keys; +} + +@end diff --git a/OpenChange/MAPIStoreFolder.h b/OpenChange/MAPIStoreFolder.h new file mode 100644 index 000000000..16a5a6d15 --- /dev/null +++ b/OpenChange/MAPIStoreFolder.h @@ -0,0 +1,84 @@ +/* MAPIStoreFolder.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 MAPISTOREFOLDER_H +#define MAPISTOREFOLDER_H + +#import + +#import "MAPIStoreTable.h" + +@class NSMutableArray; +@class NSURL; + +@class EOQualifier; + +@class MAPIStoreContext; +@class MAPIStoreMessage; +@class MAPIStoreFSMessageTable; +@class MAPIStoreFolderTable; +@class MAPIStoreMessageTable; +@class SOGoMAPIFSFolder; + +#import "MAPIStoreObject.h" + +@interface MAPIStoreFolder : MAPIStoreObject +{ + NSURL *folderURL; + MAPIStoreContext *context; + MAPIStoreMessageTable *messageTable; + NSArray *messageKeys; + MAPIStoreFSMessageTable *faiMessageTable; + NSArray *faiMessageKeys; + MAPIStoreFolderTable *folderTable; + NSMutableArray *folderKeys; + + SOGoMAPIFSFolder *faiFolder; +} + ++ (id) baseFolderWithURL: (NSURL *) newURL + inContext: (MAPIStoreContext *) newContext; +- (id) initWithURL: (NSURL *) newURL + inContext: (MAPIStoreContext *) newContext; + +- (MAPIStoreMessageTable *) messageTable; +- (NSArray *) messageKeys; + +- (MAPIStoreFSMessageTable *) faiMessageTable; +- (NSArray *) faiMessageKeys; + +- (MAPIStoreFolderTable *) folderTable; +- (NSArray *) folderKeys; + +- (MAPIStoreMessage *) createMessage: (BOOL) isAssociated; +- (NSString *) createFolder: (struct SRow *) aRow; + +/* helpers */ +- (uint64_t) idForObjectWithKey: (NSString *) childKey; + +/* subclasses */ +- (Class) messageClass; +- (MAPIStoreMessage *) createMessage; + +@end + +#endif /* MAPISTOREFOLDER_H */ diff --git a/OpenChange/MAPIStoreFolder.m b/OpenChange/MAPIStoreFolder.m new file mode 100644 index 000000000..dcd8baac9 --- /dev/null +++ b/OpenChange/MAPIStoreFolder.m @@ -0,0 +1,356 @@ +/* MAPIStoreFolder.m - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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. + */ + +/* TODO: main key arrays must be initialized */ + +#import +#import +#import +#import +#import +#import + +#import "MAPIStoreContext.h" +#import "MAPIStoreFSMessage.h" +#import "MAPIStoreFSMessageTable.h" +#import "MAPIStoreFolder.h" +#import "MAPIStoreMessage.h" +#import "MAPIStoreTypes.h" +#import "NSString+MAPIStore.h" +#import "SOGoMAPIFSFolder.h" +#import "SOGoMAPIFSMessage.h" + +#include + +#undef DEBUG +#include +#include +// #include + +Class NSExceptionK; + +@implementation MAPIStoreFolder + ++ (void) initialize +{ + NSExceptionK = [NSException class]; +} + ++ (id) baseFolderWithURL: (NSURL *) newURL + inContext: (MAPIStoreContext *) newContext +{ + id newFolder; + + newFolder = [[self alloc] initWithURL: newURL inContext: newContext]; + [newFolder autorelease]; + + return newFolder; +} + +- (id) init +{ + if ((self = [super init])) + { + messageTable = nil; + messageKeys = nil; + faiMessageTable = nil; + faiMessageKeys = nil; + folderTable = nil; + folderKeys = nil; + faiFolder = nil; + folderURL = nil; + context = nil; + } + + return self; +} + +- (id) initWithURL: (NSURL *) newURL + inContext: (MAPIStoreContext *) newContext +{ + if ((self = [self init])) + { + context = newContext; + ASSIGN (folderURL, newURL); + ASSIGN (faiFolder, + [SOGoMAPIFSFolder folderWithURL: newURL + andTableType: MAPISTORE_FAI_TABLE]); + } + + return self; +} + +- (void) dealloc +{ + [folderURL release]; + [messageTable release]; + [messageKeys release]; + [faiMessageTable release]; + [faiMessageKeys release]; + [folderTable release]; + [folderKeys release]; + [faiFolder release]; + [super dealloc]; +} + +- (MAPIStoreContext *) context +{ + if (!context) + context = [container context]; + + return context; +} + +- (NSArray *) messageKeys +{ + if (!messageKeys) + { + messageKeys = [self childKeysMatchingQualifier: nil + andSortOrderings: nil]; + [messageKeys retain]; + } + + return messageKeys; +} + +- (MAPIStoreFSMessageTable *) faiMessageTable +{ + if (!faiMessageTable) + { + faiMessageTable = [MAPIStoreFSMessageTable tableForContainer: self]; + [faiMessageTable retain]; + } + + return faiMessageTable; +} + +- (NSArray *) faiMessageKeys +{ + if (!faiMessageKeys) + { + faiMessageKeys = [faiFolder toOneRelationshipKeys]; + [faiMessageKeys retain]; + } + + return faiMessageKeys; +} + +- (MAPIStoreFolderTable *) folderTable +{ + return nil; +} + +- (NSArray *) folderKeys +{ + if (!faiMessageKeys) + faiMessageKeys = [NSArray new]; + + return faiMessageKeys; +} + +- (void) cleanupCaches +{ + [faiMessageTable cleanupCaches]; + [faiMessageKeys release]; + faiMessageKeys = nil; + [messageTable cleanupCaches]; + [messageKeys release]; + messageKeys = nil; + [folderTable cleanupCaches]; + [folderKeys release]; + folderKeys = nil; +} + +- (id) lookupChild: (NSString *) childKey +{ + MAPIStoreObject *newChild; + SOGoObject *msgObject; + + if (childKey) + { + [self faiMessageKeys]; + if ([faiMessageKeys containsObject: childKey]) + { + msgObject = [faiFolder lookupName: childKey + inContext: nil + acquire: NO]; + newChild + = [MAPIStoreFSMessage mapiStoreObjectWithSOGoObject: msgObject + inContainer: self]; + } + else + { + msgObject = [sogoObject lookupName: childKey + inContext: nil + acquire: NO]; + if ([msgObject isKindOfClass: NSExceptionK]) + msgObject = nil; + + if (msgObject) + newChild + = [[self messageClass] mapiStoreObjectWithSOGoObject: msgObject + inContainer: self]; + else + newChild = nil; + } + } + else + newChild = nil; + + return newChild; +} + +- (enum MAPISTATUS) getProperty: (void **) data + withTag: (enum MAPITAGS) propTag +{ + int rc; + + rc = MAPI_E_SUCCESS; + switch (propTag) + { + case PR_FID: + /* TODO: incomplete */ + *data = MAPILongValue (memCtx, [self objectId]); + break; + case PR_ACCESS: // TODO + *data = MAPILongValue (memCtx, 0x63); + break; + case PR_ACCESS_LEVEL: // TODO + *data = MAPILongValue (memCtx, 0x01); + break; + case PR_PARENT_FID: + *data = MAPILongLongValue (memCtx, [container objectId]); + break; + case PR_ATTR_HIDDEN: + case PR_ATTR_SYSTEM: + case PR_ATTR_READONLY: + *data = MAPIBoolValue (memCtx, NO); + break; + case PR_SUBFOLDERS: + *data = MAPIBoolValue (memCtx, [folderKeys count]); + // [[child toManyRelationshipKeys] count] > 0); + break; + case PR_CONTENT_COUNT: + *data = MAPILongValue (memCtx, [messageKeys count]); + break; + // case PR_EXTENDED_FOLDER_FLAGS: // TODO: DOUBT: how to indicate the + // // number of subresponses ? + // binaryValue = talloc_zero(memCtx, struct Binary_r); + // *data = binaryValue; + // break; + default: + rc = [super getProperty: data + withTag: propTag]; + } + + return rc; +} + +- (MAPIStoreMessage *) _createAssociatedMessage +{ + MAPIStoreMessage *newMessage; + SOGoMAPIFSMessage *fsObject; + NSString *newKey; + + newKey = [NSString stringWithFormat: @"%@.plist", + [SOGoObject globallyUniqueObjectId]]; + fsObject = [SOGoMAPIFSMessage objectWithName: newKey inContainer: faiFolder]; + newMessage = [MAPIStoreFSMessage mapiStoreObjectWithSOGoObject: fsObject + inContainer: self]; + + + return newMessage; +} + +- (MAPIStoreMessage *) createMessage: (BOOL) isAssociated +{ + MAPIStoreMessage *newMessage; + + if (isAssociated) + newMessage = [self _createAssociatedMessage]; + else + newMessage = [self createMessage]; + + return newMessage; +} + +- (NSString *) createFolder: (struct SRow *) aRow +{ + [self errorWithFormat: @"new folders cannot be created in this context"]; + + return nil; +} + +/* helpers */ + +- (NSString *) url +{ + NSString *url; + + if (folderURL) + url = [folderURL absoluteString]; + else + url = [NSString stringWithFormat: @"%@/", [super url]]; + + return url; +} + +- (uint64_t) objectId +{ + uint64_t objectId; + + if (folderURL) + objectId = [self idForObjectWithKey: nil]; + else + objectId = [super objectId]; + + return objectId; +} + +- (uint64_t) idForObjectWithKey: (NSString *) childKey +{ + return [[self context] idForObjectWithKey: childKey + inFolderURL: [self url]]; +} + +/* subclasses */ + +- (MAPIStoreMessageTable *) messageTable +{ + return nil; +} + +- (Class) messageClass +{ + [self subclassResponsibility: _cmd]; + + return Nil; +} + +- (MAPIStoreMessage *) createMessage +{ + [self subclassResponsibility: _cmd]; + + return nil; +} + +@end diff --git a/OpenChange/MAPIStoreFreebusyContext.m b/OpenChange/MAPIStoreFreebusyContext.m index b6813e167..77b5d21b6 100644 --- a/OpenChange/MAPIStoreFreebusyContext.m +++ b/OpenChange/MAPIStoreFreebusyContext.m @@ -43,19 +43,19 @@ withID: 0x70001]; } -- (void) setupModuleFolder -{ - SOGoUserFolder *userFolder; +// - (void) setupModuleFolder +// { +// SOGoUserFolder *userFolder; - userFolder = [SOGoUserFolder objectWithName: [authenticator username] - inContainer: MAPIApp]; - [parentFoldersBag addObject: userFolder]; - [woContext setClientObject: userFolder]; +// userFolder = [SOGoUserFolder objectWithName: [authenticator username] +// inContainer: MAPIApp]; +// [parentFoldersBag addObject: userFolder]; +// [woContext setClientObject: userFolder]; - moduleFolder = [userFolder lookupName: @"Calendar" - inContext: woContext - acquire: NO]; - [moduleFolder retain]; -} +// moduleFolder = [userFolder lookupName: @"Calendar" +// inContext: woContext +// acquire: NO]; +// [moduleFolder retain]; +// } @end diff --git a/OpenChange/MAPIStoreGCSFolder.h b/OpenChange/MAPIStoreGCSFolder.h new file mode 100644 index 000000000..691d620a5 --- /dev/null +++ b/OpenChange/MAPIStoreGCSFolder.h @@ -0,0 +1,35 @@ +/* MAPIStoreGCSFolder.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 MAPISTOREGCSFOLDER_H +#define MAPISTOREGCSFOLDER_H + +#import "MAPIStoreFolder.h" + +@interface MAPIStoreGCSFolder : MAPIStoreFolder + +/* subclasses */ +- (EOQualifier *) componentQualifier; + +@end + +#endif /* MAPISTOREGCSFOLDER_H */ diff --git a/OpenChange/MAPIStoreGCSFolder.m b/OpenChange/MAPIStoreGCSFolder.m new file mode 100644 index 000000000..c42b9bf7a --- /dev/null +++ b/OpenChange/MAPIStoreGCSFolder.m @@ -0,0 +1,82 @@ +/* MAPIStoreGCSFolder.m - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 +#import +#import + +#import "MAPIStoreGCSFolder.h" + +@implementation MAPIStoreGCSFolder + +- (NSArray *) childKeysMatchingQualifier: (EOQualifier *) qualifier + andSortOrderings: (NSArray *) sortOrderings +{ + static NSArray *fields = nil; + NSArray *records; + EOQualifier *componentQualifier, *fetchQualifier; + GCSFolder *ocsFolder; + EOFetchSpecification *fs; + NSArray *keys; + + if (!fields) + fields = [[NSArray alloc] + initWithObjects: @"c_name", @"c_version", nil]; + + componentQualifier = [self componentQualifier]; + if (qualifier) + { + fetchQualifier = [[EOAndQualifier alloc] + initWithQualifiers: + componentQualifier, + qualifier, + nil]; + [fetchQualifier autorelease]; + } + else + fetchQualifier = componentQualifier; + + ocsFolder = [sogoObject ocsFolder]; + fs = [EOFetchSpecification + fetchSpecificationWithEntityName: [ocsFolder folderName] + qualifier: fetchQualifier + sortOrderings: sortOrderings]; + records = [ocsFolder fetchFields: fields fetchSpecification: fs]; + keys = [records objectsForKey: @"c_name" + notFoundMarker: nil]; + + return keys; +} + +/* subclasses */ + +- (EOQualifier *) componentQualifier +{ + [self subclassResponsibility: _cmd]; + + return nil; +} + +@end diff --git a/OpenChange/MAPIStoreInboxContext.h b/OpenChange/MAPIStoreInboxContext.h new file mode 100644 index 000000000..2f2f50aae --- /dev/null +++ b/OpenChange/MAPIStoreInboxContext.h @@ -0,0 +1,32 @@ +/* MAPIStoreInboxContext.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 MAPISTOREINBOXCONTEXT_H +#define MAPISTOREINBOXCONTEXT_H + +#import "MAPIStoreMailBaseContext.h" + +@interface MAPIStoreInboxContext : MAPIStoreMailBaseContext + +@end + +#endif /* MAPISTOREINBOXCONTEXT_H */ diff --git a/OpenChange/MAPIStoreInboxContext.m b/OpenChange/MAPIStoreInboxContext.m new file mode 100644 index 000000000..13536eb71 --- /dev/null +++ b/OpenChange/MAPIStoreInboxContext.m @@ -0,0 +1,50 @@ +/* MAPIStoreInboxContext.m - this file is part of $PROJECT_NAME_HERE$ + * + * Copyright (C) 2011 Inverse inc + * + * 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 "MAPIStoreMailFolder.h" +#import "MAPIStoreMapping.h" + +#import "MAPIStoreInboxContext.h" + +@implementation MAPIStoreInboxContext + ++ (NSString *) MAPIModuleName +{ + return @"inbox"; +} + ++ (void) registerFixedMappings: (MAPIStoreMapping *) mapping +{ + [mapping registerURL: @"sogo://openchange:openchange@inbox/" + withID: 0x160001]; +} + +- (void) setupBaseFolder: (NSURL *) newURL +{ + baseFolder = [MAPIStoreInboxFolder baseFolderWithURL: newURL + inContext: self]; + [baseFolder retain]; +} + +@end diff --git a/OpenChange/MAPIStoreMailContext.h b/OpenChange/MAPIStoreMailBaseContext.h similarity index 89% rename from OpenChange/MAPIStoreMailContext.h rename to OpenChange/MAPIStoreMailBaseContext.h index 750eff03e..8615a274b 100644 --- a/OpenChange/MAPIStoreMailContext.h +++ b/OpenChange/MAPIStoreMailBaseContext.h @@ -1,4 +1,4 @@ -/* MAPIStoreMailContext.h - this file is part of SOGo +/* MAPIStoreMailBaseContext.h - this file is part of SOGo * * Copyright (C) 2010 Inverse inc. * @@ -25,7 +25,7 @@ #import "MAPIStoreContext.h" -@interface MAPIStoreMailContext : MAPIStoreContext +@interface MAPIStoreMailBaseContext : MAPIStoreContext @end diff --git a/OpenChange/MAPIStoreMailBaseContext.m b/OpenChange/MAPIStoreMailBaseContext.m new file mode 100644 index 000000000..e728ba751 --- /dev/null +++ b/OpenChange/MAPIStoreMailBaseContext.m @@ -0,0 +1,32 @@ +/* MAPIStoreMailBaseContext.m - this file is part of SOGo + * + * Copyright (C) 2010 Inverse inc. + * + * 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 3, 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 "MAPIStoreMailBaseContext.h" + +@implementation MAPIStoreMailBaseContext + ++ (NSString *) MAPIModuleName +{ + return nil; +} + +@end diff --git a/OpenChange/MAPIStoreMailContext.m b/OpenChange/MAPIStoreMailContext.m deleted file mode 100644 index fb4f0ce58..000000000 --- a/OpenChange/MAPIStoreMailContext.m +++ /dev/null @@ -1,159 +0,0 @@ -/* MAPIStoreMailContext.m - this file is part of SOGo - * - * Copyright (C) 2010 Inverse inc. - * - * 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 3, 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 -#import -#import - -#import - -#import "MAPIApplication.h" -#import "MAPIStoreAuthenticator.h" -#import "MAPIStoreMailFolderTable.h" -#import "MAPIStoreMailMessageTable.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreTypes.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreMailContext.h" - -#undef DEBUG -#include - -@implementation MAPIStoreMailContext - -+ (NSString *) MAPIModuleName -{ - return @"inbox"; -} - -+ (void) registerFixedMappings: (MAPIStoreMapping *) mapping -{ - [mapping registerURL: @"sogo://openchange:openchange@inbox/" - withID: 0x160001]; -} - -- (void) setupModuleFolder -{ - SOGoUserFolder *userFolder; - SOGoMailAccounts *accountsFolder; - SOGoMailAccount *accountFolder; - SOGoFolder *currentContainer; - - userFolder = [SOGoUserFolder objectWithName: [authenticator username] - inContainer: MAPIApp]; - [parentFoldersBag addObject: userFolder]; - [woContext setClientObject: userFolder]; - - accountsFolder = [userFolder lookupName: @"Mail" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: accountsFolder]; - [woContext setClientObject: accountsFolder]; - - accountFolder = [accountsFolder lookupName: @"0" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: accountFolder]; - [woContext setClientObject: accountFolder]; - - moduleFolder = [accountFolder inboxFolderInContext: nil]; - [moduleFolder retain]; - currentContainer = [moduleFolder container]; - while (currentContainer != (SOGoFolder *) accountFolder) - { - [parentFoldersBag addObject: currentContainer]; - currentContainer = [currentContainer container]; - } - - [self logWithFormat: @"moduleFolder: %@", moduleFolder]; -} - -- (Class) messageTableClass -{ - return [MAPIStoreMailMessageTable class]; -} - -- (Class) folderTableClass -{ - return [MAPIStoreMailFolderTable class]; -} - -- (int) openMessage: (struct mapistore_message *) msg - forKey: (NSString *) childKey - inTable: (MAPIStoreTable *) table -{ - SOGoMailObject *child; - int rc; - struct SRowSet *recipients; - NSArray *to; - NSInteger count, max; - NGImap4EnvelopeAddress *currentAddress; - NSString *name; - - rc = [super openMessage: msg forKey: childKey inTable: table]; - - if (rc == MAPI_E_SUCCESS && table == messageTable) - { - child = [[table folder] lookupName: childKey inContext: nil acquire: NO]; - /* Retrieve recipients from the message */ - to = [child toEnvelopeAddresses]; - max = [to count]; - recipients = talloc_zero (memCtx, struct SRowSet); - recipients->cRows = max; - recipients->aRow = talloc_array (recipients, struct SRow, max); - for (count = 0; count < max; count++) - { - recipients->aRow[count].ulAdrEntryPad = 0; - recipients->aRow[count].cValues = 2; - recipients->aRow[count].lpProps = talloc_array (recipients->aRow, - struct SPropValue, - 2); - - // TODO (0x01 = primary recipient) - set_SPropValue_proptag (&(recipients->aRow[count].lpProps[0]), - PR_RECIPIENT_TYPE, - MAPILongValue (memCtx, 0x01)); - - currentAddress = [to objectAtIndex: count]; - // name = [currentAddress personalName]; - // if (![name length]) - name = [currentAddress baseEMail]; - if (!name) - name = @""; - set_SPropValue_proptag (&(recipients->aRow[count].lpProps[1]), - PR_DISPLAY_NAME, - [name asUnicodeInMemCtx: recipients->aRow[count].lpProps]); - } - msg->recipients = recipients; - } - - return rc; -} - -@end diff --git a/OpenChange/MAPIStoreMailFolder.h b/OpenChange/MAPIStoreMailFolder.h new file mode 100644 index 000000000..8479cc729 --- /dev/null +++ b/OpenChange/MAPIStoreMailFolder.h @@ -0,0 +1,57 @@ +/* MAPIStoreMailFolder.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 MAPISTOREMAILFOLDER_H +#define MAPISTOREMAILFOLDER_H + +#import "MAPIStoreFolder.h" + +@class WOContext; + +@class SOGoMailAccount; +@class SOGoMailFolder; + +@interface MAPIStoreMailFolder : MAPIStoreFolder + +/* subclasses */ +- (SOGoMailFolder *) specialFolderFromAccount: (SOGoMailAccount *) account + inContext: (WOContext *) woContext; + + +@end + +@interface MAPIStoreInboxFolder : MAPIStoreMailFolder +@end + +@interface MAPIStoreSentItemsFolder : MAPIStoreMailFolder +@end + +@interface MAPIStoreDraftsFolder : MAPIStoreMailFolder +@end + +@interface MAPIStoreDeletedItemsFolder : MAPIStoreMailFolder +@end + +@interface MAPIStoreOutboxFolder : MAPIStoreMailFolder +@end + +#endif /* MAPISTOREMAILFOLDER_H */ diff --git a/OpenChange/MAPIStoreMailFolder.m b/OpenChange/MAPIStoreMailFolder.m new file mode 100644 index 000000000..d549a005e --- /dev/null +++ b/OpenChange/MAPIStoreMailFolder.m @@ -0,0 +1,306 @@ +/* MAPIStoreMailFolder.m - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import "MAPIApplication.h" +#import "MAPIStoreContext.h" +#import "MAPIStoreDraftsMessage.h" +#import "MAPIStoreMailMessage.h" +#import "MAPIStoreMailMessageTable.h" +#import "MAPIStoreMailFolderTable.h" +#import "MAPIStoreTypes.h" +#import "NSString+MAPIStore.h" + +#import "MAPIStoreMailFolder.h" + +static Class MAPIStoreDraftsMessageK; +static Class MAPIStoreMailMessageK; + +@implementation MAPIStoreMailFolder + ++ (void) initialize +{ + MAPIStoreMailMessageK = [MAPIStoreMailMessage class]; +} + +- (id) initWithURL: (NSURL *) newURL + inContext: (MAPIStoreContext *) newContext +{ + SOGoUserFolder *userFolder; + SOGoMailAccounts *accountsFolder; + SOGoMailAccount *accountFolder; + SOGoFolder *currentContainer; + WOContext *woContext; + + if ((self = [super initWithURL: newURL + inContext: newContext])) + { + woContext = [newContext woContext]; + userFolder = [SOGoUserFolder objectWithName: [newURL user] + inContainer: MAPIApp]; + [parentContainersBag addObject: userFolder]; + [woContext setClientObject: userFolder]; + + accountsFolder = [userFolder lookupName: @"Mail" + inContext: woContext + acquire: NO]; + [parentContainersBag addObject: accountsFolder]; + [woContext setClientObject: accountsFolder]; + + accountFolder = [accountsFolder lookupName: @"0" + inContext: woContext + acquire: NO]; + [parentContainersBag addObject: accountFolder]; + [woContext setClientObject: accountFolder]; + + sogoObject = [self specialFolderFromAccount: accountFolder + inContext: woContext]; + [sogoObject retain]; + currentContainer = [sogoObject container]; + while (currentContainer != (SOGoFolder *) accountFolder) + { + [parentContainersBag addObject: currentContainer]; + currentContainer = [currentContainer container]; + } + + [self logWithFormat: @"sogoObject: %@", sogoObject]; + } + + return self; +} + +- (SOGoMailFolder *) specialFolderFromAccount: (SOGoMailAccount *) accountFolder + inContext: (WOContext *) woContext +{ + [self subclassResponsibility: _cmd]; + + return nil; +} + +- (MAPIStoreMessageTable *) messageTable +{ + if (!messageTable) + ASSIGN (messageTable, + [MAPIStoreMailMessageTable tableForContainer: self]); + + return messageTable; +} + +- (Class) messageClass +{ + return MAPIStoreMailMessageK; +} + +- (NSString *) createFolder: (struct SRow *) aRow +{ + return nil; + // NSString *newFolderURL; + // NSString *folderName, *nameInContainer; + // SOGoFolder *parentFolder, *newFolder; + // int i; + + // newFolderURL = nil; + + // folderName = nil; + // for (i = 0; !folderName && i < aRow->cValues; i++) + // { + // if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME_UNICODE) + // folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszW]; + // else if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME) + // folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszA]; + // } + + // if (folderName) + // { + // parentFolder = [self lookupObject: parentFolderURL]; + // if (parentFolder) + // { + // if ([parentFolder isKindOfClass: SOGoMailAccountK] + // || [parentFolder isKindOfClass: SOGoMailFolderK]) + // { + // nameInContainer = [NSString stringWithFormat: @"folder%@", + // [folderName asCSSIdentifier]]; + // newFolder = [SOGoMailFolderK objectWithName: nameInContainer + // inContainer: parentFolder]; + // if ([newFolder create]) + // newFolderURL = [NSString stringWithFormat: @"%@/%@", + // parentFolderURL, + // [nameInContainer stringByEscapingURL]]; + // } + // } + // } + + // return newFolderURL; +} + +- (enum MAPISTATUS) getProperty: (void **) data + withTag: (enum MAPITAGS) propTag +{ + enum MAPISTATUS rc; + EOQualifier *searchQualifier; + uint32_t intValue; + + rc = MAPI_E_SUCCESS; + switch (propTag) + { + case PR_CONTENT_UNREAD: + searchQualifier + = [EOQualifier qualifierWithQualifierFormat: @"flags = %@", @"unseen"]; + intValue = [[sogoObject fetchUIDsMatchingQualifier: searchQualifier + sortOrdering: nil] count]; + *data = MAPILongValue (memCtx, intValue); + break; + case PR_CONTAINER_CLASS_UNICODE: + *data = [@"IPF.Note" asUnicodeInMemCtx: memCtx]; + break; + default: + rc = [super getProperty: data withTag: propTag]; + } + + return rc; +} + +- (NSArray *) childKeysMatchingQualifier: (EOQualifier *) qualifier + andSortOrderings: (NSArray *) sortOrderings +{ + NSArray *uidKeys; + EOQualifier *fetchQualifier, *deletedQualifier; + static EOQualifier *nonDeletedQualifier = nil; + + if (!nonDeletedQualifier) + { + deletedQualifier + = [[EOKeyValueQualifier alloc] + initWithKey: @"FLAGS" + operatorSelector: EOQualifierOperatorContains + value: [NSArray arrayWithObject: @"Deleted"]]; + nonDeletedQualifier = [[EONotQualifier alloc] + initWithQualifier: deletedQualifier]; + [deletedQualifier release]; + } + + if (!sortOrderings) + sortOrderings = [NSArray arrayWithObject: @"ARRIVAL"]; + + if (qualifier) + { + fetchQualifier = [[EOAndQualifier alloc] + initWithQualifiers: nonDeletedQualifier, qualifier, + nil]; + [fetchQualifier autorelease]; + } + else + fetchQualifier = nonDeletedQualifier; + + uidKeys = [sogoObject fetchUIDsMatchingQualifier: fetchQualifier + sortOrdering: sortOrderings]; + return [uidKeys stringsWithFormat: @"%@.eml"]; +} + +@end + +@implementation MAPIStoreInboxFolder : MAPIStoreMailFolder + +- (SOGoMailFolder *) specialFolderFromAccount: (SOGoMailAccount *) accountFolder + inContext: (WOContext *) woContext +{ + return [accountFolder inboxFolderInContext: woContext]; +} + +@end + +@implementation MAPIStoreSentItemsFolder : MAPIStoreMailFolder + +- (SOGoMailFolder *) specialFolderFromAccount: (SOGoMailAccount *) accountFolder + inContext: (WOContext *) woContext +{ + return [accountFolder sentFolderInContext: woContext]; +} + +@end + +@implementation MAPIStoreDraftsFolder : MAPIStoreMailFolder + +- (SOGoMailFolder *) specialFolderFromAccount: (SOGoMailAccount *) accountFolder + inContext: (WOContext *) woContext +{ + return [accountFolder draftsFolderInContext: woContext]; +} + +@end + +@implementation MAPIStoreDeletedItemsFolder : MAPIStoreMailFolder + +- (SOGoMailFolder *) specialFolderFromAccount: (SOGoMailAccount *) accountFolder + inContext: (WOContext *) woContext +{ + return [accountFolder trashFolderInContext: woContext]; +} + +@end + +@implementation MAPIStoreOutboxFolder : MAPIStoreMailFolder + ++ (void) initialize +{ + MAPIStoreDraftsMessageK = [MAPIStoreDraftsMessage class]; +} + +- (SOGoMailFolder *) specialFolderFromAccount: (SOGoMailAccount *) accountFolder + inContext: (WOContext *) woContext +{ + return [accountFolder draftsFolderInContext: woContext]; +} + +- (Class) messageClass +{ + return MAPIStoreDraftsMessageK; +} + +- (MAPIStoreMessage *) createMessage +{ + MAPIStoreDraftsMessage *newMessage; + SOGoDraftObject *newDraft; + + newDraft = [sogoObject newDraft]; + newMessage + = [MAPIStoreDraftsMessage mapiStoreObjectWithSOGoObject: newDraft + inContainer: self]; + + + return newMessage; +} + +@end diff --git a/OpenChange/MAPIStoreNotesContext.m b/OpenChange/MAPIStoreNotesContext.m index 62aa89567..b4cc38714 100644 --- a/OpenChange/MAPIStoreNotesContext.m +++ b/OpenChange/MAPIStoreNotesContext.m @@ -22,10 +22,10 @@ #import +#import "MAPIStoreNotesFolder.h" #import "MAPIStoreMapping.h" #import "MAPIStoreNotesContext.h" -#import "MAPIStoreNotesMessageTable.h" @implementation MAPIStoreNotesContext @@ -40,9 +40,11 @@ withID: 0x1c0001]; } -- (Class) messageTableClass +- (void) setupBaseFolder: (NSURL *) newURL { - return [MAPIStoreNotesMessageTable class]; + baseFolder = [MAPIStoreNotesFolder baseFolderWithURL: newURL + inContext: self]; + [baseFolder retain]; } @end diff --git a/OpenChange/MAPIStoreNotesFolder.h b/OpenChange/MAPIStoreNotesFolder.h new file mode 100644 index 000000000..de2eb2748 --- /dev/null +++ b/OpenChange/MAPIStoreNotesFolder.h @@ -0,0 +1,31 @@ +/* MAPIStoreNotesFolder.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 MAPISTORENOTESFOLDER_H +#define MAPISTORENOTESFOLDER_H + +#import "MAPIStoreFSFolder.h" + +@interface MAPIStoreNotesFolder : MAPIStoreFSFolder +@end + +#endif /* MAPISTORENOTESFOLDER_H */ diff --git a/OpenChange/MAPIStoreNotesFolder.m b/OpenChange/MAPIStoreNotesFolder.m new file mode 100644 index 000000000..c99ae3e88 --- /dev/null +++ b/OpenChange/MAPIStoreNotesFolder.m @@ -0,0 +1,43 @@ +/* MAPIStoreNotesFolder.m - this file is part of $PROJECT_NAME_HERE$ + * + * Copyright (C) 2011 Inverse inc + * + * 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 "MAPIStoreNotesFolder.h" + +#import "MAPIStoreNotesMessage.h" + +#import "MAPIStoreNotesFolder.h" + +static Class MAPIStoreNotesMessageK; + +@implementation MAPIStoreNotesFolder + ++ (void) initialize +{ + MAPIStoreNotesMessageK = [MAPIStoreNotesMessage class]; +} + +- (Class) messageClass +{ + return MAPIStoreNotesMessageK; +} + +@end diff --git a/OpenChange/MAPIStoreOutboxContext.h b/OpenChange/MAPIStoreOutboxContext.h index aea74496c..a2d8f9d97 100644 --- a/OpenChange/MAPIStoreOutboxContext.h +++ b/OpenChange/MAPIStoreOutboxContext.h @@ -23,9 +23,9 @@ #ifndef MAPISTOREOUTBOXCONTEXT_H #define MAPISTOREOUTBOXCONTEXT_H -#import "MAPIStoreMailContext.h" +#import "MAPIStoreMailBaseContext.h" -@interface MAPIStoreOutboxContext : MAPIStoreMailContext +@interface MAPIStoreOutboxContext : MAPIStoreMailBaseContext @end diff --git a/OpenChange/MAPIStoreOutboxContext.m b/OpenChange/MAPIStoreOutboxContext.m index bb8dafd78..45da5c4bb 100644 --- a/OpenChange/MAPIStoreOutboxContext.m +++ b/OpenChange/MAPIStoreOutboxContext.m @@ -22,14 +22,7 @@ #import -#import - -#import -#import -#import - -#import "MAPIApplication.h" -#import "MAPIStoreAuthenticator.h" +#import "MAPIStoreMailFolder.h" #import "MAPIStoreMapping.h" #import "MAPIStoreOutboxContext.h" @@ -47,44 +40,53 @@ withID: 0x150001]; } -- (void) setupModuleFolder +- (void) setupBaseFolder: (NSURL *) newURL { - SOGoUserFolder *userFolder; - SOGoMailAccounts *accountsFolder; - SOGoMailAccount *accountFolder; - id currentContainer; - - userFolder = [SOGoUserFolder objectWithName: [authenticator username] - inContainer: MAPIApp]; - [parentFoldersBag addObject: userFolder]; - [woContext setClientObject: userFolder]; - - accountsFolder = [userFolder lookupName: @"Mail" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: accountsFolder]; - [woContext setClientObject: accountsFolder]; - - accountFolder = [accountsFolder lookupName: @"0" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: accountFolder]; - [woContext setClientObject: accountFolder]; - - moduleFolder = [accountFolder draftsFolderInContext: nil]; - [moduleFolder retain]; - currentContainer = [moduleFolder container]; - while (currentContainer != accountFolder) - { - [parentFoldersBag addObject: currentContainer]; - currentContainer = [currentContainer container]; - } -} - -- (id) createMessageOfClass: (NSString *) messageClass - inFolderAtURL: (NSString *) folderURL; -{ - return [moduleFolder newDraft]; + baseFolder = [MAPIStoreOutboxFolder baseFolderWithURL: newURL + inContext: self]; + [baseFolder retain]; } @end + +// - (void) setupModuleFolder +// { +// SOGoUserFolder *userFolder; +// SOGoMailAccounts *accountsFolder; +// SOGoMailAccount *accountFolder; +// id currentContainer; + +// userFolder = [SOGoUserFolder objectWithName: [authenticator username] +// inContainer: MAPIApp]; +// [parentFoldersBag addObject: userFolder]; +// [woContext setClientObject: userFolder]; + +// accountsFolder = [userFolder lookupName: @"Mail" +// inContext: woContext +// acquire: NO]; +// [parentFoldersBag addObject: accountsFolder]; +// [woContext setClientObject: accountsFolder]; + +// accountFolder = [accountsFolder lookupName: @"0" +// inContext: woContext +// acquire: NO]; +// [parentFoldersBag addObject: accountFolder]; +// [woContext setClientObject: accountFolder]; + +// moduleFolder = [accountFolder draftsFolderInContext: nil]; +// [moduleFolder retain]; +// currentContainer = [moduleFolder container]; +// while (currentContainer != accountFolder) +// { +// [parentFoldersBag addObject: currentContainer]; +// currentContainer = [currentContainer container]; +// } +// } + +// - (id) createMessageOfClass: (NSString *) messageClass +// inFolderAtURL: (NSString *) folderURL; +// { +// return [moduleFolder newDraft]; +// } + +// @end diff --git a/OpenChange/MAPIStoreSentItemsContext.h b/OpenChange/MAPIStoreSentItemsContext.h index bd2bdc429..ec61e6492 100644 --- a/OpenChange/MAPIStoreSentItemsContext.h +++ b/OpenChange/MAPIStoreSentItemsContext.h @@ -23,9 +23,9 @@ #ifndef MAPISTORESEARCHCONTEXT_H #define MAPISTORESEARCHCONTEXT_H -#import "MAPIStoreMailContext.h" +#import "MAPIStoreMailBaseContext.h" -@interface MAPIStoreSentItemsContext : MAPIStoreMailContext +@interface MAPIStoreSentItemsContext : MAPIStoreMailBaseContext @end diff --git a/OpenChange/MAPIStoreSentItemsContext.m b/OpenChange/MAPIStoreSentItemsContext.m index 678216b89..e1c433780 100644 --- a/OpenChange/MAPIStoreSentItemsContext.m +++ b/OpenChange/MAPIStoreSentItemsContext.m @@ -22,15 +22,7 @@ #import -#import - -#import - -#import - -#import "MAPIApplication.h" -#import "MAPIStoreAuthenticator.h" - +#import "MAPIStoreMailFolder.h" #import "MAPIStoreMapping.h" #import "MAPIStoreSentItemsContext.h" @@ -48,40 +40,11 @@ withID: 0x140001]; } -- (void) setupModuleFolder +- (void) setupBaseFolder: (NSURL *) newURL { - SOGoUserFolder *userFolder; - SOGoMailAccounts *accountsFolder; - SOGoMailAccount *accountFolder; - SOGoFolder *currentContainer; - - userFolder = [SOGoUserFolder objectWithName: [authenticator username] - inContainer: MAPIApp]; - [parentFoldersBag addObject: userFolder]; - // [self logWithFormat: @"userFolder: %@", userFolder]; - [woContext setClientObject: userFolder]; - - accountsFolder = [userFolder lookupName: @"Mail" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: accountsFolder]; - // [self logWithFormat: @"accountsFolder: %@", accountsFolder]; - [woContext setClientObject: accountsFolder]; - - accountFolder = [accountsFolder lookupName: @"0" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: accountFolder]; - [woContext setClientObject: accountFolder]; - - moduleFolder = [accountFolder sentFolderInContext: nil]; - [moduleFolder retain]; - currentContainer = [moduleFolder container]; - while (currentContainer != (SOGoFolder *) accountFolder) - { - [parentFoldersBag addObject: currentContainer]; - currentContainer = [currentContainer container]; - } + baseFolder = [MAPIStoreSentItemsFolder baseFolderWithURL: newURL + inContext: self]; + [baseFolder retain]; } @end diff --git a/OpenChange/MAPIStoreTasksContext.m b/OpenChange/MAPIStoreTasksContext.m index 371c934cb..fa75dda9c 100644 --- a/OpenChange/MAPIStoreTasksContext.m +++ b/OpenChange/MAPIStoreTasksContext.m @@ -20,33 +20,13 @@ * Boston, MA 02111-1307, USA. */ -#import +#import -#import - -#import - -#import -#import -#import -#import - -#import "MAPIApplication.h" -#import "MAPIStoreAuthenticator.h" +#import "MAPIStoreTasksFolder.h" #import "MAPIStoreMapping.h" -#import "MAPIStoreTasksMessageTable.h" -#import "MAPIStoreTypes.h" -#import "NSCalendarDate+MAPIStore.h" -#import "NSString+MAPIStore.h" -#import "SOGoGCSFolder+MAPIStore.h" #import "MAPIStoreTasksContext.h" -#undef DEBUG -#include -#include -#include - @implementation MAPIStoreTasksContext + (NSString *) MAPIModuleName @@ -60,48 +40,11 @@ withID: 0x1d0001]; } -- (void) setupModuleFolder +- (void) setupBaseFolder: (NSURL *) newURL { - SOGoUserFolder *userFolder; - SOGoAppointmentFolders *parentFolder; - - userFolder = [SOGoUserFolder objectWithName: [authenticator username] - inContainer: MAPIApp]; - [parentFoldersBag addObject: userFolder]; - [woContext setClientObject: userFolder]; - - parentFolder = [userFolder lookupName: @"Calendar" - inContext: woContext - acquire: NO]; - [parentFoldersBag addObject: parentFolder]; - [woContext setClientObject: parentFolder]; - - moduleFolder = [parentFolder lookupName: @"personal" - inContext: woContext - acquire: NO]; - [moduleFolder retain]; -} - -- (Class) messageTableClass -{ - return [MAPIStoreTasksMessageTable class]; -} - -- (id) createMessageOfClass: (NSString *) messageClass - inFolderAtURL: (NSString *) folderURL; -{ - SOGoAppointmentFolder *parentFolder; - SOGoTaskObject *newEntry; - NSString *name; - - parentFolder = [self lookupObject: folderURL]; - name = [NSString stringWithFormat: @"%@.ics", - [SOGoObject globallyUniqueObjectId]]; - newEntry = [SOGoTaskObject objectWithName: name - inContainer: parentFolder]; - [newEntry setIsNew: YES]; - - return newEntry; + baseFolder = [MAPIStoreTasksFolder baseFolderWithURL: newURL + inContext: self]; + [baseFolder retain]; } @end diff --git a/OpenChange/MAPIStoreTasksFolder.h b/OpenChange/MAPIStoreTasksFolder.h new file mode 100644 index 000000000..5f30c77b4 --- /dev/null +++ b/OpenChange/MAPIStoreTasksFolder.h @@ -0,0 +1,32 @@ +/* MAPIStoreTasksFolder.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 MAPISTORETASKSFOLDER_H +#define MAPISTORETASKSFOLDER_H + +#import "MAPIStoreGCSFolder.h" + +@interface MAPIStoreTasksFolder : MAPIStoreGCSFolder + +@end + +#endif /* MAPISTORETASKSFOLDER_H */ diff --git a/OpenChange/MAPIStoreTasksFolder.m b/OpenChange/MAPIStoreTasksFolder.m new file mode 100644 index 000000000..d717d746e --- /dev/null +++ b/OpenChange/MAPIStoreTasksFolder.m @@ -0,0 +1,125 @@ +/* MAPIStoreTasksFolder.m - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * 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 +#import +#import +#import +#import + +#import "MAPIApplication.h" +#import "MAPIStoreTasksContext.h" +#import "MAPIStoreTasksMessage.h" +#import "MAPIStoreTasksMessageTable.h" + +#import "MAPIStoreTasksFolder.h" + +static Class MAPIStoreTasksMessageK; + +@implementation MAPIStoreTasksFolder + ++ (void) initialize +{ + MAPIStoreTasksMessageK = [MAPIStoreTasksMessage class]; +} + +- (id) initWithURL: (NSURL *) newURL + inContext: (MAPIStoreContext *) newContext +{ + SOGoUserFolder *userFolder; + SOGoAppointmentFolders *parentFolder; + WOContext *woContext; + + if ((self = [super initWithURL: newURL + inContext: newContext])) + { + woContext = [newContext woContext]; + userFolder = [SOGoUserFolder objectWithName: [newURL user] + inContainer: MAPIApp]; + [parentContainersBag addObject: userFolder]; + [woContext setClientObject: userFolder]; + + parentFolder = [userFolder lookupName: @"Calendar" + inContext: woContext + acquire: NO]; + [parentContainersBag addObject: parentFolder]; + [woContext setClientObject: parentFolder]; + + sogoObject = [parentFolder lookupName: @"personal" + inContext: woContext + acquire: NO]; + [sogoObject retain]; + } + + return self; +} + +- (Class) messageClass +{ + return MAPIStoreTasksMessageK; +} + +- (MAPIStoreMessageTable *) messageTable +{ + if (!messageTable) + ASSIGN (messageTable, + [MAPIStoreTasksMessageTable tableForContainer: self]); + + return messageTable; +} + +- (EOQualifier *) componentQualifier +{ + static EOQualifier *componentQualifier = nil; + + /* TODO: we need to support vlist as well */ + if (!componentQualifier) + componentQualifier + = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" + operatorSelector: EOQualifierOperatorEqual + value: @"vtodo"]; + + return componentQualifier; +} + +- (MAPIStoreMessage *) createMessage +{ + MAPIStoreMessage *newMessage; + SOGoTaskObject *newEntry; + NSString *name; + + name = [NSString stringWithFormat: @"%@.ics", + [SOGoObject globallyUniqueObjectId]]; + newEntry = [SOGoTaskObject objectWithName: name + inContainer: sogoObject]; + [newEntry setIsNew: YES]; + newMessage = [MAPIStoreTasksMessage mapiStoreObjectWithSOGoObject: newEntry + inContainer: self]; + + + return newMessage; +} + +@end