diff --git a/ChangeLog b/ChangeLog index 92d9ee779..ae26fb302 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-07-21 Wolfgang Sourdeau + + * OpenChange/MAPIStoreMailMessage.m: make use of the new class + below for calendar contents. + + * OpenChange/MAPIStoreCalendarMessage.m: make use of the new class + below. + (-save): handle invitation replies. + + * OpenChange/MAPIStoreAppointmentWrapper.m: new wrapper class + module that implements the getters for iCalEvent objects. + 2011-07-20 Wolfgang Sourdeau * OpenChange/MAPIStoreMailMessage.m (-subject): new overridable diff --git a/OpenChange/GNUmakefile b/OpenChange/GNUmakefile index 28bcea319..b76eb89d7 100644 --- a/OpenChange/GNUmakefile +++ b/OpenChange/GNUmakefile @@ -36,6 +36,7 @@ $(SOGOBACKEND)_OBJC_FILES += \ SOGoMAPIFSFolder.m \ SOGoMAPIFSMessage.m \ \ + MAPIStoreAppointmentWrapper.m \ MAPIStoreAttachment.m \ MAPIStoreAttachmentTable.m \ MAPIStoreContext.m \ diff --git a/OpenChange/MAPIStoreAppointmentWrapper.h b/OpenChange/MAPIStoreAppointmentWrapper.h new file mode 100644 index 000000000..313bb2143 --- /dev/null +++ b/OpenChange/MAPIStoreAppointmentWrapper.h @@ -0,0 +1,99 @@ +/* MAPIStoreAppointmentWrapper.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 MAPISTORECALENDARWRAPPER_H +#define MAPISTORECALENDARWRAPPER_H + +#import + +@class NSTimeZone; + +@class iCalCalendar; +@class iCalEvent; + +extern NSTimeZone *utcTZ; + +@interface MAPIStoreAppointmentWrapper : NSObject +{ + iCalCalendar *calendar; + iCalEvent *event; + NSTimeZone *timeZone; +} + ++ (id) wrapperWithICalEvent: (iCalEvent *) newEvent + inTimeZone: (NSTimeZone *) newTimeZone; +- (id) initWithICalEvent: (iCalEvent *) newEvent + inTimeZone: (NSTimeZone *) newTimeZone; + +/* getters */ +- (int) getPrIconIndex: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPrMessageClass: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPrBody: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPrStartDate: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidAppointmentStartWhole: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidCommonStart: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPrEndDate: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidAppointmentEndWhole: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidCommonEnd: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidAppointmentDuration: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidAppointmentSubType: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidBusyStatus: (void **) data // TODO + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidIndentedBusyStatus: (void **) data // TODO + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPrSubject: (void **) data // SUMMARY + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidLocation: (void **) data // LOCATION + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPrSensitivity: (void **) data // not implemented, depends on CLASS + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPrImportance: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidIsRecurring: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidRecurring: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidAppointmentRecur: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidGlobalObjectId: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidCleanGlobalObjectId: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidServerProcessed: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; + +@end + +#endif /* MAPISTORECALENDARWRAPPER_H */ diff --git a/OpenChange/MAPIStoreAppointmentWrapper.m b/OpenChange/MAPIStoreAppointmentWrapper.m new file mode 100644 index 000000000..4922064d2 --- /dev/null +++ b/OpenChange/MAPIStoreAppointmentWrapper.m @@ -0,0 +1,420 @@ +/* MAPIStoreAppointmentWrapper.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 "MAPIStoreRecurrenceUtils.h" +#import "MAPIStoreTypes.h" +#import "NSData+MAPIStore.h" +#import "NSDate+MAPIStore.h" +#import "NSObject+MAPIStore.h" +#import "NSString+MAPIStore.h" + +#import "MAPIStoreAppointmentWrapper.h" + +#undef DEBUG +#include +#include +#include +#include +#include +#include +#include + +NSTimeZone *utcTZ; + +@implementation MAPIStoreAppointmentWrapper + ++ (void) initialize +{ + utcTZ = [NSTimeZone timeZoneWithName: @"UTC"]; + [utcTZ retain]; +} + ++ (id) wrapperWithICalEvent: (iCalEvent *) newEvent + inTimeZone: (NSTimeZone *) newTimeZone +{ + MAPIStoreAppointmentWrapper *wrapper; + + wrapper = [[self alloc] initWithICalEvent: newEvent + inTimeZone: newTimeZone]; + [wrapper autorelease]; + + return wrapper; +} + +- (id) initWithICalEvent: (iCalEvent *) newEvent + inTimeZone: (NSTimeZone *) newTimeZone +{ + if ((self = [self init])) + { + ASSIGN (event, newEvent); + ASSIGN (calendar, [event parent]); + ASSIGN (timeZone, newTimeZone); + } + + return self; +} + +- (void) dealloc +{ + [calendar release]; + [event release]; + [super dealloc]; +} + +- (int) getPrIconIndex: (void **) data // TODO + inMemCtx: (TALLOC_CTX *) memCtx +{ + uint32_t longValue; + + /* 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 + + longValue = 0x0400; + if ([event isRecurrent]) + longValue |= 0x0001; + if ([[event attendees] count] > 0) + longValue |= 0x0002; + + *data = MAPILongValue (memCtx, longValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageClass: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + *data = talloc_strdup(memCtx, "IPM.Appointment"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrBody: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + NSString *stringValue; + + stringValue = [event comment]; + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrStartDate: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + NSCalendarDate *dateValue; + + if ([event isRecurrent]) + dateValue = [event firstRecurrenceStartDate]; + else + dateValue = [event startDate]; + [dateValue setTimeZone: utcTZ]; + *data = [dateValue asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidAppointmentStartWhole: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [self getPrStartDate: data inMemCtx: memCtx]; +} + +- (int) getPidLidCommonStart: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [self getPidLidAppointmentStartWhole: data inMemCtx: memCtx]; +} + +- (int) getPrEndDate: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + NSCalendarDate *dateValue; + + if ([event isRecurrent]) + dateValue = [event firstRecurrenceStartDate]; + else + dateValue = [event startDate]; + dateValue + = [dateValue dateByAddingYears: 0 months: 0 days: 0 + hours: 0 minutes: 0 + seconds: (NSInteger) [event + durationAsTimeInterval]]; + [dateValue setTimeZone: utcTZ]; + *data = [dateValue asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidAppointmentEndWhole: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [self getPrEndDate: data inMemCtx: memCtx]; +} + +- (int) getPidLidCommonEnd: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [self getPidLidAppointmentEndWhole: data inMemCtx: memCtx]; +} + +- (int) getPidLidAppointmentDuration: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + NSTimeInterval timeValue; + + timeValue = [[event endDate] timeIntervalSinceDate: [event startDate]]; + *data = MAPILongValue (memCtx, (uint32_t) (timeValue / 60)); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidAppointmentSubType: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + *data = MAPIBoolValue (memCtx, [event isAllDay]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidBusyStatus: (void **) data // TODO + inMemCtx: (TALLOC_CTX *) memCtx +{ + *data = MAPILongValue (memCtx, 0x02); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidIndentedBusyStatus: (void **) data // TODO + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [self getPidLidBusyStatus: data inMemCtx: memCtx]; +} + +- (int) getPrSubject: (void **) data // SUMMARY + inMemCtx: (TALLOC_CTX *) memCtx +{ + *data = [[event summary] asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidLocation: (void **) data // LOCATION + inMemCtx: (TALLOC_CTX *) memCtx +{ + *data = [[event location] asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidWhere: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [self getPidLidLocation: data inMemCtx: memCtx]; +} + +- (int) getPidLidServerProcessed: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [self getNo: data inMemCtx: memCtx]; +} + +- (int) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [self getNo: data inMemCtx: memCtx]; +} + +- (int) getPrSensitivity: (void **) data // not implemented, depends on CLASS + inMemCtx: (TALLOC_CTX *) memCtx +{ + // normal = 0, personal?? = 1, private = 2, confidential = 3 + return [self getLongZero: data inMemCtx: memCtx]; +} + +- (int) getPrImportance: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + uint32_t v; + if ([[event priority] isEqualToString: @"9"]) + v = 0x0; + else if ([[event priority] isEqualToString: @"1"]) + v = 0x2; + else + v = 0x1; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidIsRecurring: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + *data = MAPIBoolValue (memCtx, [event isRecurrent]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidRecurring: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + *data = MAPIBoolValue (memCtx, [event isRecurrent]); + + return MAPISTORE_SUCCESS; +} + +static void +_fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, + NSCalendarDate *startDate, NSTimeInterval duration, + NSCalendarDate * endDate, iCalRecurrenceRule *rule) +{ + uint32_t startMinutes; + + [rule fillRecurrencePattern: &arp->RecurrencePattern + withStartDate: startDate andEndDate: endDate]; + arp->ReaderVersion2 = 0x00003006; + arp->WriterVersion2 = 0x00003009; + + startMinutes = ([startDate hourOfDay] * 60 + [startDate minuteOfHour]); + arp->StartTimeOffset = startMinutes; + arp->EndTimeOffset = startMinutes + (uint32_t) (duration / 60); + + arp->ExceptionCount = 0; + arp->ReservedBlock1Size = 0; + + /* Currently ignored in property.idl: + arp->ReservedBlock2Size = 0; */ +} + +- (struct SBinary_short *) _computeAppointmentRecurInMemCtx: (TALLOC_CTX *) memCtx + +{ + struct AppointmentRecurrencePattern *arp; + struct Binary_r *bin; + struct SBinary_short *sBin; + NSCalendarDate *firstStartDate; + iCalRecurrenceRule *rule; + + rule = [[event recurrenceRules] objectAtIndex: 0]; + + firstStartDate = [event firstRecurrenceStartDate]; + if (firstStartDate) + { + [firstStartDate setTimeZone: timeZone]; + + arp = talloc_zero (memCtx, struct AppointmentRecurrencePattern); + _fillAppointmentRecurrencePattern (arp, firstStartDate, + [event durationAsTimeInterval], + [event lastPossibleRecurrenceStartDate], + rule); + sBin = talloc_zero (memCtx, struct SBinary_short); + bin = set_AppointmentRecurrencePattern (sBin, arp); + sBin->cb = bin->cb; + sBin->lpb = bin->lpb; + talloc_free (arp); + + // DEBUG(5, ("To client:\n")); + // NDR_PRINT_DEBUG (AppointmentRecurrencePattern, arp); + } + else + { + [self errorWithFormat: @"no first occurrence found in rule: %@", rule]; + sBin = NULL; + } + + return sBin; +} + +- (int) getPidLidAppointmentRecur: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + int rc = MAPISTORE_SUCCESS; + + if ([event isRecurrent]) + *data = [self _computeAppointmentRecurInMemCtx: memCtx]; + else + rc = MAPISTORE_ERR_NOT_FOUND; + + return rc; +} + +- (int) getPidLidGlobalObjectId: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + static char byteArrayId[] = {0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0xE0, + 0x00, 0x74, 0xC5, 0xB7, 0x10, 0x1A, 0x82, + 0xE0, 0x08}; + static char X[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + NSMutableData *nsData; + NSData *uidData; + NSCalendarDate *creationTime; + struct FILETIME *creationFileTime; + uint32_t uidDataLength; + + nsData = [NSMutableData dataWithCapacity: 256]; + [nsData appendBytes: byteArrayId length: 16]; + + /* FIXME TODO */ + [nsData appendBytes: X length: 4]; + /* /FIXME */ + + creationTime = [event created]; + creationFileTime = [creationTime asFileTimeInMemCtx: NULL]; + [nsData appendBytes: &creationFileTime->dwLowDateTime length: 4]; + [nsData appendBytes: &creationFileTime->dwHighDateTime length: 4]; + talloc_free (creationFileTime); + + uidData = [[event uid] dataUsingEncoding: NSUTF8StringEncoding]; + uidDataLength = [uidData length]; + [nsData appendBytes: &uidDataLength length: 4]; + [nsData appendData: uidData]; + *data = [nsData asBinaryInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidCleanGlobalObjectId: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [self getPidLidGlobalObjectId: data + inMemCtx: memCtx]; +} + +@end diff --git a/OpenChange/MAPIStoreCalendarMessage.h b/OpenChange/MAPIStoreCalendarMessage.h index cfc6b1c5f..4ccab5cdd 100644 --- a/OpenChange/MAPIStoreCalendarMessage.h +++ b/OpenChange/MAPIStoreCalendarMessage.h @@ -25,7 +25,12 @@ #import "MAPIStoreGCSMessage.h" +@class MAPIStoreAppointmentWrapper; + @interface MAPIStoreCalendarMessage : MAPIStoreGCSMessage +{ + MAPIStoreAppointmentWrapper *appointmentWrapper; +} @end diff --git a/OpenChange/MAPIStoreCalendarMessage.m b/OpenChange/MAPIStoreCalendarMessage.m index b3771f62a..024a4c50d 100644 --- a/OpenChange/MAPIStoreCalendarMessage.m +++ b/OpenChange/MAPIStoreCalendarMessage.m @@ -24,6 +24,8 @@ - merge common code with tasks - take the tz definitions from Outlook */ +#include + #import #import #import @@ -32,14 +34,16 @@ #import #import #import -#import +#import #import -#import -#import +#import #import +#import #import #import +#import +#import "MAPIStoreAppointmentWrapper.h" #import "MAPIStoreCalendarAttachment.h" #import "MAPIStoreContext.h" #import "MAPIStoreRecurrenceUtils.h" @@ -63,313 +67,167 @@ // extern void ndr_print_AppointmentRecurrencePattern(struct ndr_print *ndr, const char *name, const struct AppointmentRecurrencePattern *r); -static NSTimeZone *utcTZ; - @implementation MAPIStoreCalendarMessage -+ (void) initialize -{ - utcTZ = [NSTimeZone timeZoneWithName: @"UTC"]; - [utcTZ retain]; -} - - (id) init { if ((self = [super init])) { - attachmentKeys = [NSMutableArray new]; - attachmentParts = [NSMutableDictionary new]; + appointmentWrapper = nil; } return self; } -/* getters */ -- (int) getPrIconIndex: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx +- (void) dealloc +{ + [appointmentWrapper release]; + [super dealloc]; +} + +- (MAPIStoreAppointmentWrapper *) appointmentWrapper { - uint32_t longValue; iCalEvent *event; - event = [sogoObject component: NO secure: NO]; + if (!appointmentWrapper) + { + event = [sogoObject component: NO secure: NO]; + ASSIGN (appointmentWrapper, + [MAPIStoreAppointmentWrapper wrapperWithICalEvent: event + inTimeZone: [self ownerTimeZone]]); + } - /* 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 - - longValue = 0x0400; - if ([event isRecurrent]) - longValue |= 0x0001; - if ([[event attendees] count] > 0) - longValue |= 0x0002; - - *data = MAPILongValue (memCtx, longValue); + return appointmentWrapper; +} - return MAPISTORE_SUCCESS; +/* getters */ +- (int) getPrIconIndex: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [[self appointmentWrapper] getPrIconIndex: data inMemCtx: memCtx]; } - (int) getPrMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - *data = talloc_strdup(memCtx, "IPM.Appointment"); - - return MAPISTORE_SUCCESS; + return [[self appointmentWrapper] getPrMessageClass: data inMemCtx: memCtx]; } - (int) getPrStartDate: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - NSCalendarDate *dateValue; - iCalEvent *event; - - event = [sogoObject component: NO secure: NO]; - - if ([event isRecurrent]) - dateValue = [event firstRecurrenceStartDate]; - else - dateValue = [event startDate]; - [dateValue setTimeZone: utcTZ]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; + return [[self appointmentWrapper] getPrStartDate: data inMemCtx: memCtx]; } - (int) getPidLidAppointmentStartWhole: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - return [self getPrStartDate: data inMemCtx: memCtx]; + return [[self appointmentWrapper] getPidLidAppointmentStartWhole: data inMemCtx: memCtx]; } - (int) getPidLidCommonStart: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - return [self getPrStartDate: data inMemCtx: memCtx]; + return [[self appointmentWrapper] getPidLidCommonStart: data inMemCtx: memCtx]; } - (int) getPrEndDate: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - NSCalendarDate *dateValue; - iCalEvent *event; - - event = [sogoObject component: NO secure: NO]; - - if ([event isRecurrent]) - dateValue = [event firstRecurrenceStartDate]; - else - dateValue = [event startDate]; - dateValue - = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: (NSInteger) [event - durationAsTimeInterval]]; - [dateValue setTimeZone: utcTZ]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; + return [[self appointmentWrapper] getPrEndDate: data inMemCtx: memCtx]; } - (int) getPidLidAppointmentEndWhole: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - return [self getPrEndDate: data inMemCtx: memCtx]; + return [[self appointmentWrapper] getPidLidAppointmentEndWhole: data inMemCtx: memCtx]; } - (int) getPidLidCommonEnd: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - return [self getPrEndDate: data inMemCtx: memCtx]; + return [[self appointmentWrapper] getPidLidCommonEnd: data inMemCtx: memCtx]; } - (int) getPidLidAppointmentDuration: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - NSTimeInterval timeValue; - iCalEvent *event; - - event = [sogoObject component: NO secure: NO]; - - timeValue = [[event endDate] timeIntervalSinceDate: [event startDate]]; - *data = MAPILongValue (memCtx, (uint32_t) (timeValue / 60)); - - return MAPISTORE_SUCCESS; + return [[self appointmentWrapper] getPidLidAppointmentDuration: data inMemCtx: memCtx]; } - (int) getPidLidAppointmentSubType: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - iCalEvent *event; - - event = [sogoObject component: NO secure: NO]; - *data = MAPIBoolValue (memCtx, [event isAllDay]); - - return MAPISTORE_SUCCESS; + return [[self appointmentWrapper] getPidLidAppointmentSubType: data inMemCtx: memCtx]; } - (int) getPidLidBusyStatus: (void **) data // TODO inMemCtx: (TALLOC_CTX *) memCtx { - *data = MAPILongValue (memCtx, 0x02); - - return MAPISTORE_SUCCESS; + return [[self appointmentWrapper] getPidLidBusyStatus: data inMemCtx: memCtx]; } - (int) getPrSubject: (void **) data // SUMMARY inMemCtx: (TALLOC_CTX *) memCtx { - iCalEvent *event; - - event = [sogoObject component: NO secure: NO]; - *data = [[event summary] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; + return [[self appointmentWrapper] getPrSubject: data inMemCtx: memCtx]; } - (int) getPidLidLocation: (void **) data // LOCATION inMemCtx: (TALLOC_CTX *) memCtx { - iCalEvent *event; - - event = [sogoObject component: NO secure: NO]; - *data = [[event location] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; + return [[self appointmentWrapper] getPidLidLocation: data inMemCtx: memCtx]; } - (int) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions inMemCtx: (TALLOC_CTX *) memCtx { - return [self getNo: data inMemCtx: memCtx]; + return [[self appointmentWrapper] getPidLidPrivate: data inMemCtx: memCtx]; } - (int) getPrSensitivity: (void **) data // not implemented, depends on CLASS inMemCtx: (TALLOC_CTX *) memCtx { - // normal = 0, personal?? = 1, private = 2, confidential = 3 - return [self getLongZero: data inMemCtx: memCtx]; + return [[self appointmentWrapper] getPrSensitivity: data inMemCtx: memCtx]; } - (int) getPrImportance: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - uint32_t v; - iCalEvent *event; - - event = [sogoObject component: NO secure: NO]; - if ([[event priority] isEqualToString: @"9"]) - v = 0x0; - else if ([[event priority] isEqualToString: @"1"]) - v = 0x2; - else - v = 0x1; - - *data = MAPILongValue (memCtx, v); - - return MAPISTORE_SUCCESS; + return [[self appointmentWrapper] getPrImportance: data inMemCtx: memCtx]; } - (int) getPidLidIsRecurring: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - iCalEvent *event; - - event = [sogoObject component: NO secure: NO]; - *data = MAPIBoolValue (memCtx, [event isRecurrent]); - - return MAPISTORE_SUCCESS; + return [[self appointmentWrapper] getPidLidIsRecurring: data inMemCtx: memCtx]; } - (int) getPidLidRecurring: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - iCalEvent *event; - - event = [sogoObject component: NO secure: NO]; - *data = MAPIBoolValue (memCtx, [event isRecurrent]); - - return MAPISTORE_SUCCESS; -} - -static void -_fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, - NSCalendarDate *startDate, NSTimeInterval duration, - NSCalendarDate * endDate, iCalRecurrenceRule * rule) -{ - uint32_t startMinutes; - - [rule fillRecurrencePattern: &arp->RecurrencePattern - withStartDate: startDate andEndDate: endDate]; - arp->ReaderVersion2 = 0x00003006; - arp->WriterVersion2 = 0x00003009; - - startMinutes = ([startDate hourOfDay] * 60 + [startDate minuteOfHour]); - arp->StartTimeOffset = startMinutes; - arp->EndTimeOffset = startMinutes + (uint32_t) (duration / 60); - - arp->ExceptionCount = 0; - arp->ReservedBlock1Size = 0; - - /* Currently ignored in property.idl: - arp->ReservedBlock2Size = 0; */ -} - -- (struct SBinary_short *) _computeAppointmentRecurInMemCtx: (TALLOC_CTX *) memCtx - -{ - struct AppointmentRecurrencePattern *arp; - struct Binary_r *bin; - struct SBinary_short *sBin; - NSCalendarDate *firstStartDate; - iCalRecurrenceRule *rule; - iCalEvent *event; - - event = [sogoObject component: NO secure: NO]; - rule = [[event recurrenceRules] objectAtIndex: 0]; - - firstStartDate = [event firstRecurrenceStartDate]; - if (firstStartDate) - { - [firstStartDate setTimeZone: [self ownerTimeZone]]; - - arp = talloc_zero (memCtx, struct AppointmentRecurrencePattern); - _fillAppointmentRecurrencePattern (arp, firstStartDate, - [event durationAsTimeInterval], - [event lastPossibleRecurrenceStartDate], - rule); - sBin = talloc_zero (memCtx, struct SBinary_short); - bin = set_AppointmentRecurrencePattern (sBin, arp); - sBin->cb = bin->cb; - sBin->lpb = bin->lpb; - talloc_free (arp); - - // DEBUG(5, ("To client:\n")); - // NDR_PRINT_DEBUG (AppointmentRecurrencePattern, arp); - } - else - { - [self errorWithFormat: @"no first occurrence found in rule: %@", rule]; - sBin = NULL; - } - - return sBin; + return [[self appointmentWrapper] getPidLidRecurring: data inMemCtx: memCtx]; } - (int) getPidLidAppointmentRecur: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - int rc = MAPISTORE_SUCCESS; - iCalEvent *event; + return [[self appointmentWrapper] getPidLidAppointmentRecur: data + inMemCtx: memCtx]; +} - event = [sogoObject component: NO secure: NO]; +- (int) getPidLidGlobalObjectId: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [[self appointmentWrapper] getPidLidGlobalObjectId: data + inMemCtx: memCtx]; +} - if ([event isRecurrent]) - *data = [self _computeAppointmentRecurInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; +- (int) getPidLidCleanGlobalObjectId: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [[self appointmentWrapper] getPidLidCleanGlobalObjectId: data + inMemCtx: memCtx]; } - (void) getMessageData: (struct mapistore_message **) dataPtr @@ -462,6 +320,7 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, NSCalendarDate *now; NSString *content, *tzName; iCalEvent *newEvent; + NSUInteger responseStatus = 0; id value; [self logWithFormat: @"-save, event props:"]; @@ -524,42 +383,76 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, [newEvent setTimeStampAsDate: now]; // Organizer and attendees - value = [newProperties objectForKey: @"recipients"]; - + value + = [newProperties objectForKey: MAPIPropertyKey (PidLidResponseStatus)]; if (value) + responseStatus = [value unsignedLongValue]; + + woContext = [[self context] woContext]; + if (responseStatus == 0) { - NSArray *recipients; - NSDictionary *dict; - iCalPerson *person; - int i; + value = [newProperties objectForKey: @"recipients"]; + if (value) + { + NSArray *recipients; + NSDictionary *dict; + iCalPerson *person; + int i; - woContext = [[self context] woContext]; - dict = [[woContext activeUser] primaryIdentity]; - person = [iCalPerson new]; - [person setCn: [dict objectForKey: @"fullName"]]; - [person setEmail: [dict objectForKey: @"email"]]; - [newEvent setOrganizer: person]; - [person release]; + dict = [[woContext activeUser] primaryIdentity]; + person = [iCalPerson new]; + [person setCn: [dict objectForKey: @"fullName"]]; + [person setEmail: [dict objectForKey: @"email"]]; + [newEvent setOrganizer: person]; + [person release]; - recipients = [value objectForKey: @"to"]; + recipients = [value objectForKey: @"to"]; - for (i = 0; i < [recipients count]; i++) - { - dict = [recipients objectAtIndex: i]; - person = [iCalPerson new]; + for (i = 0; i < [recipients count]; i++) + { + dict = [recipients objectAtIndex: i]; + person = [iCalPerson new]; + + [person setCn: [dict objectForKey: @"fullName"]]; + [person setEmail: [dict objectForKey: @"email"]]; + [person setParticipationStatus: iCalPersonPartStatNeedsAction]; + [person setRsvp: @"TRUE"]; + [person setRole: @"REQ-PARTICIPANT"]; - [person setCn: [dict objectForKey: @"fullName"]]; - [person setEmail: [dict objectForKey: @"email"]]; - [person setParticipationStatus: iCalPersonPartStatNeedsAction]; - [person setRsvp: @"TRUE"]; - [person setRole: @"REQ-PARTICIPANT"]; + // FIXME: We must NOT always rely on this + if (![newEvent isAttendee: [person rfc822Email]]) + [newEvent addToAttendees: person]; - // FIXME: We must NOT always rely on this - if (![newEvent isAttendee: [person rfc822Email]]) - [newEvent addToAttendees: person]; + [person release]; + } + } + } + else + { + iCalPersonPartStat newPartStat; - [person release]; - } + switch (responseStatus) + { + case 0x02: /* respTentative */ + newPartStat = iCalPersonPartStatTentative; + break; + case 0x03: /* respAccepted */ + newPartStat = iCalPersonPartStatAccepted; + break; + case 0x04: /* respDeclined */ + newPartStat = iCalPersonPartStatDeclined; + break; + default: + newPartStat = iCalPersonPartStatUndefined; + } + + if (newPartStat != iCalPersonPartStatUndefined) + { + iCalPerson *participant; + + participant = [newEvent userAsAttendee: [woContext activeUser]]; + [participant setParticipationStatus: newPartStat]; + } } /* recurrence */ diff --git a/OpenChange/MAPIStoreCalendarMessageTable.m b/OpenChange/MAPIStoreCalendarMessageTable.m index 76aead966..eece603d9 100644 --- a/OpenChange/MAPIStoreCalendarMessageTable.m +++ b/OpenChange/MAPIStoreCalendarMessageTable.m @@ -65,6 +65,9 @@ static Class MAPIStoreCalendarMessageK = Nil; else rc = MAPIRestrictionStateAlwaysFalse; break; + case PR_OWNER_APPT_ID: + rc = MAPIRestrictionStateAlwaysFalse; + break; case PidLidBusyStatus: rc = MAPIRestrictionStateAlwaysTrue; // should be based on c_isopaque break; diff --git a/OpenChange/MAPIStoreMailMessage.h b/OpenChange/MAPIStoreMailMessage.h index 2d0e92fdc..8379e49ae 100644 --- a/OpenChange/MAPIStoreMailMessage.h +++ b/OpenChange/MAPIStoreMailMessage.h @@ -28,13 +28,22 @@ @class NSData; @class NSString; +@class MAPIStoreAppointmentWrapper; + @interface MAPIStoreMailMessage : MAPIStoreMessage { - BOOL fetchedAttachments; + BOOL headerSetup; + BOOL mailIsEvent; + NSString *mimeKey; + NSString *headerCharset; + NSString *headerEncoding; + NSString *headerMethod; + NSString *headerMimeType; BOOL bodySetup; NSData *bodyContent; - NSString *bodyMimeType; - NSString *bodyCharset; + BOOL fetchedAttachments; + + MAPIStoreAppointmentWrapper *appointmentWrapper; } - (NSString *) subject; diff --git a/OpenChange/MAPIStoreMailMessage.m b/OpenChange/MAPIStoreMailMessage.m index f5a3193fc..3d58668d8 100644 --- a/OpenChange/MAPIStoreMailMessage.m +++ b/OpenChange/MAPIStoreMailMessage.m @@ -24,9 +24,10 @@ #import #import #import +#import +#import #import #import -#import #import #import #import @@ -34,11 +35,12 @@ #import "NSData+MAPIStore.h" #import "NSObject+MAPIStore.h" #import "NSString+MAPIStore.h" +#import "MAPIStoreAppointmentWrapper.h" #import "MAPIStoreContext.h" #import "MAPIStoreFolder.h" +#import "MAPIStoreMailAttachment.h" #import "MAPIStoreMailFolder.h" #import "MAPIStoreTypes.h" -#import "MAPIStoreMailAttachment.h" #import "MAPIStoreMailMessage.h" @@ -49,6 +51,8 @@ #include #include +@class iCalCalendar, iCalEvent; + static Class NSExceptionK, MAPIStoreSentItemsFolderK, MAPIStoreDraftsFolderK; @interface NSString (MAPIStoreMIME) @@ -91,11 +95,17 @@ static Class NSExceptionK, MAPIStoreSentItemsFolderK, MAPIStoreDraftsFolderK; { if ((self = [super init])) { - bodySetup = NO; + mimeKey = nil; + mailIsEvent = NO; + headerCharset = nil; + headerEncoding = nil; + headerMethod = nil; + headerMimeType = nil; + headerSetup = NO; bodyContent = nil; - bodyMimeType = nil; - bodyCharset = nil; + bodySetup = NO; fetchedAttachments = NO; + appointmentWrapper = nil; } return self; @@ -103,20 +113,178 @@ static Class NSExceptionK, MAPIStoreSentItemsFolderK, MAPIStoreDraftsFolderK; - (void) dealloc { + [mimeKey release]; [bodyContent release]; - [bodyMimeType release]; - [bodyCharset release]; + [headerMimeType release]; + [headerCharset release]; + [headerMethod release]; + [appointmentWrapper release]; [super dealloc]; } +- (NSString *) subject +{ + return [sogoObject decodedSubject]; +} + +- (NSCalendarDate *) creationTime +{ + return [sogoObject date]; +} + +- (NSCalendarDate *) lastModificationTime +{ + return [sogoObject date]; +} + +static NSComparisonResult +_compareBodyKeysByPriority (id entry1, id entry2, void *data) +{ + NSComparisonResult result; + NSArray *keys; + NSString *data1, *data2; + NSUInteger count1, count2; + + keys = data; + + data1 = [entry1 objectForKey: @"mimeType"]; + count1 = [keys indexOfObject: data1]; + data2 = [entry2 objectForKey: @"mimeType"]; + count2 = [keys indexOfObject: data2]; + + if (count1 == count2) + { + data1 = [entry1 objectForKey: @"key"]; + count1 = [data1 countOccurrencesOfString: @"."]; + data2 = [entry2 objectForKey: @"key"]; + count2 = [data2 countOccurrencesOfString: @"."]; + if (count1 == count2) + { + data1 = [data1 _strippedBodyKey]; + count1 = [data1 intValue]; + data2 = [data2 _strippedBodyKey]; + count2 = [data2 intValue]; + if (count1 == count2) + result = NSOrderedSame; + else if (count1 < count2) + result = NSOrderedAscending; + else + result = NSOrderedDescending; + } + else if (count1 < count2) + result = NSOrderedAscending; + else + result = NSOrderedDescending; + } + else if (count1 < count2) + result = NSOrderedAscending; + else + result = NSOrderedDescending; + + return result; +} + +- (void) _fetchHeaderData +{ + NSMutableArray *keys; + NSArray *acceptedTypes; + NSDictionary *messageData, *partHeaderData, *parameters; + + acceptedTypes = [NSArray arrayWithObjects: @"text/calendar", + @"application/ics", + @"text/html", + @"text/plain", nil]; + keys = [NSMutableArray array]; + [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] + path: @"" toArray: keys + acceptedTypes: acceptedTypes]; + [keys sortUsingFunction: _compareBodyKeysByPriority context: acceptedTypes]; + if ([keys count] > 0) + { + messageData = [keys objectAtIndex: 0]; + ASSIGN (mimeKey, [messageData objectForKey: @"key"]); + ASSIGN (headerMimeType, [messageData objectForKey: @"mimeType"]); + partHeaderData + = [sogoObject lookupInfoForBodyPart: [mimeKey _strippedBodyKey]]; + ASSIGN (headerEncoding, [partHeaderData objectForKey: @"encoding"]); + parameters = [partHeaderData objectForKey: @"parameterList"]; + ASSIGN (headerCharset, [parameters objectForKey: @"charset"]); + if ([headerMimeType isEqualToString: @"text/calendar"] + || [headerMimeType isEqualToString: @"application/ics"]) + { + mailIsEvent = YES; + ASSIGN (headerMethod, [parameters objectForKey: @"method"]); + } + } + + headerSetup = YES; +} + +- (void) _fetchBodyData +{ + NSData *rawContent; + id result; + + if (!headerSetup) + [self _fetchHeaderData]; + + if (mimeKey) + { + result = [sogoObject fetchParts: [NSArray arrayWithObject: mimeKey]]; + result = [[result valueForKey: @"RawResponse"] objectForKey: @"fetch"]; + rawContent = [[result objectForKey: mimeKey] objectForKey: @"data"]; + ASSIGN (bodyContent, [rawContent bodyDataFromEncoding: headerEncoding]); + } + + bodySetup = YES; +} + +- (MAPIStoreAppointmentWrapper *) _appointmentWrapper +{ + NSArray *events; + iCalCalendar *calendar; + iCalEvent *event; + NSString *stringValue; + + if (!appointmentWrapper) + { + if (!bodySetup) + [self _fetchBodyData]; + + stringValue = [bodyContent bodyStringFromCharset: headerCharset]; + calendar = [iCalCalendar parseSingleFromSource: stringValue]; + events = [calendar events]; + if ([events count] > 0) + { + event = [events objectAtIndex: 0]; + appointmentWrapper = [MAPIStoreAppointmentWrapper + wrapperWithICalEvent: event + inTimeZone: [self ownerTimeZone]]; + [appointmentWrapper retain]; + } + } + + return appointmentWrapper; +} + - (int) getPrIconIndex: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { uint32_t longValue; + if (!headerSetup) + [self _fetchHeaderData]; + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ if ([sogoObject isNewMail]) longValue = 0xffffffff; + else if (mailIsEvent) + { + if ([headerMethod isEqualToString: @"REQUEST"]) + longValue = 0x0404; + else + longValue = 0x0400; + } else if ([sogoObject replied]) longValue = 0x105; else if ([sogoObject forwarded]) @@ -144,11 +312,6 @@ static Class NSExceptionK, MAPIStoreSentItemsFolderK, MAPIStoreDraftsFolderK; return MAPISTORE_SUCCESS; } -- (NSString *) subject -{ - return [sogoObject decodedSubject]; -} - - (int) getPrSubject: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { @@ -205,7 +368,22 @@ static Class NSExceptionK, MAPIStoreSentItemsFolderK, MAPIStoreDraftsFolderK; - (int) getPrMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - *data = talloc_strdup (memCtx, "IPM.Note"); + const char *className; + + if (!headerSetup) + [self _fetchHeaderData]; + + if (mailIsEvent) + { + if ([headerMethod isEqualToString: @"REQUEST"]) + className = "IPM.Schedule.Meeting.Request"; + else + className = "IPM.Appointment"; + } + else + className = "IPM.Note"; + + *data = talloc_strdup (memCtx, className); return MAPISTORE_SUCCESS; } @@ -213,25 +391,18 @@ static Class NSExceptionK, MAPIStoreSentItemsFolderK, MAPIStoreDraftsFolderK; - (int) getPrReplyRequested: (void **) data // TODO inMemCtx: (TALLOC_CTX *) memCtx { - return [self getNo: data inMemCtx: memCtx]; + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [self getYes: data inMemCtx: memCtx] + : [self getNo: data inMemCtx: memCtx]); } - (int) getPrResponseRequested: (void **) data // TODO inMemCtx: (TALLOC_CTX *) memCtx { - *data = MAPIBoolValue (memCtx, NO); - - return MAPISTORE_SUCCESS; -} - -- (NSCalendarDate *) creationTime -{ - return [sogoObject date]; -} - -- (NSCalendarDate *) lastModificationTime -{ - return [sogoObject date]; + return [self getPrReplyRequested: data inMemCtx: memCtx]; } - (int) getPrLatestDeliveryTime: (void **) data // DOUBT @@ -515,90 +686,6 @@ static Class NSExceptionK, MAPIStoreSentItemsFolderK, MAPIStoreDraftsFolderK; return MAPISTORE_SUCCESS; } -static NSComparisonResult -_compareBodyKeysByPriority (id entry1, id entry2, void *data) -{ - NSComparisonResult result; - NSArray *keys; - NSString *data1, *data2; - NSUInteger count1, count2; - - keys = data; - - data1 = [entry1 objectForKey: @"mimeType"]; - count1 = [keys indexOfObject: data1]; - data2 = [entry2 objectForKey: @"mimeType"]; - count2 = [keys indexOfObject: data2]; - - if (count1 == count2) - { - data1 = [entry1 objectForKey: @"key"]; - count1 = [data1 countOccurrencesOfString: @"."]; - data2 = [entry2 objectForKey: @"key"]; - count2 = [data2 countOccurrencesOfString: @"."]; - if (count1 == count2) - { - data1 = [data1 _strippedBodyKey]; - count1 = [data1 intValue]; - data2 = [data2 _strippedBodyKey]; - count2 = [data2 intValue]; - if (count1 == count2) - result = NSOrderedSame; - else if (count1 < count2) - result = NSOrderedAscending; - else - result = NSOrderedDescending; - } - else if (count1 < count2) - result = NSOrderedAscending; - else - result = NSOrderedDescending; - } - else if (count1 < count2) - result = NSOrderedAscending; - else - result = NSOrderedDescending; - - return result; -} - -- (void) _setupBodyData -{ - NSMutableArray *keys; - NSArray *acceptedTypes; - NSDictionary *messageData, *partHeaderData; - NSString *messageKey, *encoding; - NSData *rawContent; - id result; - - acceptedTypes = [NSArray arrayWithObjects: // @"text/calendar", - // @"application/ics", - @"text/html", - @"text/plain", nil]; - keys = [NSMutableArray array]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys - acceptedTypes: acceptedTypes]; - [keys sortUsingFunction: _compareBodyKeysByPriority context: acceptedTypes]; - if ([keys count] > 0) - { - messageData = [keys objectAtIndex: 0]; - ASSIGN (bodyMimeType, [messageData objectForKey: @"mimeType"]); - messageKey = [messageData objectForKey: @"key"]; - result = [sogoObject fetchParts: [NSArray arrayWithObject: messageKey]]; - result = [[result valueForKey: @"RawResponse"] objectForKey: @"fetch"]; - rawContent = [[result objectForKey: messageKey] objectForKey: @"data"]; - partHeaderData = [sogoObject - lookupInfoForBodyPart: [messageKey _strippedBodyKey]]; - encoding = [partHeaderData objectForKey: @"encoding"]; - ASSIGN (bodyContent, [rawContent bodyDataFromEncoding: encoding]); - ASSIGN (bodyCharset, [[partHeaderData objectForKey: @"parameterList"] - objectForKey: @"charset"]); - } - - bodySetup = YES; -} - - (int) getPrBody: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { @@ -606,13 +693,16 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) int rc = MAPISTORE_SUCCESS; if (!bodySetup) - [self _setupBodyData]; + [self _fetchBodyData]; - if ([bodyMimeType isEqualToString: @"text/plain"]) + if ([headerMimeType isEqualToString: @"text/plain"]) { - stringValue = [bodyContent bodyStringFromCharset: bodyCharset]; + stringValue = [bodyContent bodyStringFromCharset: headerCharset]; *data = [stringValue asUnicodeInMemCtx: memCtx]; } + else if (mailIsEvent) + rc = [[self _appointmentWrapper] getPrBody: data + inMemCtx: memCtx]; else { *data = NULL; @@ -628,9 +718,9 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) int rc = MAPISTORE_SUCCESS; if (!bodySetup) - [self _setupBodyData]; + [self _fetchBodyData]; - if ([bodyMimeType isEqualToString: @"text/html"]) + if ([headerMimeType isEqualToString: @"text/html"]) *data = [bodyContent asBinaryInMemCtx: memCtx]; else { @@ -675,37 +765,75 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) return [self getNo: data inMemCtx: memCtx]; } +- (int) getPidLidGlobalObjectId: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidGlobalObjectId: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidCleanGlobalObjectId: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidCleanGlobalObjectId: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidServerProcessed: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidServerProcessed: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + - (int) getPidLidPrivate: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - return [self getNo: data inMemCtx: memCtx]; + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidPrivate: data + inMemCtx: memCtx] + : [self getNo: data inMemCtx: memCtx]); +} + +- (int) getPidLidMeetingType: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [self getLongZero: data inMemCtx: memCtx]; } - (int) getPrMsgEditorFormat: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - NSMutableArray *keys; - NSArray *acceptedTypes; uint32_t format; + + if (!headerSetup) + [self _fetchHeaderData]; - format = 0; /* EDITOR_FORMAT_DONTKNOW */ - - acceptedTypes = [NSArray arrayWithObject: @"text/plain"]; - keys = [NSMutableArray array]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys - acceptedTypes: acceptedTypes]; - if ([keys count] == 1) + if ([headerMimeType isEqualToString: @"text/plain"]) format = EDITOR_FORMAT_PLAINTEXT; - - acceptedTypes = [NSArray arrayWithObject: @"text/html"]; - [keys removeAllObjects]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys - acceptedTypes: acceptedTypes]; - if ([keys count] == 1) + else if ([headerMimeType isEqualToString: @"text/html"]) format = EDITOR_FORMAT_HTML; - + else + format = 0; /* EDITOR_FORMAT_DONTKNOW */ + *data = MAPILongValue (memCtx, format); return MAPISTORE_SUCCESS; @@ -735,6 +863,193 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) return [self getYes: data inMemCtx: memCtx]; } +/* event getters */ +- (int) getPrStartDate: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPrStartDate: data inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidAppointmentMessageClass: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + int rc = MAPISTORE_SUCCESS; + + if (!headerSetup) + [self _fetchHeaderData]; + + if (mailIsEvent) + *data = talloc_strdup (memCtx, "IPM.Appointment"); + else + rc = MAPISTORE_ERR_NOT_FOUND; + + return rc; +} + +- (int) getPidLidAppointmentStartWhole: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidAppointmentStartWhole: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidCommonStart: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidCommonStart: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPrEndDate: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPrEndDate: data inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidAppointmentEndWhole: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidAppointmentEndWhole: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidCommonEnd: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidCommonEnd: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidAppointmentDuration: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidAppointmentDuration: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidAppointmentSubType: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidAppointmentSubType: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidBusyStatus: (void **) data // TODO + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidBusyStatus: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidLocation: (void **) data // LOCATION + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidLocation: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidIsRecurring: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidIsRecurring: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidRecurring: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidRecurring: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPidLidAppointmentRecur: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + if (!headerSetup) + [self _fetchHeaderData]; + + return (mailIsEvent + ? [[self _appointmentWrapper] getPidLidAppointmentRecur: data + inMemCtx: memCtx] + : MAPISTORE_ERR_NOT_FOUND); +} + +- (int) getPrOwnerApptId: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + int rc = MAPISTORE_SUCCESS; + + if (!headerSetup) + [self _fetchHeaderData]; + + if (mailIsEvent) + *data = MAPILongValue (memCtx, 0xabcd1234); + else + rc = MAPISTORE_ERR_NOT_FOUND; + + return rc; +} + - (void) getMessageData: (struct mapistore_message **) dataPtr inMemCtx: (TALLOC_CTX *) memCtx {