Monotone-Parent: 14109a6df43dc184c83153fd032827c7dc242db9

Monotone-Revision: 128103783f98ef7a97e614a54b987851cefbaf36

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2011-12-01T22:36:35
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2011-12-01 22:36:35 +00:00
parent e846ec1b8c
commit eff11b0b9c
4 changed files with 275 additions and 189 deletions

View File

@ -21,6 +21,7 @@
*/
#import "MAPIStoreActiveTables.h"
#import "MAPIStoreContext.h"
#import "NSObject+MAPIStore.h"
#import "MAPIStoreFAIMessage.h"
@ -29,6 +30,7 @@
#include <talloc.h>
#include <util/time.h>
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
@implementation MAPIStoreFAIMessage
@ -45,4 +47,18 @@
return [self getYes: data inMemCtx: memCtx];
}
- (enum mapistore_error) saveMessage
{
enum mapistore_error rc;
MAPIStoreContext *context;
context = [self context];
if ([[context activeUser] isEqual: [context ownerUser]])
rc = [super saveMessage];
else
rc = MAPISTORE_ERR_DENIED;
return rc;
}
@end

View File

@ -336,35 +336,41 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
mapping = [[self context] mapping];
childURL = [mapping urlFromID: fid];
if (childURL)
rc = MAPISTORE_ERR_EXIST;
else
if ([[context activeUser] isEqual: [context ownerUser]]
|| [self subscriberCanCreateSubFolders])
{
folderKey = [self createFolder: aRow withFID: fid];
if (folderKey)
mapping = [[self context] mapping];
childURL = [mapping urlFromID: fid];
if (childURL)
rc = MAPISTORE_ERR_EXIST;
else
{
[self cleanupCaches];
baseURL = [self url];
if (![baseURL hasSuffix: @"/"])
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
childURL = [NSString stringWithFormat: @"%@%@",
baseURL, folderKey];
[mapping registerURL: childURL withID: fid];
childFolder = [self lookupFolder: folderKey];
if (childFolder)
folderKey = [self createFolder: aRow withFID: fid];
if (folderKey)
{
[childFolder addPropertiesFromRow: aRow];
*childFolderPtr = childFolder;
[self cleanupCaches];
baseURL = [self url];
if (![baseURL hasSuffix: @"/"])
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
childURL = [NSString stringWithFormat: @"%@%@",
baseURL, folderKey];
[mapping registerURL: childURL withID: fid];
childFolder = [self lookupFolder: folderKey];
if (childFolder)
{
[childFolder addPropertiesFromRow: aRow];
*childFolderPtr = childFolder;
}
else
[NSException raise: @"MAPIStoreIOException"
format: @"unable to fetch created folder"];
}
else
[NSException raise: @"MAPIStoreIOException"
format: @"unable to fetch created folder"];
rc = MAPISTORE_ERROR;
}
else
rc = MAPISTORE_ERROR;
}
else
rc = MAPISTORE_ERR_DENIED;
return rc;
}
@ -437,7 +443,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
withMID: (uint64_t) mid
isAssociated: (BOOL) isAssociated
{
int rc;
enum mapistore_error rc;
MAPIStoreMessage *message;
NSString *baseURL, *childURL;
MAPIStoreMapping *mapping;
@ -445,26 +451,33 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16llx associated: %d",
__FUNCTION__, mid, isAssociated];
mapping = [[self context] mapping];
if ([mapping urlFromID: mid])
rc = MAPISTORE_ERR_EXIST;
else
context = [self context];
if ([[context activeUser] isEqual: [context ownerUser]]
|| (!isAssociated && [self subscriberCanCreateMessages]))
{
message = [self createMessage: isAssociated];
if (message)
{
baseURL = [self url];
if (![baseURL hasSuffix: @"/"])
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
childURL = [NSString stringWithFormat: @"%@%@",
baseURL, [message nameInContainer]];
[mapping registerURL: childURL withID: mid];
*messagePtr = message;
rc = MAPISTORE_SUCCESS;
}
mapping = [[self context] mapping];
if ([mapping urlFromID: mid])
rc = MAPISTORE_ERR_EXIST;
else
rc = MAPISTORE_ERROR;
{
message = [self createMessage: isAssociated];
if (message)
{
baseURL = [self url];
if (![baseURL hasSuffix: @"/"])
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
childURL = [NSString stringWithFormat: @"%@%@",
baseURL, [message nameInContainer]];
[mapping registerURL: childURL withID: mid];
*messagePtr = message;
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERROR;
}
}
else
rc = MAPISTORE_ERR_DENIED;
return rc;
}
@ -491,73 +504,80 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
message = [self lookupMessageByURL: childURL];
if (message)
{
/* we ensure the table caches are loaded so that old and new state
can be compared */
activeTables = ([message isKindOfClass: MAPIStoreFAIMessageK]
? [self activeFAIMessageTables]
: [self activeMessageTables]);
max = [activeTables count];
for (count = 0; count < max; count++)
[[activeTables objectAtIndex: count] restrictedChildKeys];
msgObject = [message sogoObject];
if (([msgObject respondsToSelector: @selector (prepareDelete)]
&& [msgObject prepareDelete])
|| [msgObject delete])
if ([[context activeUser] isEqual: [context ownerUser]]
|| (![message isKindOfClass: MAPIStoreFAIMessageK]
&& [self subscriberCanDeleteMessages]))
{
rc = MAPISTORE_ERROR;
[self logWithFormat: @"ERROR deleting object at URL: %@", childURL];
/* we ensure the table caches are loaded so that old and new state
can be compared */
activeTables = ([message isKindOfClass: MAPIStoreFAIMessageK]
? [self activeFAIMessageTables]
: [self activeMessageTables]);
max = [activeTables count];
for (count = 0; count < max; count++)
[[activeTables objectAtIndex: count] restrictedChildKeys];
msgObject = [message sogoObject];
if (([msgObject respondsToSelector: @selector (prepareDelete)]
&& [msgObject prepareDelete])
|| [msgObject delete])
{
rc = MAPISTORE_ERROR;
[self logWithFormat: @"ERROR deleting object at URL: %@", childURL];
}
else
{
if (![message isNew])
{
/* folder notification */
notif_parameters
= talloc_zero(NULL,
struct mapistore_object_notification_parameters);
notif_parameters->object_id = [self objectId];
notif_parameters->tag_count = 5;
notif_parameters->tags = talloc_array (notif_parameters,
enum MAPITAGS, 5);
notif_parameters->tags[0] = PR_CONTENT_COUNT;
notif_parameters->tags[1] = PR_DELETED_COUNT_TOTAL;
notif_parameters->tags[2] = PR_MESSAGE_SIZE;
notif_parameters->tags[3] = PR_NORMAL_MESSAGE_SIZE;
notif_parameters->tags[4] = PR_DELETED_MSG_COUNT;
notif_parameters->new_message_count = true;
notif_parameters->message_count = [[self messageKeys]
count] - 1;
connInfo = [[self context] connectionInfo];
mapistore_push_notification (connInfo->mstore_ctx,
MAPISTORE_FOLDER,
MAPISTORE_OBJECT_MODIFIED,
notif_parameters);
talloc_free(notif_parameters);
/* message notification */
notif_parameters
= talloc_zero(NULL,
struct mapistore_object_notification_parameters);
notif_parameters->object_id = mid;
notif_parameters->folder_id = [self objectId];
/* Exchange sends a fnevObjectCreated!! */
mapistore_push_notification (connInfo->mstore_ctx,
MAPISTORE_MESSAGE,
MAPISTORE_OBJECT_CREATED,
notif_parameters);
talloc_free(notif_parameters);
/* table notification */
for (count = 0; count < max; count++)
[[activeTables objectAtIndex: count]
notifyChangesForChild: message];
}
[self logWithFormat: @"successfully deleted object at URL: %@", childURL];
[mapping unregisterURLWithID: mid];
[self cleanupCaches];
rc = MAPISTORE_SUCCESS;
}
}
else
{
if (![message isNew])
{
/* folder notification */
notif_parameters
= talloc_zero(NULL,
struct mapistore_object_notification_parameters);
notif_parameters->object_id = [self objectId];
notif_parameters->tag_count = 5;
notif_parameters->tags = talloc_array (notif_parameters,
enum MAPITAGS, 5);
notif_parameters->tags[0] = PR_CONTENT_COUNT;
notif_parameters->tags[1] = PR_DELETED_COUNT_TOTAL;
notif_parameters->tags[2] = PR_MESSAGE_SIZE;
notif_parameters->tags[3] = PR_NORMAL_MESSAGE_SIZE;
notif_parameters->tags[4] = PR_DELETED_MSG_COUNT;
notif_parameters->new_message_count = true;
notif_parameters->message_count = [[self messageKeys]
count] - 1;
connInfo = [[self context] connectionInfo];
mapistore_push_notification (connInfo->mstore_ctx,
MAPISTORE_FOLDER,
MAPISTORE_OBJECT_MODIFIED,
notif_parameters);
talloc_free(notif_parameters);
/* message notification */
notif_parameters
= talloc_zero(NULL,
struct mapistore_object_notification_parameters);
notif_parameters->object_id = mid;
notif_parameters->folder_id = [self objectId];
/* Exchange sends a fnevObjectCreated!! */
mapistore_push_notification (connInfo->mstore_ctx,
MAPISTORE_MESSAGE,
MAPISTORE_OBJECT_CREATED,
notif_parameters);
talloc_free(notif_parameters);
/* table notification */
for (count = 0; count < max; count++)
[[activeTables objectAtIndex: count]
notifyChangesForChild: message];
}
[self logWithFormat: @"successfully deleted object at URL: %@", childURL];
[mapping unregisterURLWithID: mid];
[self cleanupCaches];
rc = MAPISTORE_SUCCESS;
}
rc = MAPISTORE_ERR_DENIED;
}
else
rc = MAPISTORE_ERR_NOT_FOUND;
@ -667,46 +687,51 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
MAPIStoreMapping *mapping;
struct Binary_r *targetChangeKey;
if ([sourceFolder isKindOfClass: isa]
|| [self isKindOfClass: [sourceFolder class]])
[self logWithFormat: @"%s: this class could probably implement"
@" a specialized/optimized version", __FUNCTION__];
oldMessageURLs = [NSMutableArray arrayWithCapacity: midCount];
mapping = [[self context] mapping];
for (count = 0; rc == MAPISTORE_SUCCESS && count < midCount; count++)
if (wantCopy || [[context activeUser] isEqual: [context ownerUser]])
{
oldMessageURL = [mapping urlFromID: srcMids[count]];
if (oldMessageURL)
if ([sourceFolder isKindOfClass: isa]
|| [self isKindOfClass: [sourceFolder class]])
[self logWithFormat: @"%s: this class could probably implement"
@" a specialized/optimized version", __FUNCTION__];
oldMessageURLs = [NSMutableArray arrayWithCapacity: midCount];
mapping = [[self context] mapping];
for (count = 0; rc == MAPISTORE_SUCCESS && count < midCount; count++)
{
[oldMessageURLs addObject: oldMessageURL];
if (targetChangeKeys)
targetChangeKey = targetChangeKeys[count];
oldMessageURL = [mapping urlFromID: srcMids[count]];
if (oldMessageURL)
{
[oldMessageURLs addObject: oldMessageURL];
if (targetChangeKeys)
targetChangeKey = targetChangeKeys[count];
else
targetChangeKey = NULL;
rc = [self moveCopyMessageWithMID: srcMids[count]
fromFolder: sourceFolder
withMID: targetMids[count]
andChangeKey: targetChangeKey
wantCopy: wantCopy];
}
else
targetChangeKey = NULL;
rc = [self moveCopyMessageWithMID: srcMids[count]
fromFolder: sourceFolder
withMID: targetMids[count]
andChangeKey: targetChangeKey
wantCopy: wantCopy];
rc = MAPISTORE_ERR_NOT_FOUND;
}
else
rc = MAPISTORE_ERR_NOT_FOUND;
}
/* Notifications */
if (rc == MAPISTORE_SUCCESS)
{
[self postNotificationsForMoveCopyMessagesWithMIDs: srcMids
andMessageURLs: oldMessageURLs
andCount: midCount
fromFolder: sourceFolder
withMIDs: targetMids
wantCopy: wantCopy];
/* Notifications */
if (rc == MAPISTORE_SUCCESS)
{
[self postNotificationsForMoveCopyMessagesWithMIDs: srcMids
andMessageURLs: oldMessageURLs
andCount: midCount
fromFolder: sourceFolder
withMIDs: targetMids
wantCopy: wantCopy];
// We cleanup cache of our source and destination folders
[self cleanupCaches];
[sourceFolder cleanupCaches];
// We cleanup cache of our source and destination folders
[self cleanupCaches];
[sourceFolder cleanupCaches];
}
}
else
rc = MAPISTORE_ERR_DENIED;
return rc;
}
@ -1106,7 +1131,24 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (int) getPrAccess: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 0x1|0x2|0x4|0x8|0x10|0x20);
uint32_t access = 0;
BOOL userIsOwner;
userIsOwner = [[context activeUser] isEqual: [context ownerUser]];
if (userIsOwner || [self subscriberCanModifyMessages])
access |= 0x01;
if (userIsOwner || [self subscriberCanReadMessages])
access |= 0x02;
if (userIsOwner || [self subscriberCanDeleteMessages])
access |= 0x04;
if (userIsOwner || [self subscriberCanCreateSubFolders])
access |= 0x08;
if (userIsOwner || [self subscriberCanCreateMessages])
access |= 0x10;
if (userIsOwner)
access |= 0x20;
*data = MAPILongValue (memCtx, access);
return MAPISTORE_SUCCESS;
}

View File

@ -64,7 +64,7 @@
- (int) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr
andRowCount: (uint32_t *) countPtr;
- (int) setReadFlag: (uint8_t) flag;
- (int) saveMessage;
- (enum mapistore_error) saveMessage;
/* helper getters */
- (int) getSMTPAddrType: (void **) data

View File

@ -282,6 +282,22 @@ rtf2html (NSData *compressedRTF)
return MAPISTORE_SUCCESS;
}
- (int) addPropertiesFromRow: (struct SRow *) aRow
{
enum mapistore_error rc;
MAPIStoreContext *context;
context = [self context];
if ([[context activeUser] isEqual: [context ownerUser]]
|| [self subscriberCanModifyMessage])
rc = [super addPropertiesFromRow: aRow];
else
rc = MAPISTORE_ERR_DENIED;
return rc;
}
- (void) addProperties: (NSDictionary *) newNewProperties
{
NSData *htmlData, *rtfData;
@ -407,73 +423,85 @@ rtf2html (NSData *compressedRTF)
andType: MAPISTORE_MESSAGE_TABLE];
}
- (int) saveMessage
- (enum mapistore_error) saveMessage
{
enum mapistore_error rc;
NSArray *containerTables;
NSUInteger count, max;
struct mapistore_object_notification_parameters *notif_parameters;
uint64_t folderId;
struct mapistore_context *mstoreCtx;
MAPIStoreContext *context;
/* notifications */
folderId = [(MAPIStoreFolder *) container objectId];
mstoreCtx = [[self context] connectionInfo]->mstore_ctx;
/* folder modified */
notif_parameters
= talloc_zero(NULL, struct mapistore_object_notification_parameters);
notif_parameters->object_id = folderId;
if (isNew)
context = [self context];
if ([[context activeUser] isEqual: [context ownerUser]]
|| ((isNew
&& [(MAPIStoreFolder *) container subscriberCanCreateMessages])
|| (!isNew && [self subscriberCanModifyMessage])))
{
notif_parameters->tag_count = 3;
notif_parameters->tags = talloc_array (notif_parameters,
enum MAPITAGS, 3);
notif_parameters->tags[0] = PR_CONTENT_COUNT;
notif_parameters->tags[1] = PR_MESSAGE_SIZE;
notif_parameters->tags[2] = PR_NORMAL_MESSAGE_SIZE;
notif_parameters->new_message_count = true;
notif_parameters->message_count
= [[(MAPIStoreFolder *) container messageKeys] count] + 1;
}
mapistore_push_notification (mstoreCtx,
MAPISTORE_FOLDER, MAPISTORE_OBJECT_MODIFIED,
notif_parameters);
talloc_free (notif_parameters);
/* notifications */
folderId = [(MAPIStoreFolder *) container objectId];
mstoreCtx = [[self context] connectionInfo]->mstore_ctx;
/* message created */
if (isNew)
{
/* folder modified */
notif_parameters
= talloc_zero(NULL,
struct mapistore_object_notification_parameters);
notif_parameters->object_id = [self objectId];
notif_parameters->folder_id = folderId;
notif_parameters->tag_count = 0xffff;
= talloc_zero(NULL, struct mapistore_object_notification_parameters);
notif_parameters->object_id = folderId;
if (isNew)
{
notif_parameters->tag_count = 3;
notif_parameters->tags = talloc_array (notif_parameters,
enum MAPITAGS, 3);
notif_parameters->tags[0] = PR_CONTENT_COUNT;
notif_parameters->tags[1] = PR_MESSAGE_SIZE;
notif_parameters->tags[2] = PR_NORMAL_MESSAGE_SIZE;
notif_parameters->new_message_count = true;
notif_parameters->message_count
= [[(MAPIStoreFolder *) container messageKeys] count] + 1;
}
mapistore_push_notification (mstoreCtx,
MAPISTORE_MESSAGE, MAPISTORE_OBJECT_CREATED,
MAPISTORE_FOLDER, MAPISTORE_OBJECT_MODIFIED,
notif_parameters);
talloc_free (notif_parameters);
}
/* we ensure the table caches are loaded so that old and new state
can be compared */
containerTables = [self activeContainerMessageTables];
max = [containerTables count];
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count] restrictedChildKeys];
/* message created */
if (isNew)
{
notif_parameters
= talloc_zero(NULL,
struct mapistore_object_notification_parameters);
notif_parameters->object_id = [self objectId];
notif_parameters->folder_id = folderId;
notif_parameters->tag_count = 0xffff;
mapistore_push_notification (mstoreCtx,
MAPISTORE_MESSAGE, MAPISTORE_OBJECT_CREATED,
notif_parameters);
talloc_free (notif_parameters);
}
/* we ensure the table caches are loaded so that old and new state
can be compared */
containerTables = [self activeContainerMessageTables];
max = [containerTables count];
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count] restrictedChildKeys];
[self save];
[self save];
/* table modified */
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count]
notifyChangesForChild: self];
[self setIsNew: NO];
[properties removeAllObjects];
[container cleanupCaches];
/* table modified */
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count]
notifyChangesForChild: self];
[self setIsNew: NO];
[properties removeAllObjects];
[container cleanupCaches];
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERR_DENIED;
return MAPISTORE_SUCCESS;
return rc;
}
/* helper getters */