diff --git a/ChangeLog b/ChangeLog index 0aa9d9ed4..96c1ac884 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2010-12-30 Wolfgang Sourdeau + * OpenChange/MAPIStoreCalendarContext.m: Old table methods (see + below) split into the new "MAPIStoreCalendarMessageTable" class. + (+registerFixedMappings:): changed handled uri to + @"sogo://openchange:openchange@calendar/" as we now consider that + the "host" part of the uri names the context that handles it. + * OpenChange/MAPIStoreFAIMessageTable.[hm]: new class module, subclassed from MAPIStoreFSMessageTable, that provides the interface for FAI messages in MAPIStoreContext. diff --git a/OpenChange/MAPIStoreCalendarContext.m b/OpenChange/MAPIStoreCalendarContext.m index 4f52f9761..d40d911aa 100644 --- a/OpenChange/MAPIStoreCalendarContext.m +++ b/OpenChange/MAPIStoreCalendarContext.m @@ -26,23 +26,21 @@ #import -#import - -#import +#import +#import #import #import "MAPIApplication.h" #import "MAPIStoreAuthenticator.h" +#import "MAPIStoreCalendarMessageTable.h" #import "MAPIStoreMapping.h" -#import "MAPIStoreTypes.h" -#import "NSCalendarDate+MAPIStore.h" -#import "NSString+MAPIStore.h" #import "SOGoGCSFolder+MAPIStore.h" #import "MAPIStoreCalendarContext.h" #undef DEBUG #include +#include @implementation MAPIStoreCalendarContext @@ -53,226 +51,52 @@ + (void) registerFixedMappings: (MAPIStoreMapping *) mapping { - [mapping registerURL: @"sogo://openchange:openchange@calendar/personal/" + [mapping registerURL: @"sogo://openchange:openchange@calendar/" withID: 0x190001]; } - (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 -{ - EOQualifier *componentQualifier, *calendarQualifier; - - componentQualifier - = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" - operatorSelector: EOQualifierOperatorEqual - value: @"vevent"]; - [componentQualifier autorelease]; - if (qualifier) - { - calendarQualifier = [[EOAndQualifier alloc] - initWithQualifiers: - componentQualifier, - qualifier, - nil]; - [calendarQualifier autorelease]; - } - else - calendarQualifier = componentQualifier; - - return [super getFolderMessageKeys: folder - matchingQualifier: calendarQualifier]; -} - -- (enum MAPISTATUS) getMessageTableChildproperty: (void **) data - atURL: (NSString *) childURL - withTag: (enum MAPITAGS) proptag - inFolder: (SOGoFolder *) folder - withFID: (uint64_t) fid -{ - // id child; - id event; - int rc; - - rc = MAPI_E_SUCCESS; - switch (proptag) - { - case PR_ICON_INDEX: // TODO - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - // *longValue = 0x00000401 for recurring event - // *longValue = 0x00000402 for meeting - // *longValue = 0x00000403 for recurring meeting - // *longValue = 0x00000404 for invitation - *data = MAPILongValue (memCtx, 0x00000400); - break; - case PR_MESSAGE_CLASS_UNICODE: - *data = talloc_strdup(memCtx, "IPM.Appointment"); - break; - case 0x818f0040: // DTSTART - event = [[self lookupObject: childURL] component: NO secure: NO]; - *data = [[event startDate] asFileTimeInMemCtx: memCtx]; - break; - case 0x818a0040: // DTEND - event = [[self lookupObject: childURL] component: NO secure: NO]; - *data = [[event endDate] asFileTimeInMemCtx: memCtx]; - break; - case 0x82410003: // LABEL idx, should be saved in an X- property - *data = MAPILongValue (memCtx, 0); - break; - case PR_SUBJECT_UNICODE: // SUMMARY - case PR_NORMALIZED_SUBJECT_UNICODE: - case PR_CONVERSATION_TOPIC_UNICODE: - event = [[self lookupObject: childURL] component: NO secure: NO]; - *data = [[event summary] asUnicodeInMemCtx: memCtx]; - break; - case 0x810c001f: // LOCATION - event = [[self lookupObject: childURL] component: NO secure: NO]; - *data = [[event location] asUnicodeInMemCtx: memCtx]; - break; - case 0x8224000b: // private (bool), should depend on CLASS - *data = MAPIBoolValue (memCtx, NO); - break; - case PR_SENSITIVITY: // not implemented, depends on CLASS - // normal = 0, personal?? = 1, private = 2, confidential = 3 - *data = MAPILongValue (memCtx, 0); - break; - case PR_CREATION_TIME: - event = [[self lookupObject: childURL] component: NO secure: NO]; - *data = [[event created] asFileTimeInMemCtx: memCtx]; - break; - - // case PR_VD_NAME_UNICODE: - // *data = talloc_strdup(memCtx, "PR_VD_NAME_UNICODE"); - // break; - // case PR_EMS_AB_DXA_REMOTE_CLIENT_UNICODE: "Home:" ??? - // *data = talloc_strdup(memCtx, "PR_EMS..."); - // break; - default: - rc = [super getMessageTableChildproperty: data - atURL: childURL - withTag: proptag - inFolder: folder - withFID: fid]; - } - - // #define PR_REPLY_TIME PROP_TAG(PT_SYSTIME , 0x0030) /* 0x00300040 */ - // #define PR_INTERNET_MESSAGE_ID_UNICODE PROP_TAG(PT_UNICODE , 0x1035) /* 0x1035001f */ - // #define PR_FLAG_STATUS PROP_TAG(PT_LONG , 0x1090) /* 0x10900003 */ - // #define PR_SEARCH_KEY PROP_TAG(PT_BINARY , 0x300b) /* 0x300b0102 */ - - - // #define PR_EMS_AB_INCOMING_MSG_SIZE_LIMIT PROP_TAG(PT_LONG , 0x8190) /* 0x81900003 */ - // Not found: 81930003 // ? - // Not found: 80fa000b // ? - // Not found: 81c4000b // ? - // Not found: 81e7000b // ? - // Not found: 81ee000b // ? - - // Not found: 81f80003 // - // Not found: 82020102 // - // Not found: 818b0102 // - // Not found: 81d1001f // - - return rc; -} - -- (id) createMessageInFolder: (id) parentFolder +- (id) createMessageOfClass: (NSString *) messageClass + inFolderAtURL: (NSString *) folderURL; { + SOGoAppointmentFolder *parentFolder; SOGoAppointmentObject *newEntry; NSString *name; + parentFolder = [self lookupObject: folderURL]; name = [NSString stringWithFormat: @"%@.ics", [SOGoObject globallyUniqueObjectId]]; newEntry = [SOGoAppointmentObject objectWithName: name - inContainer: parentFolder]; + inContainer: parentFolder]; [newEntry setIsNew: YES]; return newEntry; } -// - (int) getFolderTableChildproperty: (void **) data -// atURL: (NSString *) childURL -// withTag: (enum MAPITAGS) proptag -// inFolder: (SOGoFolder *) folder -// withFID: (uint64_t) fid -// { -// int rc; - -// [self logWithFormat: @"XXXXX unexpected!!!!!!!!!"]; -// rc = MAPI_E_SUCCESS; -// switch (proptag) { -// default: -// rc = [super getFolderTableChildproperty: data -// atURL: childURL -// withTag: proptag -// inFolder: folder -// withFID: fid]; -// } - -// return rc; -// } - -- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier +- (Class) messageTableClass { - MAPIRestrictionState rc; - id value; - - value = NSObjectFromMAPISPropValue (&res->lpProp); - switch (res->ulPropTag) - { - case PR_MESSAGE_CLASS_UNICODE: - if ([value isEqualToString: @"IPM.Appointment"]) - rc = MAPIRestrictionStateAlwaysTrue; - else - rc = MAPIRestrictionStateAlwaysFalse; - break; - case 0x81930003: /* PidLidBusyStatus (named prop) */ - rc = MAPIRestrictionStateAlwaysTrue; // should be based on c_isopaque - break; - default: - rc = [super evaluatePropertyRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - static NSMutableDictionary *knownProperties = nil; - - if (!knownProperties) - { - knownProperties = [NSMutableDictionary new]; - // [knownProperties setObject: @"c_startdate" - // forKey: MAPIPropertyKey (PidLidAppointmentStartWhole)]; - [knownProperties setObject: @"c_startdate" - forKey: MAPIPropertyKey (0x818f0040)]; - // [knownProperties setObject: @"c_enddate" - // forKey: MAPIPropertyKey (PidLidAppointmentEndWhole)]; - [knownProperties setObject: @"c_enddate" - forKey: MAPIPropertyKey (0x818a0040)]; - // [knownProperties setObject: @"c_iscycle" - // forKey: MAPIPropertyKey (PidLidRecurring)]; - [knownProperties setObject: @"c_iscycle" - forKey: MAPIPropertyKey (0x81e70040)]; - } - - return [knownProperties objectForKey: MAPIPropertyKey (property)]; + return [MAPIStoreCalendarMessageTable class]; } @end diff --git a/OpenChange/MAPIStoreCalendarMessageTable.h b/OpenChange/MAPIStoreCalendarMessageTable.h new file mode 100644 index 000000000..1bed13a1b --- /dev/null +++ b/OpenChange/MAPIStoreCalendarMessageTable.h @@ -0,0 +1,32 @@ +/* MAPIStoreCalendarMessageTable.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 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. + */ + +#ifndef MAPISTORECALENDARMESSAGETABLE_H +#define MAPISTORECALENDARMESSAGETABLE_H + +#import "MAPIStoreGCSMessageTable.h" + +@interface MAPIStoreCalendarMessageTable : MAPIStoreGCSMessageTable + +@end + +#endif /* MAPISTORECALENDARMESSAGETABLE_H */ diff --git a/OpenChange/MAPIStoreCalendarMessageTable.m b/OpenChange/MAPIStoreCalendarMessageTable.m new file mode 100644 index 000000000..f59ae2516 --- /dev/null +++ b/OpenChange/MAPIStoreCalendarMessageTable.m @@ -0,0 +1,192 @@ +/* MAPIStoreCalendarMessageTable.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 "MAPIStoreTypes.h" +#import "NSCalendarDate+MAPIStore.h" +#import "NSString+MAPIStore.h" + +#import "MAPIStoreCalendarMessageTable.h" + +#include + +@implementation MAPIStoreCalendarMessageTable + +- (EOQualifier *) componentQualifier +{ + static EOQualifier *componentQualifier = nil; + + if (!componentQualifier) + componentQualifier + = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" + operatorSelector: EOQualifierOperatorEqual + value: @"vevent"]; + + return componentQualifier; +} + +- (enum MAPISTATUS) getChildProperty: (void **) data + forKey: (NSString *) childKey + withTag: (enum MAPITAGS) propTag +{ + // id child; + NSTimeInterval timeValue; + id event; + int rc; + + rc = MAPI_E_SUCCESS; + switch (propTag) + { + case PR_ICON_INDEX: // TODO + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ + // *longValue = 0x00000401 for recurring event + // *longValue = 0x00000402 for meeting + // *longValue = 0x00000403 for recurring meeting + // *longValue = 0x00000404 for invitation + *data = MAPILongValue (memCtx, 0x00000400); + break; + case PR_MESSAGE_CLASS_UNICODE: + *data = talloc_strdup(memCtx, "IPM.Appointment"); + break; + case PidLidAppointmentStartWhole: // DTSTART + event = [[self lookupChild: childKey] component: NO secure: NO]; + *data = [[event startDate] asFileTimeInMemCtx: memCtx]; + break; + case PidLidAppointmentEndWhole: // DTEND + event = [[self lookupChild: childKey] component: NO secure: NO]; + *data = [[event endDate] asFileTimeInMemCtx: memCtx]; + break; + case PidLidAppointmentDuration: + event = [[self lookupChild: childKey] component: NO secure: NO]; + timeValue = [[event endDate] timeIntervalSinceDate: [event startDate]]; + *data = MAPILongValue (memCtx, (uint32_t) (timeValue / 60)); + break; + case PidLidAppointmentSubType: + event = [[self lookupChild: childKey] component: NO secure: NO]; + *data = MAPIBoolValue (memCtx, [event isAllDay]); + break; + case PidLidBusyStatus: // TODO + *data = MAPILongValue (memCtx, 0x02); + break; + case PidLidRecurring: // TODO + *data = MAPIBoolValue (memCtx, NO); + break; + + // case 0x82410003: // TODO + // *data = MAPILongValue (memCtx, 0); + // break; + case PR_SUBJECT_UNICODE: // SUMMARY + case PR_NORMALIZED_SUBJECT_UNICODE: + case PR_CONVERSATION_TOPIC_UNICODE: + event = [[self lookupChild: childKey] component: NO secure: NO]; + *data = [[event summary] asUnicodeInMemCtx: memCtx]; + break; + case PidLidLocation: // LOCATION + event = [[self lookupChild: childKey] component: NO secure: NO]; + *data = [[event location] asUnicodeInMemCtx: memCtx]; + break; + case PidLidPrivate: // private (bool), should depend on CLASS + *data = MAPIBoolValue (memCtx, NO); + break; + case PR_SENSITIVITY: // not implemented, depends on CLASS + // normal = 0, personal?? = 1, private = 2, confidential = 3 + *data = MAPILongValue (memCtx, 0); + break; + case PR_CREATION_TIME: + event = [[self lookupChild: childKey] component: NO secure: NO]; + *data = [[event created] asFileTimeInMemCtx: memCtx]; + break; + + case PidLidTimeZoneStruct: + + + // case PR_VD_NAME_UNICODE: + // *data = talloc_strdup(memCtx, "PR_VD_NAME_UNICODE"); + // break; + // case PR_EMS_AB_DXA_REMOTE_CLIENT_UNICODE: "Home:" ??? + // *data = talloc_strdup(memCtx, "PR_EMS..."); + // break; + default: + rc = [super getChildProperty: data + forKey: childKey + withTag: propTag]; + } + + // #define PR_REPLY_TIME PROP_TAG(PT_SYSTIME , 0x0030) /* 0x00300040 */ + // #define PR_INTERNET_MESSAGE_ID_UNICODE PROP_TAG(PT_UNICODE , 0x1035) /* 0x1035001f */ + // #define PR_FLAG_STATUS PROP_TAG(PT_LONG , 0x1090) /* 0x10900003 */ + + return rc; +} + +- (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 isEqualToString: @"IPM.Appointment"]) + rc = MAPIRestrictionStateAlwaysTrue; + else + rc = MAPIRestrictionStateAlwaysFalse; + break; + case PidLidBusyStatus: + rc = MAPIRestrictionStateAlwaysTrue; // should be based on c_isopaque + break; + default: + rc = [super evaluatePropertyRestriction: res intoQualifier: qualifier]; + } + + return rc; +} + +- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property +{ + static NSMutableDictionary *knownProperties = nil; + + if (!knownProperties) + { + knownProperties = [NSMutableDictionary new]; + [knownProperties setObject: @"c_startdate" + forKey: MAPIPropertyKey (PidLidAppointmentStartWhole)]; + [knownProperties setObject: @"c_enddate" + forKey: MAPIPropertyKey (PidLidAppointmentEndWhole)]; + [knownProperties setObject: @"c_iscycle" + forKey: MAPIPropertyKey (PidLidRecurring)]; + } + + return [knownProperties objectForKey: MAPIPropertyKey (property)]; +} + +@end