Merge pull request #110 from Zentyal/ejhernandez/sharing-calendar-request

This requires https://github.com/openchange/openchange/pull/244 to work
but basically we have modified this backend to store request-related
properties in a `MAPIStoreMailMessage` using the versions message
from the `MAPIStoreMailFolder` container and fix the setter/getter
for the following properties:

  * PidNameXSharingFlavor
  * PidLidSharingFlavor
  * PidNameXSharingCapabilities
  * PidLidSharingResponseType
  * PidLidSharingResponseTime
pull/65/head
Jesús García Sáez 2015-03-25 17:09:14 +01:00
commit 0e5de2df42
7 changed files with 170 additions and 20 deletions

1
NEWS
View File

@ -2,6 +2,7 @@ master
------
Enhancements
- Sharing request among different Outlook versions
- Improve sync speed from Outlook by non-reprocessing already downloaded unread mails
Bug fixes

View File

@ -55,6 +55,11 @@
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey;
- (NSData *) predecessorChangeListForMessageWithKey: (NSString *) messageKey;
/* Extra properties from mail messages that already hit the server */
- (void) setExtraProperties: (NSDictionary *) props
forMessage: (NSString *) messageKey;
- (NSDictionary *) extraPropertiesForMessage: (NSString *) messageKey;
@end
/* MAPIStoreOutboxFolder is a special subclass of MAPIStoreMailFolder where

View File

@ -964,6 +964,37 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
return list;
}
/* Management for extra properties once they already hit the IMAP server */
- (void) setExtraProperties: (NSDictionary *) props
forMessage: (NSString *) messageKey
{
NSMutableDictionary *extraProps, *currentProperties;
NSString *messageUid;
messageUid = [self messageUIDFromMessageKey: messageKey];
currentProperties = [versionsMessage properties];
extraProps = [currentProperties objectForKey: @"ExtraMessagesProperties"];
if (!extraProps)
{
extraProps = [NSMutableDictionary new];
[currentProperties setObject: extraProps forKey: @"ExtraMessagesProperties"];
[extraProps release];
}
[extraProps setObject: props
forKey: messageUid];
[versionsMessage save];
}
- (NSDictionary *) extraPropertiesForMessage: (NSString *) messageKey
{
NSString *messageUid;
messageUid = [self messageUIDFromMessageKey: messageKey];
return [[[versionsMessage properties] objectForKey: @"ExtraMessagesProperties"]
objectForKey: messageUid];
}
- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum
andCN: (NSNumber **) cnNbr
inTableType: (uint8_t) tableType

View File

@ -65,7 +65,7 @@
@class iCalCalendar, iCalEvent;
static Class NSExceptionK;
static Class NSExceptionK, MAPIStoreSharingMessageK;
@interface NSString (MAPIStoreMIME)
@ -108,6 +108,7 @@ static Class NSExceptionK;
+ (void) initialize
{
NSExceptionK = [NSException class];
MAPIStoreSharingMessageK = [MAPIStoreSharingMessage class];
}
- (id) init
@ -267,7 +268,8 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
a sharing object is a proxy in a mail message */
sharingMessage = [[MAPIStoreSharingMessage alloc]
initWithMailHeaders: [sogoObject mailHeaders]
andConnectionInfo: [[self context] connectionInfo]];
andConnectionInfo: [[self context] connectionInfo]
fromMessage: self];
[self addProxy: sharingMessage];
[sharingMessage release];
}
@ -1641,6 +1643,21 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
bodySetup = YES;
}
- (MAPIStoreSharingMessage *) _sharingObject
{
/* Get the sharing object if available */
NSUInteger i, max;
id proxy;
max = [proxies count];
for (i = 0; i < max; i++) {
proxy = [proxies objectAtIndex: i];
if ([proxy isKindOfClass: MAPIStoreSharingMessageK])
return proxy;
}
return nil;
}
- (void) save: (TALLOC_CTX *) memCtx
{
NSNumber *value;
@ -1654,6 +1671,11 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
else /* 0: unflagged, 1: follow up complete */
[sogoObject removeFlags: @"\\Flagged"];
}
if (mailIsSharingObject)
[[self _sharingObject] saveWithMessage: self
andSOGoObject: sogoObject];
}
@end

View File

@ -28,6 +28,7 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSScanner.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <NGExtensions/NGBase64Coding.h>
@ -541,6 +542,7 @@ FillMessageHeadersFromSharingProperties (NGMutableHashMap *headers, NSDictionary
about the properties */
id value;
NSNumber *sharingFlavourNum = nil;
value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingCapabilities)];
if (value)
@ -549,8 +551,32 @@ FillMessageHeadersFromSharingProperties (NGMutableHashMap *headers, NSDictionary
value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingFlavor)];
if (value)
[headers setObject: value
forKey: @"X-MS-Sharing-Flavor"];
sharingFlavourNum = (NSNumber *)value;
else
{
value = [mailProperties objectForKey: MAPIPropertyKey (PidNameXSharingFlavor)];
if (value)
{
/* Transform the hex string to unsigned int */
NSScanner *scanner;
unsigned int sharingFlavour;
scanner = [NSScanner scannerWithString:value];
if ([scanner scanHexInt:&sharingFlavour])
sharingFlavourNum =[NSNumber numberWithUnsignedInt: sharingFlavour];
}
}
if (sharingFlavourNum)
{
if ([sharingFlavourNum unsignedIntegerValue] == 0x5100)
{
/* 0x5100 sharing flavour is not in standard but it seems to
be a denial of request + invitation message so we store
deny sharing flavour */
sharingFlavourNum = [NSNumber numberWithUnsignedInt: SHARING_DENY_REQUEST];
}
[headers setObject: sharingFlavourNum
forKey: @"X-MS-Sharing-Flavor"];
}
value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingInitiatorEntryId)];
if (value)

View File

@ -23,8 +23,10 @@
#ifndef MAPISTORESHARINGMESSAGE_H
#define MAPISTORESHARINGMESSAGE_H
#import "MAPIStoreMailMessage.h"
#import "MAPIStoreObjectProxy.h"
#define SHARING_SPECIAL_FOLDER 0x40290
@interface MAPIStoreSharingMessage : MAPIStoreObjectProxy
{
@ -33,7 +35,8 @@
}
- (id) initWithMailHeaders: (NSDictionary *) mailHeaders
andConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
andConnectionInfo: (struct mapistore_connection_info *) newConnInfo
fromMessage: (MAPIStoreMailMessage *) msg;
/* getters */
- (int) getPidLidSharingCapabilities: (void **) data
@ -89,6 +92,10 @@
- (int) getPidNameContentClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
/* Save */
- (void) saveWithMessage: (MAPIStoreMailMessage *) msg
andSOGoObject: (SOGoMailObject *) sogoObject;
@end
#endif /* MAPISTORECALENDARWRAPPER_H */

View File

@ -22,9 +22,11 @@
#include <talloc.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Mailer/SOGoMailObject.h>
#import <NGExtensions/NGBase64Coding.h>
#import "MAPIStoreTypes.h"
@ -33,9 +35,12 @@
#import "NSString+MAPIStore.h"
#import "NSValue+MAPIStore.h"
#import "MAPIStoreMailFolder.h"
#import "MAPIStoreSharingMessage.h"
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
#include <mapistore/mapistore_nameid.h>
@implementation MAPIStoreSharingMessage
@ -52,6 +57,7 @@
- (id) initWithMailHeaders: (NSDictionary *) mailHeaders
andConnectionInfo: (struct mapistore_connection_info *) newConnInfo
fromMessage: (MAPIStoreMailMessage *) msg
{
NSEnumerator *enumerator;
NSString *key;
@ -67,6 +73,12 @@
[properties setObject: [mailHeaders objectForKey: key]
forKey: key];
}
/* Set request properties from container folder */
NSDictionary *requestProps = [(MAPIStoreMailFolder *)[msg container]
extraPropertiesForMessage: [msg nameInContainer]];
if (requestProps)
[properties addEntriesFromDictionary: requestProps];
}
return self;
@ -123,7 +135,8 @@
value = [properties objectForKey: @"x-ms-sharing-capabilities"];
if (value)
{
*data = [[value stringValue] asUnicodeInMemCtx: memCtx];
*data = [[NSString stringWithFormat:@"%X", [value intValue]]
asUnicodeInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
@ -163,28 +176,28 @@
value = [properties objectForKey: @"x-ms-sharing-capabilities"];
if (value)
{
if ([value intValue] == 0x40290) /* Special folder */
if ([value intValue] == SHARING_SPECIAL_FOLDER)
{
value = [properties objectForKey: @"x-ms-sharing-responsetime"];
auxValue = [properties objectForKey: @"x-ms-sharing-remotename"];
auxValue = [properties objectForKey: @"x-ms-sharing-remoteuid"];
if (value) /* A sharing request */
{
if (auxValue)
*data = MAPILongValue (memCtx, 0x20710);
*data = MAPILongValue (memCtx, SHARING_INVITATION_REQUEST_FOLDER);
else
*data = MAPILongValue (memCtx, 0x20500);
*data = MAPILongValue (memCtx, SHARING_REQUEST_SPECIAL_FOLDER);
}
else
{
if (auxValue) /* It SHOULD be an invitation or response acceptance */
*data = MAPILongValue (memCtx, 0x20310);
else
*data = MAPILongValue (memCtx, 0x23310);
if (auxValue) /* It SHOULD be an invitation or response */
*data = MAPILongValue (memCtx, SHARING_INVITATION_SPECIAL_FOLDER);
else /* No remote info, then denial */
*data = MAPILongValue (memCtx, SHARING_DENY_REQUEST);
}
}
else
{
*data = MAPILongValue (memCtx, 0x310);
*data = MAPILongValue (memCtx, SHARING_INVITATION_FOLDER);
}
rc = MAPISTORE_SUCCESS;
}
@ -202,7 +215,8 @@
value = [properties objectForKey: @"x-ms-sharing-flavor"];
if (value)
{
*data = [[value stringValue] asUnicodeInMemCtx: memCtx];
*data = [[NSString stringWithFormat:@"%X", [value intValue]]
asUnicodeInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
@ -368,7 +382,18 @@
enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND;
id value;
value = [properties objectForKey: @"x-ms-sharing-responsetime"];
value = [properties objectForKey: MAPIPropertyKey (PidLidSharingResponseTime)];
if (!value)
{
value = [properties objectForKey: @"x-ms-sharing-responsetime"];
if (value)
{
/* Here the value is a GSCBufferString */
NSString * responseTime = [NSString stringWithUTF8String: [value UTF8String]];
value = [NSDate dateWithString: responseTime];
}
}
if (value)
{
*data = [value asFileTimeInMemCtx: memCtx];
@ -385,7 +410,10 @@
enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND;
id value;
value = [properties objectForKey: @"x-ms-sharing-responsetype"];
value = [properties objectForKey: MAPIPropertyKey (PidLidSharingResponseType)];
if (!value)
value = [properties objectForKey: @"x-ms-sharing-responsetype"];
if (value)
{
*data = MAPILongValue (memCtx, [value intValue]);
@ -398,8 +426,38 @@
- (int) getPidNameContentClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = talloc_strdup (memCtx, "Sharing");
return MAPISTORE_SUCCESS;
*data = talloc_strdup (memCtx, "Sharing");
return MAPISTORE_SUCCESS;
}
- (void) saveWithMessage: (MAPIStoreMailMessage *) msg
andSOGoObject: (SOGoMailObject *) sogoObject
{
/* Store PidLidSharingResponseType and PidLidSharingResponseTime if
required in versions message from the container as I don't see
other straightforward place to put that information */
id response;
NSDictionary *propsToStore;
response = [[msg properties] objectForKey: MAPIPropertyKey (PidLidSharingResponseType)];
if (response)
{
/* FIXME: Is there any better way to increase the modseq? */
[sogoObject addFlags: @"\\Draft"];
[sogoObject removeFlags: @"\\Draft"];
/* Store this modification in container folder along the property values */
propsToStore = [NSDictionary dictionaryWithObjects:
[NSArray arrayWithObjects: response,
[[msg properties] objectForKey: MAPIPropertyKey (PidLidSharingResponseTime)],
nil]
forKeys:
[NSArray arrayWithObjects: MAPIPropertyKey (PidLidSharingResponseType),
MAPIPropertyKey (PidLidSharingResponseTime), nil]];
[(MAPIStoreMailFolder *)[msg container] setExtraProperties: propsToStore
forMessage: [msg nameInContainer]];
}
}
@end