/* 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 "MAPIStoreFAIMessage.h" #import "MAPIStoreFAIMessageTable.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, MAPIStoreMessageTableK, MAPIStoreFAIMessageTableK, MAPIStoreFolderTableK; @implementation MAPIStoreFolder + (void) initialize { NSExceptionK = [NSException class]; MAPIStoreMessageTableK = [MAPIStoreMessageTable class]; MAPIStoreFAIMessageTableK = [MAPIStoreFAIMessageTable class]; MAPIStoreFolderTableK = [MAPIStoreFolderTable 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])) { messageKeys = nil; faiMessageKeys = nil; folderKeys = nil; faiFolder = nil; folderURL = nil; context = nil; activeMessageTables = [NSMutableArray new]; activeFAIMessageTables = [NSMutableArray new]; activeFolderTables = [NSMutableArray new]; } 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]; [messageKeys release]; [faiMessageKeys release]; [folderKeys release]; [faiFolder release]; [activeMessageTables release]; [activeFAIMessageTables release]; [activeFolderTables 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; } - (MAPIStoreFAIMessageTable *) faiMessageTable { return [MAPIStoreFAIMessageTable tableForContainer: self]; } - (NSArray *) faiMessageKeys { if (!faiMessageKeys) { faiMessageKeys = [faiFolder toOneRelationshipKeys]; [faiMessageKeys retain]; } return faiMessageKeys; } - (MAPIStoreFolderTable *) folderTable { return nil; } - (NSArray *) folderKeys { return nil; } - (NSArray *) activeMessageTables { return activeMessageTables; } - (NSArray *) activeFAIMessageTables { return activeFAIMessageTables; } - (NSArray *) activeFolderTables { return activeFolderTables; } - (NSMutableArray *) _arrayForActiveTable: (MAPIStoreTable *) activeTable { NSMutableArray *tablesArray; if ([activeTable isKindOfClass: MAPIStoreFAIMessageTableK]) tablesArray = activeMessageTables; else if ([activeTable isKindOfClass: MAPIStoreMessageTableK]) tablesArray = activeMessageTables; else if ([activeTable isKindOfClass: MAPIStoreFolderTableK]) tablesArray = activeMessageTables; else tablesArray = nil; return tablesArray; } - (void) addActiveTable: (MAPIStoreTable *) activeTable { [[self _arrayForActiveTable: activeTable] addObject: activeTable]; } - (void) removeActiveTable: (MAPIStoreTable *) activeTable { [[self _arrayForActiveTable: activeTable] removeObject: activeTable]; } - (void) _cleanupTableCaches: (NSArray *) activeTables { NSUInteger count, max; max = [activeTables count]; for (count = 0; count < max; count++) [[activeTables objectAtIndex: count] cleanupCaches]; } - (void) cleanupCaches { [self _cleanupTableCaches: activeMessageTables]; [self _cleanupTableCaches: activeFAIMessageTables]; [self _cleanupTableCaches: activeFolderTables]; [faiMessageKeys release]; faiMessageKeys = nil; [messageKeys release]; messageKeys = nil; [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 = [MAPIStoreFAIMessage 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 = [MAPIStoreFAIMessage mapiStoreObjectWithSOGoObject: fsObject inContainer: self]; return newMessage; } - (MAPIStoreMessage *) createMessage: (BOOL) isAssociated { MAPIStoreMessage *newMessage; if (isAssociated) newMessage = [self _createAssociatedMessage]; else newMessage = [self createMessage]; [newMessage setIsNew: YES]; 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