diff --git a/ChangeLog b/ChangeLog index 47260e335..7f7adc58e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2011-04-13 Wolfgang Sourdeau + * OpenChange/MAPIStoreObject.m: make use of the IMP cache methods + available in MAPIStorePropertySelectors to query object + properties. + * OpenChange/*{Message,Folder}.m: replaced the implementations of + -getProperty:withTag: with equivalent property getter methods. + * OpenChange/MAPIStoreContext.m (-url): new method that returns the context url. diff --git a/OpenChange/MAPIStoreCalendarMessage.h b/OpenChange/MAPIStoreCalendarMessage.h index 0c78c05e3..04a92712b 100644 --- a/OpenChange/MAPIStoreCalendarMessage.h +++ b/OpenChange/MAPIStoreCalendarMessage.h @@ -25,7 +25,13 @@ #import "MAPIStoreGCSMessage.h" +@class iCalEvent; + @interface MAPIStoreCalendarMessage : MAPIStoreGCSMessage +{ + iCalEvent *event; +} + @end #endif /* MAPISTORECALENDARMESSAGE_H */ diff --git a/OpenChange/MAPIStoreCalendarMessage.m b/OpenChange/MAPIStoreCalendarMessage.m index 4c26e478b..6a3e8fadd 100644 --- a/OpenChange/MAPIStoreCalendarMessage.m +++ b/OpenChange/MAPIStoreCalendarMessage.m @@ -73,17 +73,36 @@ static NSTimeZone *utcTZ; [utcTZ retain]; } +- (id) initWithSOGoObject: (id) newSOGoObject + inContainer: (MAPIStoreObject *) newContainer +{ + if ((self = [super initWithSOGoObject: newSOGoObject + inContainer: newContainer])) + { + ASSIGN (event, [newSOGoObject component: NO secure: NO]); + } + + return self; +} + - (id) init { if ((self = [super init])) { attachmentKeys = [NSMutableArray new]; attachmentParts = [NSMutableDictionary new]; + event = nil; } return self; } +- (void) dealloc +{ + [event release]; + [super dealloc]; +} + - (NSTimeZone *) ownerTimeZone { NSString *owner; @@ -100,7 +119,6 @@ static NSTimeZone *utcTZ; } - (void) _setupRecurrenceInCalendar: (iCalCalendar *) calendar - withMasterEvent: (iCalEvent *) vEvent fromData: (NSData *) mapiRecurrenceData { struct Binary_r *blob; @@ -109,13 +127,13 @@ static NSTimeZone *utcTZ; /* cleanup */ otherEvents = [[calendar events] mutableCopy]; - [otherEvents removeObject: vEvent]; + [otherEvents removeObject: event]; [calendar removeChildren: otherEvents]; [otherEvents release]; blob = [mapiRecurrenceData asBinaryInMemCtx: memCtx]; pattern = get_AppointmentRecurrencePattern (memCtx, blob); - [calendar setupRecurrenceWithMasterEntity: vEvent + [calendar setupRecurrenceWithMasterEntity: event fromRecurrencePattern: &pattern->RecurrencePattern]; talloc_free (pattern); talloc_free (blob); @@ -150,21 +168,19 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, struct Binary_r *bin; struct SBinary_short *sBin; NSCalendarDate *firstStartDate; - iCalEvent *vEvent; iCalRecurrenceRule *rule; - vEvent = [sogoObject component: NO secure: NO]; - rule = [[vEvent recurrenceRules] objectAtIndex: 0]; + rule = [[event recurrenceRules] objectAtIndex: 0]; - firstStartDate = [vEvent firstRecurrenceStartDate]; + firstStartDate = [event firstRecurrenceStartDate]; if (firstStartDate) { [firstStartDate setTimeZone: [self ownerTimeZone]]; arp = talloc_zero (memCtx, struct AppointmentRecurrencePattern); _fillAppointmentRecurrencePattern (arp, firstStartDate, - [vEvent durationAsTimeInterval], - [vEvent lastPossibleRecurrenceStartDate], + [event durationAsTimeInterval], + [event lastPossibleRecurrenceStartDate], rule); sBin = talloc_zero (memCtx, struct SBinary_short); bin = set_AppointmentRecurrencePattern (sBin, arp); @@ -184,146 +200,182 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, return sBin; } -- (enum MAPISTATUS) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag +/* getters */ +- (int) getPrIconIndex: (void **) data // TODO +{ + 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 +{ + *data = talloc_strdup(memCtx, "IPM.Appointment"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrStartDate: (void **) data +{ + 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 +{ + return [self getPrStartDate: data]; +} + +- (int) getPidLidCommonStart: (void **) data +{ + return [self getPrStartDate: data]; +} + +- (int) getPrEndDate: (void **) data +{ + 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 +{ + return [self getPrEndDate: data]; +} + +- (int) getPidLidCommonEnd: (void **) data +{ + return [self getPrEndDate: data]; +} + +- (int) getPidLidAppointmentDuration: (void **) data { NSTimeInterval timeValue; - id event; - uint32_t longValue; - NSCalendarDate *dateValue; - int rc; - rc = MAPI_E_SUCCESS; - switch ((uint32_t) 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 + timeValue = [[event endDate] timeIntervalSinceDate: [event startDate]]; + *data = MAPILongValue (memCtx, (uint32_t) (timeValue / 60)); - event = [sogoObject component: NO secure: NO]; - longValue = 0x0400; - if ([event isRecurrent]) - longValue |= 0x0001; - if ([[event attendees] count] > 0) - longValue |= 0x0002; + return MAPISTORE_SUCCESS; +} - *data = MAPILongValue (memCtx, longValue); - break; - case PR_MESSAGE_CLASS_UNICODE: - *data = talloc_strdup(memCtx, "IPM.Appointment"); - break; - case PR_START_DATE: - case PidLidAppointmentStartWhole: - case PidLidCommonStart: - event = [sogoObject component: NO secure: NO]; - if ([event isRecurrent]) - dateValue = [event firstRecurrenceStartDate]; - else - dateValue = [event startDate]; - [dateValue setTimeZone: utcTZ]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - break; - case PR_END_DATE: - case PidLidAppointmentEndWhole: - case PidLidCommonEnd: - 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]; - break; - case PidLidAppointmentDuration: - event = [sogoObject component: NO secure: NO]; - timeValue = [[event endDate] timeIntervalSinceDate: [event startDate]]; - *data = MAPILongValue (memCtx, (uint32_t) (timeValue / 60)); - break; - case PidLidAppointmentSubType: - event = [sogoObject component: NO secure: NO]; - *data = MAPIBoolValue (memCtx, [event isAllDay]); - break; - case PidLidBusyStatus: // TODO - *data = MAPILongValue (memCtx, 0x02); - break; +- (int) getPidLidAppointmentSubType: (void **) data +{ + *data = MAPIBoolValue (memCtx, [event isAllDay]); - // case 0x82410003: // TODO - // *data = MAPILongValue (memCtx, 0); - // break; - case PR_SUBJECT_UNICODE: // SUMMARY - event = [sogoObject component: NO secure: NO]; - *data = [[event summary] asUnicodeInMemCtx: memCtx]; - break; - case PidLidLocation: // LOCATION - event = [sogoObject component: NO secure: NO]; - *data = [[event location] asUnicodeInMemCtx: memCtx]; - break; - case PidLidPrivate: // private (bool), should depend on CLASS and permissions - *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 = [sogoObject component: NO secure: NO]; - *data = [[event created] asFileTimeInMemCtx: memCtx]; - break; + return MAPISTORE_SUCCESS; +} - case PR_IMPORTANCE: - { - unsigned int v; +- (int) getPidLidBusyStatus: (void **) data // TODO +{ + *data = MAPILongValue (memCtx, 0x02); - event = [sogoObject component: NO secure: NO]; + return MAPISTORE_SUCCESS; +} - if ([[event priority] isEqualToString: @"9"]) - v = 0x0; - else if ([[event priority] isEqualToString: @"1"]) - v = 0x2; - else - v = 0x1; +- (int) getPrSubject: (void **) data // SUMMARY +{ + *data = [[event summary] asUnicodeInMemCtx: memCtx]; - *data = MAPILongValue (memCtx, v); - } - break; + return MAPISTORE_SUCCESS; +} +- (int) getPidLidLocation: (void **) data // LOCATION +{ + *data = [[event location] asUnicodeInMemCtx: memCtx]; - /* Recurrence */ - case PidLidIsRecurring: - case PidLidRecurring: - event = [sogoObject component: NO secure: NO]; - *data = MAPIBoolValue (memCtx, [event isRecurrent]); - break; - case PidLidAppointmentRecur: - event = [sogoObject component: NO secure: NO]; - if ([event isRecurrent]) - *data = [self _computeAppointmentRecur]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - break; + return MAPISTORE_SUCCESS; +} - // 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 getProperty: data - withTag: propTag]; - } +- (int) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions +{ + return [self getNo: data]; +} - // #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 */ +- (int) getPrSensitivity: (void **) data // not implemented, depends on CLASS +{ + // normal = 0, personal?? = 1, private = 2, confidential = 3 + return [self getLongZero: data]; +} + +- (int) getPrCreationTime: (void **) data +{ + *data = [[event created] asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrImportance: (void **) data +{ + 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 +{ + *data = MAPIBoolValue (memCtx, [event isRecurrent]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidRecurring: (void **) data +{ + *data = MAPIBoolValue (memCtx, [event isRecurrent]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidAppointmentRecur: (void **) data +{ + int rc = MAPISTORE_SUCCESS; + + if ([event isRecurrent]) + *data = [self _computeAppointmentRecur]; + else + rc = MAPISTORE_ERR_NOT_FOUND; return rc; } @@ -333,12 +385,10 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, NSString *name, *email; NSArray *attendees; iCalPerson *person; - id event; struct SRowSet *recipients; int count, max; [super openMessage: msg]; - event = [sogoObject component: NO secure: NO]; attendees = [event attendees]; max = [attendees count]; @@ -382,11 +432,11 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, { WOContext *woContext; iCalCalendar *vCalendar; - iCalEvent *vEvent; iCalDateTime *start, *end; iCalTimeZone *tz; NSCalendarDate *now; NSString *content, *tzName; + iCalEvent *newEvent; id value; [self logWithFormat: @"-save, event props:"]; @@ -395,25 +445,29 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, content = [sogoObject contentAsString]; if (![content length]) { - vEvent = [sogoObject component: YES secure: NO]; - vCalendar = [vEvent parent]; + newEvent = [sogoObject component: YES secure: NO]; + if (newEvent != event) + ASSIGN (event, newEvent); + vCalendar = [event parent]; [vCalendar setProdID: @"-//Inverse inc.//OpenChange+SOGo//EN"]; content = [vCalendar versitString]; } vCalendar = [iCalCalendar parseSingleFromSource: content]; - vEvent = [[vCalendar events] objectAtIndex: 0]; + newEvent = [[vCalendar events] objectAtIndex: 0]; + if (newEvent != event) + ASSIGN (event, newEvent); // summary value = [newProperties objectForKey: MAPIPropertyKey (PR_NORMALIZED_SUBJECT_UNICODE)]; if (value) - [vEvent setSummary: value]; + [event setSummary: value]; // Location value = [newProperties objectForKey: MAPIPropertyKey (PidLidLocation)]; if (value) - [vEvent setLocation: value]; + [event setLocation: value]; tzName = [[self ownerTimeZone] name]; tz = [iCalTimeZone timeZoneForName: tzName]; @@ -425,7 +479,7 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, value = [newProperties objectForKey: MAPIPropertyKey (PidLidAppointmentStartWhole)]; if (value) { - start = (iCalDateTime *) [vEvent uniqueChildWithTag: @"dtstart"]; + start = (iCalDateTime *) [event uniqueChildWithTag: @"dtstart"]; [start setTimeZone: tz]; [start setDateTime: value]; } @@ -436,7 +490,7 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, value = [newProperties objectForKey: MAPIPropertyKey (PidLidAppointmentEndWhole)]; if (value) { - end = (iCalDateTime *) [vEvent uniqueChildWithTag: @"dtend"]; + end = (iCalDateTime *) [event uniqueChildWithTag: @"dtend"]; [end setTimeZone: tz]; [end setDateTime: value]; } @@ -444,9 +498,9 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, now = [NSCalendarDate date]; if ([sogoObject isNew]) { - [vEvent setCreated: now]; + [event setCreated: now]; } - [vEvent setTimeStampAsDate: now]; + [event setTimeStampAsDate: now]; // Organizer and attendees value = [newProperties objectForKey: @"recipients"]; @@ -463,7 +517,7 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, person = [iCalPerson new]; [person setCn: [dict objectForKey: @"fullName"]]; [person setEmail: [dict objectForKey: @"email"]]; - [vEvent setOrganizer: person]; + [event setOrganizer: person]; [person release]; recipients = [value objectForKey: @"to"]; @@ -480,8 +534,8 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, [person setRole: @"REQ-PARTICIPANT"]; // FIXME: We must NOT always rely on this - if (![vEvent isAttendee: [person rfc822Email]]) - [vEvent addToAttendees: person]; + if (![event isAttendee: [person rfc822Email]]) + [event addToAttendees: person]; [person release]; } @@ -492,11 +546,10 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)]; if (value) [self _setupRecurrenceInCalendar: vCalendar - withMasterEvent: vEvent fromData: value]; // [sogoObject saveContentString: [vCalendar versitString]]; - [sogoObject saveComponent: vEvent]; + [sogoObject saveComponent: event]; } /* TODO: those are stubs meant to prevent OpenChange from crashing when a diff --git a/OpenChange/MAPIStoreContactsMessage.m b/OpenChange/MAPIStoreContactsMessage.m index 013fc2ae4..ddeca15c1 100644 --- a/OpenChange/MAPIStoreContactsMessage.m +++ b/OpenChange/MAPIStoreContactsMessage.m @@ -29,6 +29,7 @@ #import #import +#import "MAPIStorePropertySelectors.h" #import "MAPIStoreTypes.h" #import "NSArray+MAPIStore.h" #import "NSCalendarDate+MAPIStore.h" @@ -46,461 +47,466 @@ @implementation MAPIStoreContactsMessage -- (CardElement *) _element: (NSString *) elementTag - ofType: (NSString *) aType - excluding: (NSString *) aTypeToExclude - inCard: (NGVCard *) card +- (int) getPrIconIndex: (void **) data // TODO +{ + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ + *data = MAPILongValue (memCtx, 0x00000200); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageClass: (void **) data +{ + *data = talloc_strdup (memCtx, "IPM.Contact"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrOabName: (void **) data +{ + *data = talloc_strdup (memCtx, "PR_OAB_NAME_UNICODE"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrOabLangid: (void **) data +{ + /* see http://msdn.microsoft.com/en-us/goglobal/bb895996.asxp */ + /* English US */ + *data = MAPILongValue (memCtx, 0x0409); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrTitle: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] title]; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrCompanyName: (void **) data +{ + NSArray *values; + NSString *stringValue; + + values = [[sogoObject vCard] org]; + stringValue = nil; + + if ([values count] > 0) + stringValue = [values objectAtIndex: 0]; + else + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrDepartmentName: (void **) data +{ + NSArray *values; + NSString *stringValue; + + values = [[sogoObject vCard] org]; + stringValue = nil; + + if ([values count] > 1) + stringValue = [values objectAtIndex: 1]; + else + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSendInternetEncoding: (void **) data +{ + *data = MAPILongValue (memCtx, 0x00065001); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSubject: (void **) data +{ + return [self getPrDisplayName: data]; +} + +- (int) getPidLidFileUnder: (void **) data +{ + return [self getPrDisplayName: data]; +} + +- (int) getPidLidFileUnderId: (void **) data +{ + *data = MAPILongValue (memCtx, 0xffffffff); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidEmail1DisplayName: (void **) data +{ + NGVCard *vCard; + NSString *fn, *email; + + vCard = [sogoObject vCard]; + fn = [vCard fn]; + email = [vCard preferredEMail]; + *data = [[NSString stringWithFormat: @"%@ <%@>", fn, email] + asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidEmail1OriginalDisplayName: (void **) data +{ + return [self getPidLidEmail1DisplayName: data]; +} + +- (int) getPidLidEmail1EmailAddress: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] preferredEMail]; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrAccount: (void **) data +{ + return [self getPidLidEmail1EmailAddress: data]; +} + +- (int) getPrContactEmailAddresses: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] preferredEMail]; + if (!stringValue) + stringValue = @""; + *data = [[NSArray arrayWithObject: stringValue] + asArrayOfUnicodeStringsInCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrEmsAbTargetAddress: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] preferredEMail]; + *data = [[NSString stringWithFormat: @"SMTP:%@", stringValue] + asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSearchKey: (void **) data // TODO +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] preferredEMail]; + *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] + asBinaryInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMailPermission: (void **) data +{ + return [self getYes: data]; +} + +- (int) getPidLidEmail2EmailAddress: (void **) data +{ + NSMutableArray *emails; + NSString *email, *stringValue; + NGVCard *card; + NSUInteger count, max; + + emails = [NSMutableArray array]; + stringValue = nil; + + card = [sogoObject vCard]; + [emails addObjectsFromArray: [card childrenWithTag: @"email"]]; + [emails removeObjectsInArray: [card childrenWithTag: @"email" + andAttribute: @"type" + havingValue: @"pref"]]; + + max = [emails count]; + for (count = 0; !stringValue && count < max; count++) + { + email = [[emails objectAtIndex: count] value: 0]; + + if ([email caseInsensitiveCompare: [card preferredEMail]] != NSOrderedSame) + stringValue = email; + } + + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidEmail2OriginalDisplayName: (void **) data // Other email +{ + return [self getPidLidEmail2EmailAddress: data]; +} + +- (int) getPrBody: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] note]; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) _getElement: (NSString *) elementTag + ofType: (NSString *) aType + excluding: (NSString *) aTypeToExclude + atPos: (NSUInteger) pos + inData: (void **) data { NSArray *elements; - CardElement *ce, *found; + CardElement *ce; NSUInteger count, max; + NGVCard *vCard; + NSString *stringValue; - found = nil; + stringValue = nil; - elements = [[card childrenWithTag: elementTag] + vCard = [sogoObject vCard]; + elements = [[vCard childrenWithTag: elementTag] cardElementsWithAttribute: @"type" havingValue: aType]; max = [elements count]; - for (count = 0; !found && count < max; count++) + for (count = 0; !stringValue && count < max; count++) { ce = [elements objectAtIndex: count]; if (!aTypeToExclude || ![ce hasAttribute: @"type" havingValue: aTypeToExclude]) - found = ce; + stringValue = [ce value: pos]; } - return found; + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; } -- (enum MAPISTATUS) getProperty: (void **) data - withTag: (enum MAPITAGS) proptag +- (int) getPrOfficeTelephoneNumber: (void **) data { - NSString *stringValue, *stringValue2; + return [self _getElement: @"tel" ofType: @"work" excluding: @"fax" + atPos: 0 inData: data]; +} + +- (int) getPrHomeTelephoneNumber: (void **) data +{ + return [self _getElement: @"tel" ofType: @"home" excluding: @"fax" + atPos: 0 inData: data]; +} + +- (int) getPrMobileTelephoneNumber: (void **) data +{ + return [self _getElement: @"tel" ofType: @"cell" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPrPrimaryTelephoneNumber: (void **) data +{ + return [self _getElement: @"tel" ofType: @"pref" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPrBusinessHomePage: (void **) data +{ + return [self _getElement: @"url" ofType: @"work" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPrPersonalHomePage: (void **) data +{ + return [self _getElement: @"url" ofType: @"home" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPidLidEmail1AddressType: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPidLidEmail2AddressType: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPidLidEmail3AddressType: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPidLidInstantMessagingAddress: (void **) data +{ + NSString *stringValue; + + stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-aim"] + value: 0]; + if (!stringValue) + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidPostalAddressId: (void **) data +{ + NSArray *elements; CardElement *element; - uint32_t longValue; + uint32_t longValue = 0; NGVCard *vCard; - enum MAPISTATUS rc; - rc = MAPISTORE_SUCCESS; - switch ((uint32_t) proptag) + vCard = [sogoObject vCard]; + elements = [[vCard childrenWithTag: @"adr"] + cardElementsWithAttribute: @"type" + havingValue: @"pref"]; + if ([elements count] > 0) { - case PR_ICON_INDEX: // TODO - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - *data = MAPILongValue (memCtx, 0x00000200); - break; - case PR_MESSAGE_CLASS_UNICODE: - *data = talloc_strdup (memCtx, "IPM.Contact"); - 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; - case PR_OAB_NAME_UNICODE: - *data = talloc_strdup (memCtx, "PR_OAB_NAME_UNICODE"); - break; - case PR_OAB_LANGID: - /* see http://msdn.microsoft.com/en-us/goglobal/bb895996.asxp */ - /* English US */ - *data = MAPILongValue (memCtx, 0x0409); - break; - - case PR_TITLE_UNICODE: - stringValue = [[sogoObject vCard] title]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_COMPANY_NAME_UNICODE: - case PR_DEPARTMENT_NAME_UNICODE: - { - NSArray *values; - - values = [[sogoObject vCard] org]; - stringValue = nil; - - if (proptag == PR_COMPANY_NAME_UNICODE && [values count] > 0) - stringValue = [values objectAtIndex: 0]; - else if (proptag == PR_DEPARTMENT_NAME_UNICODE && [values count] > 1) - stringValue = [values objectAtIndex: 1]; - - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - } - break; - - case PR_SEND_INTERNET_ENCODING: - *data = MAPILongValue (memCtx, 0x00065001); - break; - - case PR_SUBJECT_UNICODE: - case PR_DISPLAY_NAME_UNICODE: // Full Name - case PidLidFileUnder: // contact block title name - rc = [super getProperty: data - withTag: PR_DISPLAY_NAME_UNICODE]; - break; - case PidLidFileUnderId: - *data = MAPILongValue (memCtx, 0xffffffff); - break; - - case PidLidEmail1OriginalDisplayName: - case PidLidEmail1DisplayName: - vCard = [sogoObject vCard]; - stringValue = [vCard fn]; - stringValue2 = [vCard preferredEMail]; - *data = [[NSString stringWithFormat: @"%@ <%@>", - stringValue, stringValue2] - asUnicodeInMemCtx: memCtx]; - break; - - case PidLidEmail1EmailAddress: - case PR_ACCOUNT_UNICODE: - stringValue = [[sogoObject vCard] preferredEMail]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_CONTACT_EMAIL_ADDRESSES_UNICODE: - stringValue = [[sogoObject vCard] preferredEMail]; - if (!stringValue) - stringValue = @""; - *data = [[NSArray arrayWithObject: stringValue] - asArrayOfUnicodeStringsInCtx: memCtx]; - break; - - case PR_EMS_AB_TARGET_ADDRESS_UNICODE: - stringValue = [[sogoObject vCard] preferredEMail]; - *data = [[NSString stringWithFormat: @"SMTP:%@", stringValue] - asUnicodeInMemCtx: memCtx]; - break; - - case PR_SEARCH_KEY: // TODO - stringValue = [[sogoObject vCard] preferredEMail]; - *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] - asBinaryInMemCtx: memCtx]; - break; - - case PR_MAIL_PERMISSION: - *data = MAPIBoolValue (memCtx, YES); - break; - - // - // TODO - same logic as -secondaryEmail in UI/Contacts/UIxContactView.m - // We should eventually merge that in order to not duplicate the code. - // We should also eventually handle PidLidEmail3OriginalDisplayName in - // SOGo, Thunderbird, etc. - // - case PidLidEmail2EmailAddress: - case PidLidEmail2OriginalDisplayName: // Other email - { - NSMutableArray *emails; - NSString *email; - NGVCard *card; - - emails = [NSMutableArray array]; - stringValue = nil; - - card = [sogoObject vCard]; - [emails addObjectsFromArray: [card childrenWithTag: @"email"]]; - [emails removeObjectsInArray: [card childrenWithTag: @"email" - andAttribute: @"type" - havingValue: @"pref"]]; - - if ([emails count] > 0) - { - int i; - - for (i = 0; i < [emails count]; i++) - { - email = [[emails objectAtIndex: i] value: 0]; - - if ([email caseInsensitiveCompare: [card preferredEMail]] != NSOrderedSame) - { - stringValue = email; - break; - } - } - } - - if (!stringValue) - stringValue = @""; - - *data = [stringValue asUnicodeInMemCtx: memCtx]; - } - break; - - // FIXME: this property does NOT work - case PR_BODY_UNICODE: - stringValue = [[sogoObject vCard] note]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_OFFICE_TELEPHONE_NUMBER_UNICODE: - element = [self _element: @"tel" ofType: @"work" - excluding: @"fax" - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_HOME_TELEPHONE_NUMBER_UNICODE: - element = [self _element: @"tel" ofType: @"home" - excluding: @"fax" - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_MOBILE_TELEPHONE_NUMBER_UNICODE: - element = [self _element: @"tel" ofType: @"cell" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_PRIMARY_TELEPHONE_NUMBER_UNICODE: - element = [self _element: @"tel" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_BUSINESS_HOME_PAGE_UNICODE: - case PR_PERSONAL_HOME_PAGE_UNICODE: - { - NSString *type; - - type = (proptag == PR_BUSINESS_HOME_PAGE_UNICODE ? @"work" : @"home"); - element = [self _element: @"url" ofType: type - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - } - break; - - case PidLidEmail1AddressType: - case PidLidEmail2AddressType: - case PidLidEmail3AddressType: - *data = [@"SMTP" asUnicodeInMemCtx: memCtx]; - break; - - case PidLidInstantMessagingAddress: - stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-aim"] value: 0]; - - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - // - // We don't handle 0x00000003 - The Other Address is the mailing address. - // See: http://msdn.microsoft.com/en-us/library/cc815430.aspx - // - case PidLidPostalAddressId: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; + element = [elements objectAtIndex: 0]; if ([element hasAttribute: @"type" - havingValue: @"home"]) - longValue = 1; // The Home Address is the mailing address. + havingValue: @"home"]) + longValue = 1; // The Home Address is the mailing address. else if ([element hasAttribute: @"type" - havingValue: @"work"]) - longValue = 2; // The Work Address is the mailing address. - else - longValue = 0; // No address is selected as the mailing address. - *data = MAPILongValue (memCtx, longValue); - break; - - /* preferred address */ - case PR_POSTAL_ADDRESS_UNICODE: - element = [self _element: @"label" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_POST_OFFICE_BOX_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_STREET_ADDRESS_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 2]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_LOCALITY_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 3]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_STATE_OR_PROVINCE_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 4]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_POSTAL_CODE_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 5]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_COUNTRY_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 6]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - // case PidLidAddressCountryCode: - - case PidLidWorkAddress: - element = [self _element: @"label" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PidLidWorkAddressPostOfficeBox: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PidLidWorkAddressStreet: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 2]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PidLidWorkAddressCity: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 3]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PidLidWorkAddressState: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 4]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PidLidWorkAddressPostalCode: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 5]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PidLidWorkAddressCountry: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 6]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - // PidTagNickname - case PR_NICKNAME_UNICODE: - stringValue = [[sogoObject vCard] nickname]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_BIRTHDAY: - { - NSCalendarDate *dateValue; - - stringValue = [[sogoObject vCard] bday]; - - if (stringValue) - { - dateValue = [NSCalendarDate dateWithString: stringValue - calendarFormat: @"%Y-%m-%d"]; - // FIXME: We add a day, otherwise Outlook 2003 will display at day earlier - dateValue = [dateValue addYear: 0 month: 0 day: 1 hour: 0 minute: 0 second: 0]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - } - break; - - default: - rc = [super getProperty: data withTag: proptag]; + havingValue: @"work"]) + longValue = 2; // The Work Address is the mailing address. } - + *data = MAPILongValue (memCtx, longValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrPostalAddress: (void **) data +{ + return [self _getElement: @"label" ofType: @"pref" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPrPostOfficeBox: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPrStreetAddress: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 2 inData: data]; +} + +- (int) getPrLocality: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 3 inData: data]; +} + +- (int) getPrStateOrProvince: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 4 inData: data]; +} + +- (int) getPrPostalCode: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 5 inData: data]; +} + +- (int) getPrCountry: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 6 inData: data]; +} + +- (int) getPidLidWorkAddress: (void **) data +{ + return [self _getElement: @"label" ofType: @"work" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPidLidWorkAddressPostOfficeBox: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPidLidWorkAddressStreet: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 2 inData: data]; +} + +- (int) getPidLidWorkAddressCity: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 3 inData: data]; +} + +- (int) getPidLidWorkAddressState: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 4 inData: data]; +} + +- (int) getPidLidWorkAddressPostalCode: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 5 inData: data]; +} + +- (int) getPidLidWorkAddressCountry: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 6 inData: data]; +} + +- (int) getPrNickname: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] nickname]; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrBirthday: (void **) data +{ + NSCalendarDate *dateValue; + NSString *stringValue; + int rc = MAPISTORE_SUCCESS; + + stringValue = [[sogoObject vCard] bday]; + if (stringValue) + { + dateValue = [NSCalendarDate dateWithString: stringValue + calendarFormat: @"%Y-%m-%d"]; + // FIXME: We add a day, otherwise Outlook 2003 will display at day earlier + dateValue = [dateValue addYear: 0 month: 0 day: 1 hour: 0 minute: 0 second: 0]; + *data = [dateValue asFileTimeInMemCtx: memCtx]; + } + else + rc = MAPISTORE_ERR_NOT_FOUND; + return rc; } diff --git a/OpenChange/MAPIStoreFSMessage.m b/OpenChange/MAPIStoreFSMessage.m index 06ee5ac77..441cf9002 100644 --- a/OpenChange/MAPIStoreFSMessage.m +++ b/OpenChange/MAPIStoreFSMessage.m @@ -35,7 +35,7 @@ { id value; enum MAPISTATUS rc; - + value = [[sogoObject properties] objectForKey: MAPIPropertyKey (propTag)]; if (value) rc = [value getMAPIValue: data forTag: propTag inMemCtx: memCtx]; diff --git a/OpenChange/MAPIStoreMailMessage.m b/OpenChange/MAPIStoreMailMessage.m index 67fb9ea23..8d89d9941 100644 --- a/OpenChange/MAPIStoreMailMessage.m +++ b/OpenChange/MAPIStoreMailMessage.m @@ -35,6 +35,7 @@ #import "NSString+MAPIStore.h" #import "MAPIStoreContext.h" #import "MAPIStoreFolder.h" +#import "MAPIStoreMailFolder.h" #import "MAPIStoreTypes.h" #import "MAPIStoreMailAttachment.h" @@ -47,7 +48,7 @@ #include #include -static Class NSExceptionK; +static Class NSExceptionK, MAPIStoreSentItemsFolderK, MAPIStoreDraftsFolderK; @interface NSString (MAPIStoreMIME) @@ -81,6 +82,8 @@ static Class NSExceptionK; + (void) initialize { NSExceptionK = [NSException class]; + MAPIStoreSentItemsFolderK = [MAPIStoreSentItemsFolder class]; + MAPIStoreDraftsFolderK = [MAPIStoreDraftsFolder class]; } - (MAPIStoreAttachmentTable *) attachmentTable @@ -88,465 +91,602 @@ static Class NSExceptionK; return [MAPIStoreAttachmentTable tableForContainer: self]; } -- (enum MAPISTATUS) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag +- (int) getPrIconIndex: (void **) data { - NSString *subject, *stringValue; - NSInteger colIdx; - uint32_t intValue; - enum MAPISTATUS rc; + uint32_t longValue; - rc = MAPISTORE_SUCCESS; - switch ((uint32_t) propTag) + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ + if ([sogoObject isNewMail]) + longValue = 0xffffffff; + else if ([sogoObject replied]) + longValue = 0x105; + else if ([sogoObject forwarded]) + longValue = 0x106; + else if ([sogoObject read]) + longValue = 0x100; + else + longValue = 0x101; + *data = MAPILongValue (memCtx, longValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidImapDeleted: (void **) data +{ + uint32_t longValue; + + if ([sogoObject deleted]) + longValue = 1; + else + longValue = 0; + *data = MAPILongValue (memCtx, longValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSubject: (void **) data +{ + NSString *stringValue; + + stringValue = [sogoObject decodedSubject]; + if (!stringValue) + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSubjectPrefix: (void **) data +{ + NSString *subject; + NSUInteger colIdx; + NSString *stringValue; + + subject = [sogoObject decodedSubject]; + colIdx = [subject rangeOfString: @":"].location; + if (colIdx != NSNotFound && colIdx < 4) + stringValue = [NSString stringWithFormat: @"%@: ", + [subject substringToIndex: colIdx]]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrNormalizedSubject: (void **) data +{ + NSString *subject; + NSUInteger colIdx; + NSString *stringValue; + + subject = [sogoObject decodedSubject]; + colIdx = [subject rangeOfString: @":"].location; + if (colIdx != NSNotFound && colIdx < 4) + stringValue = [[subject substringFromIndex: colIdx + 1] + stringByTrimmingLeadSpaces]; + else + stringValue = subject; + if (!stringValue) + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageClass: (void **) data +{ + *data = talloc_strdup (memCtx, "IPM.Note"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrReplyRequested: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPrResponseRequested: (void **) data // TODO +{ + *data = MAPIBoolValue (memCtx, NO); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrCreationTime: (void **) data // DOUBT +{ + *data = [[sogoObject date] asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrLastModificationTime: (void **) data // DOUBT +{ + return [self getPrCreationTime: data]; +} + +- (int) getPrLatestDeliveryTime: (void **) data // DOUBT +{ + return [self getPrCreationTime: data]; +} + +- (int) getPrOriginalSubmitTime: (void **) data +{ + return [self getPrCreationTime: data]; +} + +- (int) getPrClientSubmitTime: (void **) data +{ + return [self getPrCreationTime: data]; +} + +- (int) getPrMessageDeliveryTime: (void **) data +{ + return [self getPrCreationTime: data]; +} + +- (int) getPrMessageFlags: (void **) data // TODO +{ + NSDictionary *coreInfos; + NSArray *flags; + unsigned int v = 0; + + coreInfos = [sogoObject fetchCoreInfos]; + flags = [coreInfos objectForKey: @"flags"]; + + if ([container isKindOfClass: MAPIStoreSentItemsFolderK] + || [container isKindOfClass: MAPIStoreDraftsFolderK]) + v |= MSGFLAG_FROMME; + if ([flags containsObject: @"seen"]) + v |= MSGFLAG_READ; + if ([[self childKeysMatchingQualifier: nil + andSortOrderings: nil] count] > 0) + v |= MSGFLAG_HASATTACH; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrFlagStatus: (void **) data +{ + NSDictionary *coreInfos; + NSArray *flags; + unsigned int v; + + coreInfos = [sogoObject fetchCoreInfos]; + + flags = [coreInfos objectForKey: @"flags"]; + if ([flags containsObject: @"flagged"]) + v = 2; + else + v = 0; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrFollowupIcon: (void **) data +{ + NSDictionary *coreInfos; + NSArray *flags; + unsigned int v; + + coreInfos = [sogoObject fetchCoreInfos]; + + flags = [coreInfos objectForKey: @"flags"]; + if ([flags containsObject: @"flagged"]) + v = 6; + else + v = 0; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSensitivity: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getProriginalSensitivity: (void **) data // TODO +{ + return [self getPrSensitivity: data]; +} + +- (int) getPrExpiryTime: (void **) data // TODO +{ + *data = [[NSCalendarDate date] asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +// - (int) getPrReplyTime: (void **) data // TODO +// { +// *data = [[NSCalendarDate date] asFileTimeInMemCtx: memCtx]; + +// return MAPISTORE_SUCCESS; +// } + +- (int) getPrSentRepresentingAddrtype: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPrRcvdRepresentingAddrtype: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPrReceivedByAddrtype: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPrSenderAddrtype: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPrSenderEmailAddress: (void **) data +{ + NSString *stringValue; + + stringValue = [sogoObject from]; + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSenderName: (void **) data +{ + return [self getPrSenderEmailAddress: data]; +} + +- (int) getPrOriginalAuthorName: (void **) data +{ + return [self getPrSenderEmailAddress: data]; +} + +- (int) getPrSentRepresentingEmailAddress: (void **) data +{ + return [self getPrSenderEmailAddress: data]; +} + +- (int) getPrSentRepresentingName: (void **) data +{ + return [self getPrSenderEmailAddress: data]; +} + +- (int) getPrReceivedByEmailAddress: (void **) data +{ + NSString *stringValue; + + stringValue = [sogoObject to]; + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrReceivedByName: (void **) data +{ + return [self getPrReceivedByEmailAddress: data]; +} + +- (int) getPrRcvdRepresentingName: (void **) data +{ + return [self getPrReceivedByEmailAddress: data]; +} + +- (int) getPrRcvdRepresentingEmailAddress: (void **) data +{ + return [self getPrReceivedByEmailAddress: data]; +} + +- (int) getPrDisplayTo: (void **) data +{ + return [self getPrReceivedByEmailAddress: data]; +} + +- (int) getPrOriginalDisplayTo: (void **) data +{ + return [self getPrDisplayTo: data]; +} + +- (int) getPrDisplayCc: (void **) data +{ + NSString *stringValue; + + stringValue = [sogoObject cc]; + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrOriginalDisplayCc: (void **) data +{ + return [self getPrDisplayCc: data]; +} + +- (int) getPrDisplayBcc: (void **) data +{ + return [self getEmptyString: data]; +} + +- (int) getPrOriginalDisplayBcc: (void **) data +{ + return [self getPrDisplayBcc: data]; +} + +- (int) getPidNameContentType: (void **) data +{ + *data = [@"message/rfc822" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrImportance: (void **) data +{ + uint32_t v; + NSString *s; + + s = [[sogoObject mailHeaders] objectForKey: @"x-priority"]; + v = 0x1; + + if ([s hasPrefix: @"1"]) v = 0x2; + else if ([s hasPrefix: @"2"]) v = 0x2; + else if ([s hasPrefix: @"4"]) v = 0x0; + else if ([s hasPrefix: @"5"]) v = 0x0; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrInternetCpid: (void **) data +{ + /* ref: + http://msdn.microsoft.com/en-us/library/dd317756%28v=vs.85%29.aspx + + minimal list that should be handled: + us-ascii: 20127 + iso-8859-1: 28591 + iso-8859-15: 28605 + utf-8: 65001 */ + *data = MAPILongValue(memCtx, 65001); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrBody: (void **) data +{ + NSMutableArray *keys; + id result; + NSData *content; + NSDictionary *partHeaderData; + NSString *partKey, *encoding, *charset, *stringValue; + int rc = MAPISTORE_SUCCESS; + + keys = [NSMutableArray array]; + [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] + path: @"" toArray: keys + acceptedTypes: [NSArray arrayWithObject: + @"text/html"]]; + if ([keys count] > 0) { - case PR_ICON_INDEX: - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - if ([sogoObject isNewMail]) - intValue = 0xffffffff; - else if ([sogoObject replied]) - intValue = 0x105; - else if ([sogoObject forwarded]) - intValue = 0x106; - else if ([sogoObject read]) - intValue = 0x100; - else - intValue = 0x101; - *data = MAPILongValue (memCtx, intValue); - break; - case PidLidImapDeleted: - if ([sogoObject deleted]) - intValue = 1; - else - intValue = 0; - *data = MAPILongValue (memCtx, intValue); - break; - case PR_SUBJECT_UNICODE: - stringValue = [sogoObject decodedSubject]; - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_SUBJECT_PREFIX_UNICODE: - subject = [sogoObject decodedSubject]; - colIdx = [subject rangeOfString: @":"].location; - if (colIdx != NSNotFound && colIdx < 4) - stringValue = [NSString stringWithFormat: @"%@: ", - [subject substringToIndex: colIdx]]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_NORMALIZED_SUBJECT_UNICODE: - subject = [sogoObject decodedSubject]; - colIdx = [subject rangeOfString: @":"].location; - if (colIdx != NSNotFound && colIdx < 4) - stringValue = [[subject substringFromIndex: colIdx + 1] - stringByTrimmingLeadSpaces]; - else - stringValue = subject; - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_MESSAGE_CLASS_UNICODE: - case PR_ORIG_MESSAGE_CLASS_UNICODE: - *data = talloc_strdup (memCtx, "IPM.Note"); - break; - // case PidLidRemoteAttachment: // TODO - case PR_REPLY_REQUESTED: // TODO - case PR_RESPONSE_REQUESTED: // TODO - *data = MAPIBoolValue (memCtx, NO); - break; - // case PidLidHeaderItem: - // *data = MAPILongValue (memCtx, 0x00000001); - // break; - // case PidLidRemoteTransferSize: - // rc = [self getChildProperty: data - // forKey: childKey - // withTag: PR_MESSAGE_SIZE]; - // break; - case PR_CREATION_TIME: // DOUBT - case PR_LAST_MODIFICATION_TIME: // DOUBT - case PR_LATEST_DELIVERY_TIME: // DOUBT - case PR_ORIGINAL_SUBMIT_TIME: - case PR_CLIENT_SUBMIT_TIME: - case PR_MESSAGE_DELIVERY_TIME: - // offsetDate = [[sogoObject date] addYear: -1 month: 0 day: 0 - // hour: 0 minute: 0 second: 0]; - // *data = [offsetDate asFileTimeInMemCtx: memCtx]; - *data = [[sogoObject date] asFileTimeInMemCtx: memCtx]; - break; - case PR_MESSAGE_FLAGS: // TODO - { - NSDictionary *coreInfos; - NSArray *flags; - unsigned int v; - - coreInfos = [sogoObject fetchCoreInfos]; - - flags = [coreInfos objectForKey: @"flags"]; - v = MSGFLAG_FROMME; - - if ([flags containsObject: @"seen"]) - v |= MSGFLAG_READ; - - *data = MAPILongValue (memCtx, v); - } - break; - - case PR_FLAG_STATUS: - { - NSDictionary *coreInfos; - NSArray *flags; - unsigned int v; - - coreInfos = [sogoObject fetchCoreInfos]; - - flags = [coreInfos objectForKey: @"flags"]; - if ([flags containsObject: @"flagged"]) - v = 2; - else - v = 0; - - *data = MAPILongValue (memCtx, v); - } - break; - - case PR_FOLLOWUP_ICON: - { - NSDictionary *coreInfos; - NSArray *flags; - unsigned int v; - - coreInfos = [sogoObject fetchCoreInfos]; - - flags = [coreInfos objectForKey: @"flags"]; - if ([flags containsObject: @"flagged"]) - v = 6; - else - v = 0; - - *data = MAPILongValue (memCtx, v); - } - break; - - case PR_SENSITIVITY: // TODO - case PR_ORIGINAL_SENSITIVITY: // TODO - *data = MAPILongValue (memCtx, 0); - break; - - case PR_EXPIRY_TIME: // TODO - case PR_REPLY_TIME: - *data = [[NSCalendarDate date] asFileTimeInMemCtx: memCtx]; - break; - - case PR_SENT_REPRESENTING_ADDRTYPE_UNICODE: - case PR_RCVD_REPRESENTING_ADDRTYPE_UNICODE: - case PR_RECEIVED_BY_ADDRTYPE_UNICODE: - case PR_SENDER_ADDRTYPE_UNICODE: - *data = [@"SMTP" asUnicodeInMemCtx: memCtx]; - break; - case PR_ORIGINAL_AUTHOR_NAME_UNICODE: - case PR_SENDER_NAME_UNICODE: - case PR_SENDER_EMAIL_ADDRESS_UNICODE: - case PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE: - case PR_SENT_REPRESENTING_NAME_UNICODE: - *data = [[sogoObject from] asUnicodeInMemCtx: memCtx]; - break; - - /* TODO: some of the following are supposed to be display names, separated by a semicolumn */ - case PR_RECEIVED_BY_NAME_UNICODE: - case PR_RECEIVED_BY_EMAIL_ADDRESS_UNICODE: - case PR_RCVD_REPRESENTING_NAME_UNICODE: - case PR_RCVD_REPRESENTING_EMAIL_ADDRESS_UNICODE: - case PR_DISPLAY_TO_UNICODE: - case PR_ORIGINAL_DISPLAY_TO_UNICODE: - stringValue = [sogoObject to]; - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_DISPLAY_CC_UNICODE: - case PR_ORIGINAL_DISPLAY_CC_UNICODE: - stringValue = [sogoObject cc]; - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_DISPLAY_BCC_UNICODE: - case PR_ORIGINAL_DISPLAY_BCC_UNICODE: - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PidNameContentType: - *data = [@"message/rfc822" asUnicodeInMemCtx: memCtx]; - break; - - - // - // TODO: Merge with the code in UI/MailerUI/UIxMailListActions.m: -messagePriority - // to avoid the duplication of the logic - // - case PR_IMPORTANCE: - { - unsigned int v; - NSString *s; - - s = [[sogoObject mailHeaders] objectForKey: @"x-priority"]; - v = 0x1; - - - if ([s hasPrefix: @"1"]) v = 0x2; - else if ([s hasPrefix: @"2"]) v = 0x2; - else if ([s hasPrefix: @"4"]) v = 0x0; - else if ([s hasPrefix: @"5"]) v = 0x0; - - *data = MAPILongValue (memCtx, v); - } - break; - - case PR_BODY_UNICODE: - { - NSMutableArray *keys; - - keys = [NSMutableArray array]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys - acceptedTypes: [NSArray arrayWithObject: - @"text/html"]]; - if ([keys count] > 0) - { - *data = NULL; - rc = MAPISTORE_ERR_NOT_FOUND; - } - else - { - [keys removeAllObjects]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys - acceptedTypes: [NSArray arrayWithObject: - @"text/plain"]]; - if ([keys count] > 0) - { - id result; - NSData *content; - NSDictionary *partHeaderData; - NSString *partKey, *encoding, *charset; - - result = [sogoObject fetchParts: [keys objectsForKey: @"key" - notFoundMarker: nil]]; - result = [[result valueForKey: @"RawResponse"] objectForKey: @"fetch"]; - partKey = [[keys objectAtIndex: 0] objectForKey: @"key"]; - content = [[result objectForKey: partKey] objectForKey: @"data"]; - - partHeaderData - = [sogoObject lookupInfoForBodyPart: [partKey _strippedBodyKey]]; - encoding = [partHeaderData objectForKey: @"encoding"]; - charset = [[partHeaderData objectForKey: @"parameterList"] - objectForKey: @"charset"]; - stringValue = [[content bodyDataFromEncoding: encoding] - bodyStringFromCharset: charset]; - - *data = [stringValue asUnicodeInMemCtx: memCtx]; - if (strlen (*data) > 16384) - { - /* TODO: currently a hack to transfer properties as - streams */ - [newProperties setObject: stringValue - forKey: MAPIPropertyKey (propTag)]; - *data = NULL; - rc = MAPI_E_NOT_ENOUGH_MEMORY; - [self logWithFormat: @"PR_BODY data too wide"]; - } - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - } - } - break; - - case PR_INTERNET_CPID: - /* ref: - http://msdn.microsoft.com/en-us/library/dd317756%28v=vs.85%29.aspx - - minimal list that should be handled: - us-ascii: 20127 - iso-8859-1: 28591 - iso-8859-15: 28605 - utf-8: 65001 */ - *data = MAPILongValue(memCtx, 65001); - break; - - case PR_HTML: - { - NSMutableArray *keys; - NSArray *acceptedTypes; - - acceptedTypes = [NSArray arrayWithObject: @"text/html"]; - keys = [NSMutableArray array]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys acceptedTypes: acceptedTypes]; - if ([keys count] > 0) - { - id result; - NSData *content; - NSDictionary *partHeaderData; - NSString *key, *encoding; - char *oldBytes, *newBytes; - NSUInteger c, newC, max, newMax; - - result = [sogoObject fetchParts: [keys objectsForKey: @"key" - notFoundMarker: nil]]; - result = [[result valueForKey: @"RawResponse"] objectForKey: - @"fetch"]; - key = [[keys objectAtIndex: 0] objectForKey: @"key"]; - content = [[result objectForKey: key] objectForKey: @"data"]; - - max = [content length]; - newMax = max; - oldBytes = malloc (max); - newBytes = malloc (max * 2); - [content getBytes: oldBytes]; - newC = 0; - for (c = 0; c < max; c++) - { - if (*(oldBytes + c) == '\n') - { - *(newBytes + newC) = '\r'; - newC++; - newMax++; - } - *(newBytes + newC) = *(oldBytes + c); - newC++; - } - content = [[NSData alloc] initWithBytesNoCopy: newBytes - length: newMax];; - [content autorelease]; - - partHeaderData - = [sogoObject lookupInfoForBodyPart: [key _strippedBodyKey]]; - encoding = [partHeaderData objectForKey: @"encoding"]; - content = [content bodyDataFromEncoding: encoding]; - - if ([content length] > 16384) - { - /* TODO: currently a hack to transfer properties as - streams */ - [newProperties setObject: content - forKey: MAPIPropertyKey (propTag)]; - *data = NULL; - rc = MAPI_E_NOT_ENOUGH_MEMORY; - [self logWithFormat: @"PR_HTML data too wide"]; - } - else - *data = [content asBinaryInMemCtx: memCtx]; - } - else - { - *data = NULL; - rc = MAPISTORE_ERR_NOT_FOUND; - } - } - break; - - /* We don't handle any RTF content. */ - case PR_RTF_COMPRESSED: *data = NULL; rc = MAPISTORE_ERR_NOT_FOUND; - break; - case PR_RTF_IN_SYNC: - *data = MAPIBoolValue (memCtx, NO); - break; - case PR_INTERNET_MESSAGE_ID_UNICODE: - *data = [[sogoObject messageId] asUnicodeInMemCtx: memCtx]; - break; - case PR_READ_RECEIPT_REQUESTED: // TODO - case PR_DELETE_AFTER_SUBMIT: // TODO - *data = MAPIBoolValue (memCtx, NO); - break; - case PidLidPrivate: - *data = MAPIBoolValue (memCtx, NO); - break; - - case PR_MSG_EDITOR_FORMAT: - { - NSMutableArray *keys; - NSArray *acceptedTypes; - uint32_t format; - - 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) - format = EDITOR_FORMAT_PLAINTEXT; - - acceptedTypes = [NSArray arrayWithObject: @"text/html"]; - [keys removeAllObjects]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys - acceptedTypes: acceptedTypes]; - if ([keys count] == 1) - format = EDITOR_FORMAT_HTML; - - *data = MAPILongValue (memCtx, format); - } - break; - - case PidLidReminderSet: // TODO - case PidLidUseTnef: // TODO - *data = MAPIBoolValue (memCtx, NO); - break; - case PidLidRemoteStatus: // TODO - *data = MAPILongValue (memCtx, 0); - break; - // case PidLidSmartNoAttach: // TODO - case PidLidAgingDontAgeMe: // TODO - *data = MAPIBoolValue (memCtx, YES); - break; - -// PidLidFlagRequest -// PidLidBillingInformation -// PidLidMileage -// PidLidCommonEnd -// PidLidCommonStart -// PidLidNonSendableBcc -// PidLidNonSendableCc -// PidLidNonSendtableTo -// PidLidNonSendBccTrackStatus -// PidLidNonSendCcTrackStatus -// PidLidNonSendToTrackStatus -// PidLidReminderDelta -// PidLidReminderFileParameter -// PidLidReminderSignalTime -// PidLidReminderOverride -// PidLidReminderPlaySound -// PidLidReminderTime -// PidLidReminderType -// PidLidSmartNoAttach -// PidLidTaskGlobalId -// PidLidTaskMode -// PidLidVerbResponse -// PidLidVerbStream -// PidLidInternetAccountName -// PidLidInternetAccountStamp -// PidLidContactLinkName -// PidLidContactLinkEntry -// PidLidContactLinkSearchKey -// PidLidSpamOriginalFolder - - default: - rc = [super getProperty: data withTag: propTag]; + } + else + { + [keys removeAllObjects]; + [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] + path: @"" toArray: keys + acceptedTypes: [NSArray arrayWithObject: + @"text/plain"]]; + if ([keys count] > 0) + { + result = [sogoObject fetchParts: [keys objectsForKey: @"key" + notFoundMarker: nil]]; + result = [[result valueForKey: @"RawResponse"] objectForKey: @"fetch"]; + partKey = [[keys objectAtIndex: 0] objectForKey: @"key"]; + content = [[result objectForKey: partKey] objectForKey: @"data"]; + + partHeaderData + = [sogoObject lookupInfoForBodyPart: [partKey _strippedBodyKey]]; + encoding = [partHeaderData objectForKey: @"encoding"]; + charset = [[partHeaderData objectForKey: @"parameterList"] + objectForKey: @"charset"]; + stringValue = [[content bodyDataFromEncoding: encoding] + bodyStringFromCharset: charset]; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + if (strlen (*data) > 16384) + { + /* TODO: currently a hack to transfer properties as + streams */ + [newProperties setObject: stringValue + forKey: MAPIPropertyKey (PR_BODY_UNICODE)]; + *data = NULL; + rc = MAPI_E_NOT_ENOUGH_MEMORY; + [self logWithFormat: @"PR_BODY data too wide"]; + } + } + else + rc = MAPISTORE_ERR_NOT_FOUND; } return rc; } +- (int) getPrHtml: (void **) data +{ + id result; + NSData *content; + NSDictionary *partHeaderData; + NSString *key, *encoding; + char *oldBytes, *newBytes; + NSUInteger c, newC, max, newMax; + NSMutableArray *keys; + NSArray *acceptedTypes; + int rc = MAPISTORE_SUCCESS; + + acceptedTypes = [NSArray arrayWithObject: @"text/html"]; + keys = [NSMutableArray array]; + [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] + path: @"" toArray: keys + acceptedTypes: acceptedTypes]; + if ([keys count] > 0) + { + result = [sogoObject fetchParts: [keys objectsForKey: @"key" + notFoundMarker: nil]]; + result = [[result valueForKey: @"RawResponse"] objectForKey: + @"fetch"]; + key = [[keys objectAtIndex: 0] objectForKey: @"key"]; + content = [[result objectForKey: key] objectForKey: @"data"]; + + max = [content length]; + newMax = max; + oldBytes = malloc (max); + newBytes = malloc (max * 2); + [content getBytes: oldBytes]; + newC = 0; + for (c = 0; c < max; c++) + { + if (*(oldBytes + c) == '\n') + { + *(newBytes + newC) = '\r'; + newC++; + newMax++; + } + *(newBytes + newC) = *(oldBytes + c); + newC++; + } + content = [[NSData alloc] initWithBytesNoCopy: newBytes + length: newMax];; + [content autorelease]; + + partHeaderData + = [sogoObject lookupInfoForBodyPart: [key _strippedBodyKey]]; + encoding = [partHeaderData objectForKey: @"encoding"]; + content = [content bodyDataFromEncoding: encoding]; + + if ([content length] > 16384) + { + /* TODO: currently a hack to transfer properties as + streams */ + [newProperties setObject: content + forKey: MAPIPropertyKey (PR_HTML)]; + *data = NULL; + rc = MAPI_E_NOT_ENOUGH_MEMORY; + [self logWithFormat: @"PR_HTML data too wide"]; + } + else + *data = [content asBinaryInMemCtx: memCtx]; + } + else + { + *data = NULL; + rc = MAPISTORE_ERR_NOT_FOUND; + } + + return rc; +} + +- (int) getPrRtfCompressed: (void **) data +{ + *data = NULL; + + return MAPISTORE_ERR_NOT_FOUND; +} + +- (int) getPrRtfInSync: (void **) data +{ + return [self getNo: data]; +} + +- (int) getPrInternetMessageId: (void **) data +{ + *data = [[sogoObject messageId] asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrReadReceiptRequested: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPrDeleteAfterSubmit: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPidLidPrivate: (void **) data +{ + return [self getNo: data]; +} + +- (int) getPrMsgEditorFormat: (void **) data +{ + NSMutableArray *keys; + NSArray *acceptedTypes; + uint32_t format; + + 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) + format = EDITOR_FORMAT_PLAINTEXT; + + acceptedTypes = [NSArray arrayWithObject: @"text/html"]; + [keys removeAllObjects]; + [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] + path: @"" toArray: keys + acceptedTypes: acceptedTypes]; + if ([keys count] == 1) + format = EDITOR_FORMAT_HTML; + + *data = MAPILongValue (memCtx, format); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidReminderSet: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPidLidUseTnef: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPidLidRemoteStatus: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPidLidAgingDontAgeMe: (void **) data // TODO +{ + return [self getYes: data]; +} + - (void) openMessage: (struct mapistore_message *) msg { struct SRowSet *recipients; diff --git a/OpenChange/MAPIStoreMessage.h b/OpenChange/MAPIStoreMessage.h index 0bed90bbc..73af085ab 100644 --- a/OpenChange/MAPIStoreMessage.h +++ b/OpenChange/MAPIStoreMessage.h @@ -48,6 +48,9 @@ - (void) openMessage: (struct mapistore_message *) msg; +/* helper getters */ +- (int) getSMTPAddrType: (void **) data; + /* subclasses */ - (void) submit; - (void) save; diff --git a/OpenChange/MAPIStoreMessage.m b/OpenChange/MAPIStoreMessage.m index 05953a4a5..dbee2c973 100644 --- a/OpenChange/MAPIStoreMessage.m +++ b/OpenChange/MAPIStoreMessage.m @@ -22,9 +22,11 @@ #import #import +#import #import #import +#import "MAPIStoreContext.h" #import "MAPIStoreTypes.h" #import "NSData+MAPIStore.h" #import "NSString+MAPIStore.h" @@ -127,146 +129,274 @@ msg->properties = properties; } -- (int) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag +/* helper getters */ +- (int) getSMTPAddrType: (void **) data { - int rc; + *data = [@"SMTP" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +/* getters */ +- (int) getPrInstId: (void **) data // TODO: DOUBT +{ + /* we return a unique id based on the key */ + *data = MAPILongLongValue (memCtx, [[sogoObject nameInContainer] hash]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrInstanceNum: (void **) data // TODO: DOUBT +{ + return [self getLongZero: data]; +} + +- (int) getPrRowType: (void **) data // TODO: DOUBT +{ + *data = MAPILongValue (memCtx, TBL_LEAF_ROW); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrDepth: (void **) data // TODO: DOUBT +{ + *data = MAPILongLongValue (memCtx, 0); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrAccess: (void **) data // TODO +{ + *data = MAPILongValue (memCtx, 0x03); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrAccessLevel: (void **) data // TODO +{ + *data = MAPILongValue (memCtx, 0x01); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrViewStyle: (void **) data +{ + return [self getLongZero: data]; +} + +- (int) getPrViewMajorversion: (void **) data +{ + return [self getLongZero: data]; +} + +- (int) getPidLidSideEffects: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPidLidCurrentVersion: (void **) data +{ + *data = MAPILongValue (memCtx, 115608); // Outlook 11.5608 + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidCurrentVersionName: (void **) data +{ + *data = [@"11.0" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidAutoProcessState: (void **) data +{ + *data = MAPILongValue (memCtx, 0x00000000); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidNameContentClass: (void **) data +{ + *data = [@"Sharing" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrFid: (void **) data +{ + *data = MAPILongLongValue (memCtx, [container objectId]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMid: (void **) data +{ + *data = MAPILongLongValue (memCtx, [self objectId]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageLocaleId: (void **) data +{ + *data = MAPILongValue (memCtx, 0x0409); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageFlags: (void **) data // TODO +{ + *data = MAPILongValue (memCtx, MSGFLAG_FROMME | MSGFLAG_READ | MSGFLAG_UNMODIFIED); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageSize: (void **) data // TODO +{ + /* TODO: choose another name in SOGo for that method */ + *data = MAPILongValue (memCtx, [[sogoObject davContentLength] intValue]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMsgStatus: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPrImportance: (void **) data // TODO -> subclass? +{ + *data = MAPILongValue (memCtx, 1); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrPriority: (void **) data // TODO -> subclass? +{ + return [self getLongZero: data]; +} + +- (int) getPrSensitivity: (void **) data // TODO -> subclass in calendar +{ + return [self getLongZero: data]; +} + +// TODO: PR_CHANGE_KEY is a GID based on the ReplGUID +- (int) getPrChangeKey: (void **) data +{ + int rc = MAPISTORE_SUCCESS; NSString *stringValue; NSUInteger length; - rc = MAPI_E_SUCCESS; - switch ((uint32_t) propTag) + stringValue = [sogoObject davEntityTag]; + if (stringValue) { - case PR_INST_ID: // TODO: DOUBT - /* we return a unique id based on the key */ - *data = MAPILongLongValue (memCtx, [[sogoObject nameInContainer] hash]); - break; - case PR_INSTANCE_NUM: // TODO: DOUBT - *data = MAPILongValue (memCtx, 0); - break; - case PR_ROW_TYPE: // TODO: DOUBT - *data = MAPILongValue (memCtx, TBL_LEAF_ROW); - break; - case PR_DEPTH: // TODO: DOUBT - *data = MAPILongLongValue (memCtx, 0); - break; - case PR_ACCESS: // TODO - *data = MAPILongValue (memCtx, 0x03); - break; - case PR_ACCESS_LEVEL: // TODO - *data = MAPILongValue (memCtx, 0x01); - break; - case PR_VIEW_STYLE: - case PR_VIEW_MAJORVERSION: - *data = MAPILongValue (memCtx, 0); - break; - case PidLidSideEffects: // TODO - *data = MAPILongValue (memCtx, 0x00000000); - break; - case PidLidCurrentVersion: - *data = MAPILongValue (memCtx, 115608); // Outlook 11.5608 - break; - case PidLidCurrentVersionName: - *data = [@"11.0" asUnicodeInMemCtx: memCtx]; - break; - case PidLidAutoProcessState: - *data = MAPILongValue (memCtx, 0x00000000); - break; - case PidNameContentClass: - *data = [@"Sharing" asUnicodeInMemCtx: memCtx]; - break; - case PR_FID: - *data = MAPILongLongValue (memCtx, [container objectId]); - break; - case PR_MID: - *data = MAPILongLongValue (memCtx, [self objectId]); - break; - case PR_MESSAGE_LOCALE_ID: - *data = MAPILongValue (memCtx, 0x0409); - break; - case PR_MESSAGE_FLAGS: // TODO - *data = MAPILongValue (memCtx, MSGFLAG_FROMME | MSGFLAG_READ | MSGFLAG_UNMODIFIED); - break; - case PR_MESSAGE_SIZE: // TODO - /* TODO: choose another name in SOGo for that method */ - *data = MAPILongValue (memCtx, [[sogoObject davContentLength] intValue]); - break; - case PR_MSG_STATUS: // TODO - *data = MAPILongValue (memCtx, 0); - break; - case PR_IMPORTANCE: // TODO -> subclass? - *data = MAPILongValue (memCtx, 1); - break; - case PR_PRIORITY: // TODO -> subclass? - *data = MAPILongValue (memCtx, 0); - break; - case PR_SENSITIVITY: // TODO -> subclass in calendar - *data = MAPILongValue (memCtx, 0); - break; - case PR_CHANGE_KEY: - stringValue = [sogoObject davEntityTag]; - if (stringValue) - { - stringValue = @"-1"; - length = [stringValue length]; - if (length < 6) /* guid = 16 bytes */ - { - length += 6; - stringValue = [NSString stringWithFormat: @"000000%@", - stringValue]; - } - if (length > 6) - stringValue = [stringValue substringFromIndex: length - 6]; - stringValue = [NSString stringWithFormat: @"SOGo%@%@%@", - stringValue, stringValue, stringValue]; - *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] - asShortBinaryInMemCtx: memCtx]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - break; - - case PR_ORIGINAL_SUBJECT_UNICODE: - case PR_CONVERSATION_TOPIC_UNICODE: - rc = [self getProperty: data withTag: PR_NORMALIZED_SUBJECT_UNICODE]; - break; - - case PR_SUBJECT_PREFIX_UNICODE: - *data = [@"" asUnicodeInMemCtx: memCtx]; - break; - case PR_NORMALIZED_SUBJECT_UNICODE: - rc = [self getProperty: data withTag: PR_SUBJECT_UNICODE]; - break; - - case PR_DISPLAY_TO_UNICODE: - case PR_DISPLAY_CC_UNICODE: - case PR_DISPLAY_BCC_UNICODE: - case PR_ORIGINAL_DISPLAY_TO_UNICODE: - case PR_ORIGINAL_DISPLAY_CC_UNICODE: - case PR_ORIGINAL_DISPLAY_BCC_UNICODE: - *data = [@"" asUnicodeInMemCtx: memCtx]; - break; - case PR_LAST_MODIFIER_NAME_UNICODE: - *data = [@"openchange" asUnicodeInMemCtx: memCtx]; - break; - - case PR_ORIG_MESSAGE_CLASS_UNICODE: - rc = [self getProperty: data withTag: PR_MESSAGE_CLASS_UNICODE]; - break; - - case PR_HASATTACH: - *data = MAPIBoolValue (memCtx, - [[self childKeysMatchingQualifier: nil - andSortOrderings: nil] count] > 0); - break; - - default: - rc = [super getProperty: data withTag: propTag]; + stringValue = @"-1"; + length = [stringValue length]; + if (length < 6) /* guid = 16 bytes */ + length += 6; + stringValue = [NSString stringWithFormat: @"000000%@", + stringValue]; + if (length > 6) + stringValue = [stringValue substringFromIndex: length - 6]; + stringValue = [NSString stringWithFormat: @"SOGo%@%@%@", + stringValue, stringValue, stringValue]; + *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] + asShortBinaryInMemCtx: memCtx]; } + else + rc = MAPISTORE_ERR_NOT_FOUND; return rc; } +- (int) getPrSubject: (void **) data +{ + [self subclassResponsibility: _cmd]; + + return MAPISTORE_ERR_NOT_FOUND; +} + +- (int) getPrNormalizedSubject: (void **) data +{ + return [self getPrSubject: data]; +} + +- (int) getPrOriginalSubject: (void **) data +{ + return [self getPrNormalizedSubject: data]; +} + +- (int) getPrConversationTopic: (void **) data +{ + return [self getPrNormalizedSubject: data]; +} + +- (int) getPrSubjectPrefix: (void **) data +{ + return [self getEmptyString: data]; +} + +- (int) getPrDisplayTo: (void **) data +{ + return [self getEmptyString: data]; +} + +- (int) getPrDisplayCc: (void **) data +{ + return [self getEmptyString: data]; +} + +- (int) getPrDisplayBcc: (void **) data +{ + return [self getEmptyString: data]; +} + +- (int) getPrOriginalDisplayTo: (void **) data +{ + return [self getPrDisplayTo: data]; +} + +- (int) getPrOriginalDisplayCc: (void **) data +{ + return [self getPrDisplayCc: data]; +} + +- (int) getPrOriginalDisplayBcc: (void **) data +{ + return [self getPrDisplayBcc: data]; +} + +- (int) getPrLastModifierName: (void **) data +{ + NSURL *contextUrl; + + contextUrl = [[self context] url]; + *data = [[contextUrl user] asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageClass: (void **) data +{ + [self subclassResponsibility: _cmd]; + + return MAPISTORE_ERR_NOT_FOUND; +} + +- (int) getPrOrigMessageClass: (void **) data +{ + return [self getPrMessageClass: data]; +} + +- (int) getPrHasattach: (void **) data +{ + *data = MAPIBoolValue (memCtx, + [[self childKeysMatchingQualifier: nil + andSortOrderings: nil] count] > 0); + + return MAPISTORE_SUCCESS; +} + - (void) save { [self subclassResponsibility: _cmd]; diff --git a/OpenChange/MAPIStoreNotesMessage.m b/OpenChange/MAPIStoreNotesMessage.m index 51896f499..bb6821b81 100644 --- a/OpenChange/MAPIStoreNotesMessage.m +++ b/OpenChange/MAPIStoreNotesMessage.m @@ -24,35 +24,27 @@ #import "MAPIStoreNotesMessage.h" +#include + @implementation MAPIStoreNotesMessage -- (enum MAPISTATUS) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag +- (int) getPrIconIndex: (void **) data // TODO { - int rc; + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ + // *longValue = 0x00000300 for blue + // *longValue = 0x00000301 for green + // *longValue = 0x00000302 for pink + // *longValue = 0x00000303 for yellow + // *longValue = 0x00000304 for white + *data = MAPILongValue (memCtx, 0x00000303); + + return MAPISTORE_SUCCESS; +} - rc = MAPI_E_SUCCESS; - switch (propTag) - { - case PR_ICON_INDEX: // TODO - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - // *longValue = 0x00000300 for blue - // *longValue = 0x00000301 for green - // *longValue = 0x00000302 for pink - // *longValue = 0x00000303 for yellow - // *longValue = 0x00000304 for white - *data = MAPILongValue (memCtx, 0x00000303); - break; - - case PR_SUBJECT_UNICODE: - rc = [super getProperty: data - withTag: PR_NORMALIZED_SUBJECT_UNICODE]; - break; - default: - rc = [super getProperty: data withTag: propTag]; - } - - return rc; +- (int) getPrSubject: (void **) data +{ + return [self getProperty: data + withTag: PR_NORMALIZED_SUBJECT_UNICODE]; } @end diff --git a/OpenChange/MAPIStoreObject.h b/OpenChange/MAPIStoreObject.h index 3a9f061ca..7f84ae9bb 100644 --- a/OpenChange/MAPIStoreObject.h +++ b/OpenChange/MAPIStoreObject.h @@ -36,6 +36,8 @@ @interface MAPIStoreObject : NSObject { + const IMP *classGetters; + NSMutableArray *parentContainersBag; MAPIStoreObject *container; id sogoObject; @@ -83,6 +85,12 @@ - (int) getProperty: (void **) data withTag: (enum MAPITAGS) propTag; +/* helper getters */ +- (int) getEmptyString: (void **) data; +- (int) getLongZero: (void **) data; +- (int) getYes: (void **) data; +- (int) getNo: (void **) data; + /* subclasses */ - (id) lookupChild: (NSString *) childKey; - (NSArray *) childKeysMatchingQualifier: (EOQualifier *) qualifier diff --git a/OpenChange/MAPIStoreObject.m b/OpenChange/MAPIStoreObject.m index d06738945..3f4009a36 100644 --- a/OpenChange/MAPIStoreObject.m +++ b/OpenChange/MAPIStoreObject.m @@ -25,6 +25,7 @@ #import #import "MAPIStoreFolder.h" +#import "MAPIStorePropertySelectors.h" #import "MAPIStoreTypes.h" #import "NSData+MAPIStore.h" #import "NSString+MAPIStore.h" @@ -64,6 +65,7 @@ static Class NSExceptionK, MAPIStoreFolderK; { if ((self = [super init])) { + classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa); parentContainersBag = [NSMutableArray new]; container = nil; sogoObject = nil; @@ -190,52 +192,83 @@ static Class NSExceptionK, MAPIStoreFolderK; - (int) getProperty: (void **) data withTag: (enum MAPITAGS) propTag { - NSString *stringValue; - int rc; + MAPIStorePropertyGetter method = NULL; + uint16_t propValue; const char *propName; - - /* TODO: handle unsaved properties */ - - rc = MAPISTORE_SUCCESS; - switch (propTag) + int rc = MAPISTORE_ERR_NOT_FOUND; + + propValue = (propTag & 0xffff0000) >> 16; + method = (MAPIStorePropertyGetter) classGetters[propValue]; + if (method) + rc = method (self, NULL, data); + else { - case PR_DISPLAY_NAME_UNICODE: - *data = [[sogoObject displayName] asUnicodeInMemCtx: memCtx]; - break; - case PR_SEARCH_KEY: // TODO - stringValue = [sogoObject nameInContainer]; - *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] - asBinaryInMemCtx: memCtx]; - break; - case PR_GENERATE_EXCHANGE_VIEWS: // TODO - *data = MAPIBoolValue (memCtx, NO); - break; - - default: propName = get_proptag_name (propTag); if (!propName) - propName = ""; + propName = ""; + *data = NULL; + [self warnWithFormat: - @"unhandled or NULL value: %s (0x%.8x), childKey: %@", - propName, propTag, [sogoObject nameInContainer]]; - // if ((propTag & 0x001F) == 0x001F) - // { - // stringValue = [NSString stringWithFormat: @"fake %s (0x.8x) value", - // propName, propTag]; - // *data = [stringValue asUnicodeInMemCtx: memCtx]; - // rc = MAPISTORE_SUCCESS; - // } - // else - // { - *data = NULL; - rc = MAPISTORE_ERR_NOT_FOUND; - // } - break; + @"unimplemented property: %s (0x%.8x) in class '%@'", + propName, propTag, NSStringFromClass (isa)]; } return rc; } +/* helper getters */ +- (int) getEmptyString: (void **) data +{ + *data = [@"" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getLongZero: (void **) data +{ + *data = MAPILongValue (memCtx, 0); + + return MAPISTORE_SUCCESS; +} + +- (int) getYes: (void **) data +{ + *data = MAPIBoolValue (memCtx, YES); + + return MAPISTORE_SUCCESS; +} + +- (int) getNo: (void **) data +{ + *data = MAPIBoolValue (memCtx, NO); + + return MAPISTORE_SUCCESS; +} + +/* getters */ + - (int) getPrDisplayName: (void **) data +{ + *data = [[sogoObject displayName] asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSearchKey: (void **) data +{ + NSString *stringValue; + + stringValue = [sogoObject nameInContainer]; + *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] + asBinaryInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrGenerateExchangeViews: (void **) data +{ + return [self getNo: data]; +} + /* MAPIStoreProperty protocol */ - (int) getProperties: (struct mapistore_property_data *) data withTags: (enum MAPITAGS *) tags @@ -277,8 +310,6 @@ static Class NSExceptionK, MAPIStoreFolderK; - (NSArray *) childKeysMatchingQualifier: (EOQualifier *) qualifier andSortOrderings: (NSArray *) sortOrderings { - [self subclassResponsibility: _cmd]; - return nil; } diff --git a/OpenChange/MAPIStoreTasksMessage.h b/OpenChange/MAPIStoreTasksMessage.h index 273cde7cb..ad3ddcd40 100644 --- a/OpenChange/MAPIStoreTasksMessage.h +++ b/OpenChange/MAPIStoreTasksMessage.h @@ -25,7 +25,12 @@ #import "MAPIStoreGCSMessage.h" +@class iCalToDo; + @interface MAPIStoreTasksMessage : MAPIStoreGCSMessage +{ + iCalToDo *task; +} @end diff --git a/OpenChange/MAPIStoreTasksMessage.m b/OpenChange/MAPIStoreTasksMessage.m index 581ab5c9b..b21bd5f67 100644 --- a/OpenChange/MAPIStoreTasksMessage.m +++ b/OpenChange/MAPIStoreTasksMessage.m @@ -49,221 +49,212 @@ @implementation MAPIStoreTasksMessage -- (enum MAPISTATUS) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag +- (id) initWithSOGoObject: (id) newSOGoObject + inContainer: (MAPIStoreObject *) newContainer { - NSString *status; - iCalToDo *task; - int32_t statusValue; - NSCalendarDate *dateValue; - int rc; - double doubleValue; - - rc = MAPI_E_SUCCESS; - switch ((uint32_t) propTag) + if ((self = [super initWithSOGoObject: newSOGoObject + inContainer: newContainer])) { - 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 - task = [sogoObject component: NO secure: NO]; - *data = [[task summary] asUnicodeInMemCtx: memCtx]; - break; - - // - // Not to be confused with PR_PRIORITY - // - // IMPORTANCE_LOW = 0x0, IMPORTANCE_NORMAL = 0x1 and IMPORTANCE_HIGH = 0x2 - // - case PR_IMPORTANCE: - { - unsigned int v; - - task = [sogoObject component: NO secure: NO]; - - if ([[task priority] isEqualToString: @"9"]) - v = 0x0; - else if ([[task priority] isEqualToString: @"1"]) - v = 0x2; - else - v = 0x1; - - *data = MAPILongValue (memCtx, v); - } - break; - case PidLidTaskComplete: - task = [sogoObject component: NO secure: NO]; - *data = MAPIBoolValue (memCtx, - [[task status] isEqualToString: @"COMPLETED"]); - break; - case PidLidPercentComplete: - task = [sogoObject component: NO secure: NO]; - doubleValue = ((double) [[task percentComplete] intValue] / 100); - *data = MAPIDoubleValue (memCtx, doubleValue); - break; - case PidLidTaskDateCompleted: - task = [sogoObject component: NO secure: NO]; - dateValue = [task completed]; - if (dateValue) - *data = [dateValue asFileTimeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - break; - // http://msdn.microsoft.com/en-us/library/cc765590.aspx - // It's important to have a proper value for PidLidTaskState - // as it'll affect the UI options of Outlook - making the - // task non-editable in some cases. - case PidLidTaskState: - *data = MAPILongValue (memCtx, 0x1); // not assigned - break; - case PidLidTaskMode: // TODO - *data = MAPILongValue (memCtx, 0x0); - break; - case PidLidTaskFRecurring: - case PidLidTaskAccepted: // TODO - *data = MAPIBoolValue (memCtx, NO); - break; - case PidLidTaskActualEffort: // TODO - case PidLidTaskEstimatedEffort: // TODO - *data = MAPILongValue (memCtx, 0); - break; - case PR_HASATTACH: - *data = MAPIBoolValue (memCtx, NO); - break; - - case PidLidTaskDueDate: - task = [sogoObject component: NO secure: NO]; - dateValue = [task due]; - if (dateValue) - *data = [dateValue asFileTimeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - break; - - case PR_CREATION_TIME: - task = [sogoObject 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 = [sogoObject component: NO secure: NO]; - *data = [[task lastModified] asFileTimeInMemCtx: memCtx]; - break; - case PidLidTaskStatus: // status - task = [sogoObject component: NO secure: NO]; - status = [task status]; - if (![status length] - || [status isEqualToString: @"NEEDS-ACTION"]) - 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; - - // FIXME - use the current user - case PidLidTaskOwner: - *data = [@"openchange@example.com" asUnicodeInMemCtx: memCtx]; - break; - - // See http://msdn.microsoft.com/en-us/library/cc842113.aspx - case PidLidTaskOwnership: - *data = MAPILongValue (memCtx, 0x0); // not assigned - break; - -// #define PidLidFlagRequest 0x9027001f -// #define PidNameContentType 0x905a001f -// #define PidLidBillingInformation 0x908b001f -// #define PidLidTaskStartDate 0x911e0040 -// #define PidLidTaskOwner 0x9122001f -// #define PidLidTaskDeadOccurrence 0x9127000b -// #define PidLidTaskMultipleRecipients 0x912a0003 -// #define PidLidTaskHistory 0x912b0003 -// #define PidLidAcceptanceState 0x912c0003 -// #define PidLidTaskLastUser 0x912d001f -// #define PidLidTaskLastUpdate 0x912e0040 -// #define PidLidTaskOwnership 0x912f0003 -// #define PidLidTaskNoCompute 0x9130000b -// #define PidLidTaskFFixOffline 0x9131000b -// #define PidLidTaskRole 0x9132001f -// #define PidLidTaskVersion 0x91330003 -// #define PidLidTaskAssigner 0x9134001f -// #define PidLidTeamTask 0x9135000b -// #define PidLidTaskRecurrence 0x91360102 -// #define PidLidTaskResetReminder 0x9137000b -// #define PidLidTaskOrdinal 0x91380003 -// #define PidLidMileage 0x914a001f -// #define PidLidAgingDontAgeMe 0x9185000b -// #define PidLidCommonEnd 0x91980040 -// #define PidLidCommonStart 0x91990040 -// #define PidLidNonSendableBcc 0x91d7001f -// #define PidLidNonSendableCc 0x91d8001f -// #define PidLidNonSendtableTo 0x91d9001f -// #define PidLidNonSendBccTrackStatus 0x91da1003 -// #define PidLidNonSendCcTrackStatus 0x91db1003 -// #define PidLidNonSendToTrackStatus 0x91dc1003 -// #define PidLidReminderDelta 0x91e90003 -// #define PidLidReminderFileParameter 0x91ea001f -// #define PidLidReminderSignalTime 0x91eb0040 -// #define PidLidReminderOverride 0x91ec000b -// #define PidLidReminderPlaySound 0x91ed000b -// #define PidLidReminderSet 0x91ee000b -// #define PidLidReminderTime 0x91ef0040 -// #define PidLidReminderType 0x91f20003 -// #define PidLidRemoteStatus 0x91f30003 -// #define PidLidSmartNoAttach 0x91fa000b -// #define PidLidTaskGlobalId 0x91fe0102 -// #define PidLidVerbResponse 0x9203001f -// #define PidLidVerbStream 0x92040102 -// #define PidLidPrivate 0x9224000b -// #define PidLidInternetAccountName 0x9225001f -// #define PidLidInternetAccountStamp 0x9226001f -// #define PidLidUseTnef 0x9227000b -// #define PidLidContactLinkName 0x9229001f -// #define PidLidContactLinkEntry 0x922a0102 -// #define PidLidContactLinkSearchKey 0x922b0102 -// #define PidLidSpamOriginalFolder 0x92370102 -// #define PidLidTaskUpdates 0x9345000b -// #define PidLidTaskStatusOnComplete 0x9346000b -// #define PidLidTaskLastDelegate 0x9347001f -// #define PidLidTaskAssigners 0x934a0102 -// #define PidLidTaskFCreator 0x934c000b -// #define PidLidImapDeleted 0x94e50003 -// #define PidLidHeaderItem 0x94e60003 - - default: - rc = [super getProperty: data withTag: propTag]; + ASSIGN (task, [newSOGoObject component: NO secure: NO]); } + return self; +} + +- (void) dealloc +{ + [task release]; + [super dealloc]; +} + +- (int) getPrIconIndex: (void **) data // 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); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageClass: (void **) data +{ + *data = talloc_strdup(memCtx, "IPM.Task"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSubject: (void **) data // SUMMARY +{ + *data = [[task summary] asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrImportance: (void **) data +{ + uint32_t v; + + if ([[task priority] isEqualToString: @"9"]) + v = 0x0; + else if ([[task priority] isEqualToString: @"1"]) + v = 0x2; + else + v = 0x1; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidTaskComplete: (void **) data +{ + *data = MAPIBoolValue (memCtx, + [[task status] isEqualToString: @"COMPLETED"]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidPercentComplete: (void **) data +{ + double doubleValue; + + doubleValue = ((double) [[task percentComplete] intValue] / 100); + *data = MAPIDoubleValue (memCtx, doubleValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidTaskDateCompleted: (void **) data +{ + NSCalendarDate *dateValue; + int rc = MAPISTORE_SUCCESS; + + dateValue = [task completed]; + if (dateValue) + *data = [dateValue asFileTimeInMemCtx: memCtx]; + else + rc = MAPISTORE_ERR_NOT_FOUND; + return rc; } +- (int) getPidLidTaskState: (void **) data +{ + *data = MAPILongValue (memCtx, 0x1); // not assigned + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidTaskMode: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPidLidTaskFRecurring: (void **) data +{ + return [self getNo: data]; +} + +- (int) getPidLidTaskAccepted: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPidLidTaskActualEffort: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPidLidTaskEstimatedEffort: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPrHasattach: (void **) data +{ + return [self getNo: data]; +} + +- (int) getPidLidTaskDueDate: (void **) data +{ + NSCalendarDate *dateValue; + int rc = MAPISTORE_SUCCESS; + + dateValue = [task due]; + if (dateValue) + *data = [dateValue asFileTimeInMemCtx: memCtx]; + else + rc = MAPISTORE_ERR_NOT_FOUND; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrCreationTime: (void **) data +{ + *data = [[task created] asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageDeliveryTime: (void **) data +{ + *data = [[task lastModified] asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getClientSubmitTime: (void **) data +{ + return [self getPrMessageDeliveryTime: data]; +} + +- (int) getLocalCommitTime: (void **) data +{ + return [self getPrMessageDeliveryTime: data]; +} + +- (int) getLastModificationTime: (void **) data +{ + return [self getPrMessageDeliveryTime: data]; +} + +- (int) getPidLidTaskStatus: (void **) data // status +{ + NSString *status; + uint32_t longValue; + + status = [task status]; + if (![status length] + || [status isEqualToString: @"NEEDS-ACTION"]) + longValue = 0; + else if ([status isEqualToString: @"IN-PROCESS"]) + longValue = 1; + else if ([status isEqualToString: @"COMPLETED"]) + longValue = 2; + else + longValue = 0xff; + *data = MAPILongValue (memCtx, longValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidTaskOwner: (void **) data +{ + *data = [@"openchange@example.com" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidTaskOwnership: (void **) data +{ + return [self getLongZero: data]; +} + - (void) save { iCalCalendar *vCalendar;