From 356701eb72a970f0746f6fa8fb09c108a02497b8 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Thu, 30 Dec 2010 14:33:52 +0000 Subject: [PATCH] Monotone-Parent: 08fd408516a2d328b26b44c64b78709c05d91800 Monotone-Revision: 1cf0666c301d95bac897f1c057e68496cb752e24 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2010-12-30T14:33:52 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 5 + OpenChange/MAPIStoreTasksContext.m | 215 +++----------------- OpenChange/MAPIStoreTasksMessageTable.h | 32 +++ OpenChange/MAPIStoreTasksMessageTable.m | 255 ++++++++++++++++++++++++ 4 files changed, 315 insertions(+), 192 deletions(-) create mode 100644 OpenChange/MAPIStoreTasksMessageTable.h create mode 100644 OpenChange/MAPIStoreTasksMessageTable.m diff --git a/ChangeLog b/ChangeLog index 96c1ac884..1e0c9c809 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2010-12-30 Wolfgang Sourdeau + * OpenChange/MAPIStoreTasksContext.m: Old table methods (see + below) split into the new "MAPIStoreTasksMessageTable" class. + (+registerFixedMappings:): changed handled uri to + @"sogo://openchange:openchange@tasks/". + * OpenChange/MAPIStoreCalendarContext.m: Old table methods (see below) split into the new "MAPIStoreCalendarMessageTable" class. (+registerFixedMappings:): changed handled uri to diff --git a/OpenChange/MAPIStoreTasksContext.m b/OpenChange/MAPIStoreTasksContext.m index fb52ac8cd..371c934cb 100644 --- a/OpenChange/MAPIStoreTasksContext.m +++ b/OpenChange/MAPIStoreTasksContext.m @@ -27,11 +27,14 @@ #import #import +#import +#import #import #import "MAPIApplication.h" #import "MAPIStoreAuthenticator.h" #import "MAPIStoreMapping.h" +#import "MAPIStoreTasksMessageTable.h" #import "MAPIStoreTypes.h" #import "NSCalendarDate+MAPIStore.h" #import "NSString+MAPIStore.h" @@ -40,7 +43,9 @@ #import "MAPIStoreTasksContext.h" #undef DEBUG +#include #include +#include @implementation MAPIStoreTasksContext @@ -51,147 +56,45 @@ + (void) registerFixedMappings: (MAPIStoreMapping *) mapping { - [mapping registerURL: @"sogo://openchange:openchange@tasks/personal/" + [mapping registerURL: @"sogo://openchange:openchange@tasks/" withID: 0x1d0001]; } - (void) setupModuleFolder { - id userFolder; + SOGoUserFolder *userFolder; + SOGoAppointmentFolders *parentFolder; userFolder = [SOGoUserFolder objectWithName: [authenticator username] inContainer: MAPIApp]; [parentFoldersBag addObject: userFolder]; [woContext setClientObject: userFolder]; - moduleFolder = [userFolder lookupName: @"Calendar" - inContext: woContext - acquire: NO]; + parentFolder = [userFolder lookupName: @"Calendar" + inContext: woContext + acquire: NO]; + [parentFoldersBag addObject: parentFolder]; + [woContext setClientObject: parentFolder]; + + moduleFolder = [parentFolder lookupName: @"personal" + inContext: woContext + acquire: NO]; [moduleFolder retain]; } -- (NSArray *) getFolderMessageKeys: (SOGoFolder *) folder - matchingQualifier: (EOQualifier *) qualifier +- (Class) messageTableClass { - EOQualifier *componentQualifier, *tasksQualifier; - - componentQualifier - = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" - operatorSelector: EOQualifierOperatorEqual - value: @"vtodo"]; - [componentQualifier autorelease]; - if (qualifier) - { - tasksQualifier = [[EOAndQualifier alloc] - initWithQualifiers: - componentQualifier, - qualifier, - nil]; - [tasksQualifier autorelease]; - } - else - tasksQualifier = componentQualifier; - - return [super getFolderMessageKeys: folder - matchingQualifier: tasksQualifier]; + return [MAPIStoreTasksMessageTable class]; } -- (enum MAPISTATUS) getMessageTableChildproperty: (void **) data - atURL: (NSString *) childURL - withTag: (enum MAPITAGS) proptag - inFolder: (SOGoFolder *) folder - withFID: (uint64_t) fid -{ - NSString *status; - // id child; - id task; - int32_t statusValue; - int rc; - - rc = MAPI_E_SUCCESS; - switch (proptag) - { - case PR_ICON_INDEX: // TODO - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - // Unassigned recurring task 0x00000501 - // Assignee's task 0x00000502 - // Assigner's task 0x00000503 - // Task request 0x00000504 - // Task acceptance 0x00000505 - // Task rejection 0x00000506 - *data = MAPILongValue (memCtx, 0x00000500); - break; - case PR_MESSAGE_CLASS_UNICODE: - *data = talloc_strdup(memCtx, "IPM.Task"); - break; - case PR_SUBJECT_UNICODE: // SUMMARY - case PR_NORMALIZED_SUBJECT_UNICODE: - case PR_CONVERSATION_TOPIC_UNICODE: - task = [[self lookupObject: childURL] component: NO secure: NO]; - *data = [[task summary] asUnicodeInMemCtx: memCtx]; - break; - case 0x8124000b: // completed - task = [[self lookupObject: childURL] component: NO secure: NO]; - *data = MAPIBoolValue (memCtx, - [[task status] isEqualToString: @"COMPLETED"]); - break; - case 0x81250040: // completion date - task = [[self lookupObject: childURL] component: NO secure: NO]; - *data = [[task completed] asFileTimeInMemCtx: memCtx]; - break; - case PR_CREATION_TIME: - task = [[self lookupObject: childURL] component: NO secure: NO]; - *data = [[task created] asFileTimeInMemCtx: memCtx]; - break; - case PR_MESSAGE_DELIVERY_TIME: - case PR_CLIENT_SUBMIT_TIME: - case PR_LOCAL_COMMIT_TIME: - case PR_LAST_MODIFICATION_TIME: - task = [[self lookupObject: childURL] component: NO secure: NO]; - *data = [[task lastModified] asFileTimeInMemCtx: memCtx]; - break; - case 0x81200003: // status - task = [[self lookupObject: childURL] component: NO secure: NO]; - status = [task status]; - if (![status length] - || [status isEqualToString: @"NEEDS-ACTIONS"]) - statusValue = 0; - else if ([status isEqualToString: @"IN-PROCESS"]) - statusValue = 1; - else if ([status isEqualToString: @"COMPLETED"]) - statusValue = 2; - else - statusValue = 0xff; - *data = MAPILongValue (memCtx, statusValue); - break; - /* Completed */ - // - 0x81380003 = -2000 - // + 0x81380003 = -4000 - - // 68330048 - // 68420102 - case 0x68340003: - case 0x683a0003: - case 0x68410003: - *data = MAPILongValue (memCtx, 0); - break; - - default: - rc = [super getMessageTableChildproperty: data - atURL: childURL - withTag: proptag - inFolder: folder - withFID: fid]; - } - - return rc; -} - -- (id) createMessageInFolder: (id) parentFolder +- (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 @@ -201,76 +104,4 @@ return newEntry; } -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - static NSMutableDictionary *knownProperties = nil; - - if (!knownProperties) - { - knownProperties = [NSMutableDictionary new]; - } - - return [knownProperties objectForKey: MAPIPropertyKey (property)]; -} - -/* restrictions */ - -- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - id value; - - value = NSObjectFromMAPISPropValue (&res->lpProp); - switch (res->ulPropTag) - { - case PR_MESSAGE_CLASS_UNICODE: - if ([value isKindOfClass: [NSString class]] - && [value isEqualToString: @"IPM.Task"]) - rc = MAPIRestrictionStateAlwaysTrue; - else - rc = MAPIRestrictionStateAlwaysFalse; - break; - case PR_RULE_PROVIDER_UNICODE: // TODO: what's this? - rc = MAPIRestrictionStateAlwaysTrue; - break; - case 0x81200003: // PidLidTaskStatus - rc = MAPIRestrictionStateAlwaysTrue; - break; - case 0x81250040: // PidLidTaskDateCompleted - rc = MAPIRestrictionStateAlwaysTrue; - break; - - default: - rc = [super evaluatePropertyRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -- (MAPIRestrictionState) evaluateExistRestriction: (struct mapi_SExistRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - - switch (res->ulPropTag) - { - case 0x81250040: // PidLidTaskDateCompleted - /* since we don't store the completion date in the quick table, we only - checks whether the task has been completed */ - *qualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_status" - operatorSelector: EOQualifierOperatorEqual - value: [NSNumber numberWithInt: 1]]; - [*qualifier autorelease]; - rc = MAPIRestrictionStateNeedsEval; - break; - - default: - rc = [super evaluateExistRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - @end diff --git a/OpenChange/MAPIStoreTasksMessageTable.h b/OpenChange/MAPIStoreTasksMessageTable.h new file mode 100644 index 000000000..2180dd9ec --- /dev/null +++ b/OpenChange/MAPIStoreTasksMessageTable.h @@ -0,0 +1,32 @@ +/* MAPIStoreTasksMessageTable.h - 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 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 MAPISTORETASKSMESSAGETABLE_H +#define MAPISTORETASKSMESSAGETABLE_H + +#import "MAPIStoreGCSMessageTable.h" + +@interface MAPIStoreTasksMessageTable : MAPIStoreGCSMessageTable + +@end + +#endif /* MAPISTORETASKSMESSAGETABLE_H */ diff --git a/OpenChange/MAPIStoreTasksMessageTable.m b/OpenChange/MAPIStoreTasksMessageTable.m new file mode 100644 index 000000000..32f18ab0c --- /dev/null +++ b/OpenChange/MAPIStoreTasksMessageTable.m @@ -0,0 +1,255 @@ +/* MAPIStoreTasksMessageTable.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 "MAPIStoreTypes.h" +#import "NSCalendarDate+MAPIStore.h" +#import "NSString+MAPIStore.h" + +#import "MAPIStoreTasksMessageTable.h" + +#include + +@implementation MAPIStoreTasksMessageTable + +- (enum MAPISTATUS) getChildProperty: (void **) data + forKey: (NSString *) childKey + withTag: (enum MAPITAGS) propTag +{ + NSString *status; + // id child; + iCalToDo *task; + int32_t statusValue; + NSCalendarDate *dateValue; + int rc; + double doubleValue; + + rc = MAPI_E_SUCCESS; + switch (propTag) + { + case PR_ICON_INDEX: // TODO + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ + // Unassigned recurring task 0x00000501 + // Assignee's task 0x00000502 + // Assigner's task 0x00000503 + // Task request 0x00000504 + // Task acceptance 0x00000505 + // Task rejection 0x00000506 + *data = MAPILongValue (memCtx, 0x00000500); + break; + case PR_MESSAGE_CLASS_UNICODE: + *data = talloc_strdup(memCtx, "IPM.Task"); + break; + case PR_SUBJECT_UNICODE: // SUMMARY + case PR_NORMALIZED_SUBJECT_UNICODE: + case PR_CONVERSATION_TOPIC_UNICODE: + task = [[self lookupChild: childKey] component: NO secure: NO]; + *data = [[task summary] asUnicodeInMemCtx: memCtx]; + break; + case PidLidTaskComplete: + task = [[self lookupChild: childKey] component: NO secure: NO]; + *data = MAPIBoolValue (memCtx, + [[task status] isEqualToString: @"COMPLETED"]); + break; + case PidLidPercentComplete: + task = [[self lookupChild: childKey] component: NO secure: NO]; + doubleValue = ((double) [[task percentComplete] intValue] / 100); + *data = MAPIDoubleValue (memCtx, doubleValue); + break; + case PidLidTaskDateCompleted: + task = [[self lookupChild: childKey] component: NO secure: NO]; + *data = [[task completed] asFileTimeInMemCtx: memCtx]; + break; + case PidLidTaskState: // TODO (check) + *data = MAPILongValue (memCtx, 0x02 | 0x03); + break; + case PidLidTaskAccepted: // TODO + *data = MAPIBoolValue (memCtx, YES); + break; + case PR_HASATTACH: + *data = MAPIBoolValue (memCtx, NO); + break; + + case PidLidTaskDueDate: + task = [[self lookupChild: childKey] component: NO secure: NO]; + dateValue = [task due]; + if (dateValue) + *data = [dateValue asFileTimeInMemCtx: memCtx]; + else + rc = MAPI_E_NOT_FOUND; + break; + + case PR_CREATION_TIME: + task = [[self lookupChild: childKey] component: NO secure: NO]; + *data = [[task created] asFileTimeInMemCtx: memCtx]; + break; + case PR_MESSAGE_DELIVERY_TIME: + case PR_CLIENT_SUBMIT_TIME: + case PR_LOCAL_COMMIT_TIME: + case PR_LAST_MODIFICATION_TIME: + task = [[self lookupChild: childKey] component: NO secure: NO]; + *data = [[task lastModified] asFileTimeInMemCtx: memCtx]; + break; + case PidLidTaskStatus: // status + task = [[self lookupChild: childKey] component: NO secure: NO]; + status = [task status]; + if (![status length] + || [status isEqualToString: @"NEEDS-ACTIONS"]) + statusValue = 0; + else if ([status isEqualToString: @"IN-PROCESS"]) + statusValue = 1; + else if ([status isEqualToString: @"COMPLETED"]) + statusValue = 2; + else + statusValue = 0xff; + *data = MAPILongValue (memCtx, statusValue); + break; + /* Completed */ + // - 0x81380003 = -2000 + // + 0x81380003 = -4000 + + // 68330048 + // 68420102 + case 0x68340003: + case 0x683a0003: + case 0x68410003: + *data = MAPILongValue (memCtx, 0); + break; + + default: + rc = [super getChildProperty: data + forKey: childKey + withTag: propTag]; + } + + return rc; +} + +- (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; +} + +- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property +{ + static NSMutableDictionary *knownProperties = nil; + + if (!knownProperties) + { + knownProperties = [NSMutableDictionary new]; + [knownProperties setObject: @"c_enddate" + forKey: MAPIPropertyKey (PidLidTaskDueDate)]; + } + + return [knownProperties objectForKey: MAPIPropertyKey (property)]; +} + +/* restrictions */ + +- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res + intoQualifier: (EOQualifier **) qualifier +{ + MAPIRestrictionState rc; + id value; + + value = NSObjectFromMAPISPropValue (&res->lpProp); + switch (res->ulPropTag) + { + case PR_MESSAGE_CLASS_UNICODE: + if ([value isKindOfClass: [NSString class]] + && [value isEqualToString: @"IPM.Task"]) + rc = MAPIRestrictionStateAlwaysTrue; + else + rc = MAPIRestrictionStateAlwaysFalse; + break; + case PR_RULE_PROVIDER_UNICODE: // TODO: what's this? + rc = MAPIRestrictionStateAlwaysTrue; + break; + case PidLidTaskOwnership: + rc = MAPIRestrictionStateAlwaysTrue; + break; + case PidLidTaskStatus: + rc = MAPIRestrictionStateAlwaysTrue; + break; + + case PidLidTaskComplete: + *qualifier = [[EOKeyValueQualifier alloc] + initWithKey: @"c_status" + operatorSelector: EOQualifierOperatorEqual + value: [NSNumber numberWithInt: 1]]; + [*qualifier autorelease]; + rc = MAPIRestrictionStateNeedsEval; + break; + + case PidLidTaskDateCompleted: + rc = MAPIRestrictionStateAlwaysTrue; + break; + + default: + rc = [super evaluatePropertyRestriction: res intoQualifier: qualifier]; + } + + return rc; +} + +- (MAPIRestrictionState) evaluateExistRestriction: (struct mapi_SExistRestriction *) res + intoQualifier: (EOQualifier **) qualifier +{ + MAPIRestrictionState rc; + + switch (res->ulPropTag) + { + case PidLidTaskDateCompleted: + /* since we don't store the completion date in the quick table, we only + checks whether the task has been completed */ + *qualifier = [[EOKeyValueQualifier alloc] + initWithKey: @"c_status" + operatorSelector: EOQualifierOperatorEqual + value: [NSNumber numberWithInt: 1]]; + [*qualifier autorelease]; + rc = MAPIRestrictionStateNeedsEval; + break; + + default: + rc = [super evaluateExistRestriction: res intoQualifier: qualifier]; + } + + return rc; +} + +@end