Monotone-Parent: 5599b85afd7e2707325836a3b533b900d96b8b0c
Monotone-Revision: 570b17715b63da450bef9fde6d9c95288911034f Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2012-08-15T01:02:08 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
dac62b634c
commit
45974ec74b
|
@ -1,5 +1,10 @@
|
|||
2012-08-14 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* OpenChange/MAPIStoreFolder.m (-moveToFolder:withNewName:):
|
||||
renamed to "moveCopyToFolder:withNewName:isMove:isRecursive:",
|
||||
with the ability to specify whether the operation is a move or
|
||||
copy operation and whether it is recursive or not (for copy).
|
||||
|
||||
* OpenChange/MAPIStoreSOGo.m (sogo_folder_move_folder): if
|
||||
"target_folder_object", we do not attempt to access the
|
||||
corresponding instance member.
|
||||
|
|
|
@ -47,6 +47,9 @@
|
|||
/* helpers */
|
||||
- (NSData *) mimeAttachTag;
|
||||
|
||||
/* move & copy operations */
|
||||
- (void) copyToAttachment: (MAPIStoreAttachment *) newAttachment;
|
||||
|
||||
/* subclasses */
|
||||
- (MAPIStoreEmbeddedMessage *) openEmbeddedMessage;
|
||||
- (MAPIStoreEmbeddedMessage *) createEmbeddedMessage;
|
||||
|
|
|
@ -158,6 +158,30 @@
|
|||
return ULLONG_MAX;
|
||||
}
|
||||
|
||||
- (void) copyToAttachment: (MAPIStoreAttachment *) newAttachment
|
||||
{
|
||||
void *attachMethod;
|
||||
enum mapistore_error error;
|
||||
MAPIStoreEmbeddedMessage *embeddedMessage, *newEmbeddedMessage;
|
||||
|
||||
[self copyPropertiesToObject: newAttachment];
|
||||
|
||||
attachMethod = NULL;
|
||||
error = [self getProperty: &attachMethod
|
||||
withTag: PidTagAttachMethod
|
||||
inMemCtx: NULL];
|
||||
if (error == MAPISTORE_SUCCESS && attachMethod)
|
||||
{
|
||||
if (*(uint32_t *) attachMethod == afEmbeddedMessage)
|
||||
{
|
||||
embeddedMessage = [self openEmbeddedMessage];
|
||||
newEmbeddedMessage = [newAttachment createEmbeddedMessage];
|
||||
[embeddedMessage copyToMessage: newEmbeddedMessage];
|
||||
}
|
||||
talloc_free (attachMethod);
|
||||
}
|
||||
}
|
||||
|
||||
/* subclasses */
|
||||
- (MAPIStoreEmbeddedMessage *) openEmbeddedMessage
|
||||
{
|
||||
|
|
|
@ -126,8 +126,10 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
|||
return rc;
|
||||
}
|
||||
|
||||
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
|
||||
withNewName: (NSString *) newFolderName
|
||||
- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
|
||||
withNewName: (NSString *) newFolderName
|
||||
isMove: (BOOL) isMove
|
||||
isRecursive: (BOOL) isRecursive
|
||||
{
|
||||
enum mapistore_error rc;
|
||||
NSString *path, *pathComponent, *targetPath, *newPath;
|
||||
|
@ -135,7 +137,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
|||
MAPIStoreMapping *mapping;
|
||||
NSRange slashRange;
|
||||
|
||||
if ([targetFolder isKindOfClass: MAPIStoreDBFolderK])
|
||||
if (isMove && [targetFolder isKindOfClass: MAPIStoreDBFolderK])
|
||||
{
|
||||
path = [sogoObject path];
|
||||
slashRange = [path rangeOfString: @"/" options: NSBackwardsSearch];
|
||||
|
@ -158,7 +160,9 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
|||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
else
|
||||
rc = MAPISTORE_ERR_DENIED;
|
||||
rc = [super moveCopyToFolder: targetFolder withNewName: newFolderName
|
||||
isMove: isMove
|
||||
isRecursive: isRecursive];
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -123,8 +123,10 @@
|
|||
andChangeKeys: (struct Binary_r **) targetChangeKeys
|
||||
wantCopy: (uint8_t) want_copy;
|
||||
|
||||
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
|
||||
withNewName: (NSString *) newFolderName;
|
||||
- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
|
||||
withNewName: (NSString *) newFolderName
|
||||
isMove: (BOOL) isMove
|
||||
isRecursive: (BOOL) isRecursive;
|
||||
- (enum mapistore_error) copyToFolder: (MAPIStoreFolder *) targetFolder
|
||||
recursive: (BOOL) resursive
|
||||
withNewName: (NSString *) newFolderName;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
/* TODO: main key arrays must be initialized */
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSAutoreleasePool.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSException.h>
|
||||
|
@ -653,13 +654,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
int rc;
|
||||
MAPIStoreMessage *sourceMsg, *destMsg;
|
||||
TALLOC_CTX *memCtx;
|
||||
struct SPropTagArray *availableProps;
|
||||
bool *exclusions;
|
||||
NSUInteger count;
|
||||
enum MAPITAGS propTag;
|
||||
struct SRow *aRow;
|
||||
int error;
|
||||
void *data;
|
||||
struct SRow aRow;
|
||||
struct SPropValue property;
|
||||
|
||||
memCtx = talloc_zero (NULL, TALLOC_CTX);
|
||||
rc = [sourceFolder openMessage: &sourceMsg
|
||||
|
@ -669,56 +665,23 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
if (rc != MAPISTORE_SUCCESS)
|
||||
goto end;
|
||||
|
||||
rc = [sourceMsg getAvailableProperties: &availableProps
|
||||
inMemCtx: memCtx];
|
||||
if (rc != MAPISTORE_SUCCESS)
|
||||
goto end;
|
||||
|
||||
exclusions = talloc_array(NULL, bool, 65536);
|
||||
exclusions[PR_ROW_TYPE >> 16] = true;
|
||||
exclusions[PR_INSTANCE_KEY >> 16] = true;
|
||||
exclusions[PR_INSTANCE_NUM >> 16] = true;
|
||||
exclusions[PR_INST_ID >> 16] = true;
|
||||
exclusions[PR_FID >> 16] = true;
|
||||
exclusions[PR_MID >> 16] = true;
|
||||
exclusions[PR_SOURCE_KEY >> 16] = true;
|
||||
exclusions[PR_PARENT_SOURCE_KEY >> 16] = true;
|
||||
exclusions[PR_PARENT_FID >> 16] = true;
|
||||
exclusions[PR_CHANGE_KEY >> 16] = true;
|
||||
exclusions[PR_PREDECESSOR_CHANGE_LIST >> 16] = true;
|
||||
|
||||
aRow = talloc_zero (memCtx, struct SRow);
|
||||
aRow->lpProps = talloc_array (aRow, struct SPropValue, 65535);
|
||||
|
||||
for (count = 0; count < availableProps->cValues; count++)
|
||||
{
|
||||
propTag = availableProps->aulPropTag[count];
|
||||
if (!exclusions[propTag >> 16])
|
||||
{
|
||||
error = [sourceMsg getProperty: &data
|
||||
withTag: propTag
|
||||
inMemCtx: aRow];
|
||||
if (error == MAPISTORE_SUCCESS && data)
|
||||
{
|
||||
set_SPropValue_proptag(&aRow->lpProps[aRow->cValues], propTag, data);
|
||||
aRow->cValues++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetChangeKey)
|
||||
{
|
||||
set_SPropValue_proptag(&aRow->lpProps[aRow->cValues], PR_CHANGE_KEY, targetChangeKey);
|
||||
aRow->cValues++;
|
||||
}
|
||||
|
||||
rc = [self createMessage: &destMsg withMID: targetMid
|
||||
isAssociated: [sourceMsg isKindOfClass: MAPIStoreFAIMessageK]];
|
||||
if (rc != MAPISTORE_SUCCESS)
|
||||
goto end;
|
||||
rc = [destMsg addPropertiesFromRow: aRow];
|
||||
if (rc != MAPISTORE_SUCCESS)
|
||||
goto end;
|
||||
|
||||
[sourceMsg copyToMessage: destMsg];
|
||||
|
||||
if (targetChangeKey)
|
||||
{
|
||||
property.ulPropTag = PidTagChangeKey;
|
||||
property.value.bin = *targetChangeKey;
|
||||
aRow.cValues = 1;
|
||||
aRow.lpProps = &property;
|
||||
rc = [destMsg addPropertiesFromRow: &aRow];
|
||||
if (rc != MAPISTORE_SUCCESS)
|
||||
goto end;
|
||||
}
|
||||
[destMsg save];
|
||||
if (!wantCopy)
|
||||
rc = [sourceFolder deleteMessageWithMID: srcMid andFlags: 0];
|
||||
|
@ -795,10 +758,118 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
return rc;
|
||||
}
|
||||
|
||||
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
|
||||
withNewName: (NSString *) newFolderName
|
||||
- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
|
||||
withNewName: (NSString *) newFolderName
|
||||
isMove: (BOOL) isMove
|
||||
isRecursive: (BOOL) isRecursive
|
||||
{
|
||||
return MAPISTORE_ERR_DENIED;
|
||||
enum mapistore_error rc;
|
||||
NSAutoreleasePool *pool;
|
||||
struct SRow folderRow;
|
||||
struct SPropValue nameProperty;
|
||||
MAPIStoreFolder *subFolder, *newFolder;
|
||||
NSArray *children;
|
||||
MAPIStoreMapping *mapping;
|
||||
MAPIStoreMessage *message, *targetMessage;
|
||||
NSUInteger count, max;
|
||||
NSString *childKey;
|
||||
uint64_t fmid;
|
||||
|
||||
/* TODO: one possible issue with this algorithm is that moved messages will
|
||||
lack a version number and will all be assigned a new one, even though
|
||||
they have not changed. This also means that they will be transferred
|
||||
again to the client during a sync operation. */
|
||||
|
||||
if ([targetFolder supportsSubFolders])
|
||||
{
|
||||
mapping = [self mapping];
|
||||
|
||||
if (!newFolderName)
|
||||
newFolderName = [sogoObject displayName];
|
||||
nameProperty.ulPropTag = PidTagDisplayName;
|
||||
nameProperty.value.lpszW = [newFolderName UTF8String];
|
||||
folderRow.lpProps = &nameProperty;
|
||||
folderRow.cValues = 1;
|
||||
rc = [targetFolder createFolder: &folderRow
|
||||
withFID: [self objectId]
|
||||
andKey: &childKey];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
{
|
||||
newFolder = [targetFolder lookupFolder: childKey];
|
||||
[self copyPropertiesToObject: newFolder];
|
||||
|
||||
pool = [NSAutoreleasePool new];
|
||||
children = [self messageKeys];
|
||||
max = [children count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
childKey = [children objectAtIndex: count];
|
||||
message = [self lookupMessage: childKey];
|
||||
targetMessage = [newFolder createMessage: NO];
|
||||
[message copyToMessage: targetMessage];
|
||||
if (isMove)
|
||||
{
|
||||
fmid = [mapping idFromURL: [message url]];
|
||||
[self deleteMessageWithMID: fmid andFlags: 0];
|
||||
[mapping registerURL: [targetMessage url]
|
||||
withID: fmid];
|
||||
}
|
||||
[targetMessage save];
|
||||
}
|
||||
[pool release];
|
||||
|
||||
pool = [NSAutoreleasePool new];
|
||||
children = [self faiMessageKeys];
|
||||
max = [children count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
childKey = [children objectAtIndex: count];
|
||||
message = [self lookupFAIMessage: childKey];
|
||||
targetMessage = [newFolder createMessage: YES];
|
||||
[message copyToMessage: targetMessage];
|
||||
if (isMove)
|
||||
{
|
||||
fmid = [mapping idFromURL: [message url]];
|
||||
[self deleteMessageWithMID: fmid andFlags: 0];
|
||||
[mapping registerURL: [targetMessage url]
|
||||
withID: fmid];
|
||||
}
|
||||
[targetMessage save];
|
||||
}
|
||||
[pool release];
|
||||
|
||||
if (isRecursive)
|
||||
{
|
||||
pool = [NSAutoreleasePool new];
|
||||
children = [self folderKeys];
|
||||
max = [children count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
childKey = [children objectAtIndex: count];
|
||||
subFolder = [self lookupFolder: childKey];
|
||||
[subFolder moveCopyToFolder: newFolder withNewName: nil
|
||||
isMove: isMove
|
||||
isRecursive: isRecursive];
|
||||
}
|
||||
[pool release];
|
||||
}
|
||||
|
||||
if (isMove)
|
||||
{
|
||||
fmid = [mapping idFromURL: [self url]];
|
||||
[mapping unregisterURLWithID: fmid];
|
||||
[self deleteFolder];
|
||||
[mapping registerURL: [newFolder url]
|
||||
withID: fmid];
|
||||
}
|
||||
[targetFolder cleanupCaches];
|
||||
}
|
||||
[self cleanupCaches];
|
||||
}
|
||||
else
|
||||
rc = MAPISTORE_ERR_DENIED;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
- (enum mapistore_error) copyToFolder: (MAPIStoreFolder *) targetFolder
|
||||
|
|
|
@ -207,7 +207,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
|
|||
}
|
||||
|
||||
- (int) getPidTagContentUnreadCount: (void **) data
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
EOQualifier *searchQualifier;
|
||||
uint32_t longValue;
|
||||
|
@ -1012,8 +1012,10 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
|||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
|
||||
withNewName: (NSString *) newFolderName
|
||||
- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
|
||||
withNewName: (NSString *) newFolderName
|
||||
isMove: (BOOL) isMove
|
||||
isRecursive: (BOOL) isRecursive
|
||||
{
|
||||
enum mapistore_error rc;
|
||||
NSURL *folderURL, *newFolderURL;
|
||||
|
@ -1022,12 +1024,11 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
|||
NSException *error;
|
||||
MAPIStoreMapping *mapping;
|
||||
|
||||
if ([targetFolder isKindOfClass: MAPIStoreMailFolderK])
|
||||
if (isMove && [targetFolder isKindOfClass: MAPIStoreMailFolderK])
|
||||
{
|
||||
folderURL = [sogoObject imap4URL];
|
||||
if (!newFolderName)
|
||||
newFolderName = [[sogoObject nameInContainer]
|
||||
substringFromIndex: 6]; /* length of "folder" */
|
||||
newFolderName = [sogoObject displayName];
|
||||
newFolderName = [newFolderName stringByEscapingURL];
|
||||
targetSOGoFolder = [targetFolder sogoObject];
|
||||
newFolderURL = [NSURL URLWithString: newFolderName
|
||||
|
@ -1053,9 +1054,13 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
|||
parentDBFolderPath,
|
||||
newFolderName]];
|
||||
}
|
||||
[targetFolder cleanupCaches];
|
||||
[self cleanupCaches];
|
||||
}
|
||||
else
|
||||
rc = MAPISTORE_ERR_DENIED;
|
||||
rc = [super moveCopyToFolder: targetFolder withNewName: newFolderName
|
||||
isMove: isMove
|
||||
isRecursive: isRecursive];
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,9 @@
|
|||
|
||||
- (NSArray *) activeUserRoles;
|
||||
|
||||
/* move & copy internal ops */
|
||||
- (void) copyToMessage: (MAPIStoreMessage *) newMessage;
|
||||
|
||||
/* subclasses */
|
||||
- (void) save;
|
||||
|
||||
|
|
|
@ -425,6 +425,41 @@ rtf2html (NSData *compressedRTF)
|
|||
andType: MAPISTORE_MESSAGE_TABLE];
|
||||
}
|
||||
|
||||
- (void) copyToMessage: (MAPIStoreMessage *) newMessage
|
||||
|
||||
{
|
||||
TALLOC_CTX *memCtx;
|
||||
struct mapistore_message *messageData;
|
||||
NSArray *keys;
|
||||
NSUInteger count, max;
|
||||
NSString *key;
|
||||
MAPIStoreAttachment *attachment, *newAttachment;
|
||||
|
||||
memCtx = talloc_zero (NULL, TALLOC_CTX);
|
||||
|
||||
/* message headers and recipients */
|
||||
[self getMessageData: &messageData inMemCtx: memCtx];
|
||||
[newMessage modifyRecipientsWithRecipients: messageData->recipients
|
||||
andCount: messageData->recipients_count
|
||||
andColumns: messageData->columns];
|
||||
|
||||
/* properties */
|
||||
[self copyPropertiesToObject: newMessage];
|
||||
|
||||
/* attachments */
|
||||
keys = [self attachmentKeys];
|
||||
max = [keys count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
key = [keys objectAtIndex: count];
|
||||
attachment = [self lookupAttachment: key];
|
||||
newAttachment = [newMessage createAttachment];
|
||||
[attachment copyToAttachment: newAttachment];
|
||||
}
|
||||
|
||||
talloc_free (memCtx);
|
||||
}
|
||||
|
||||
- (enum mapistore_error) saveMessage
|
||||
{
|
||||
enum mapistore_error rc;
|
||||
|
|
|
@ -90,6 +90,9 @@
|
|||
- (int) getPidTagLastModificationTime: (void **) data
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
|
||||
/* move and copy operations */
|
||||
- (void) copyPropertiesToObject: (MAPIStoreObject *) newObject;
|
||||
|
||||
/* subclasses */
|
||||
- (NSString *) nameInContainer;
|
||||
- (NSDate *) creationTime;
|
||||
|
|
|
@ -315,6 +315,62 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
|||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
/* move and copy operations */
|
||||
- (void) copyPropertiesToObject: (MAPIStoreObject *) newObject
|
||||
{
|
||||
TALLOC_CTX *memCtx;
|
||||
struct SPropTagArray *availableProps;
|
||||
struct SRow row;
|
||||
enum MAPITAGS propTag;
|
||||
bool *exclusions;
|
||||
NSUInteger count;
|
||||
enum mapistore_error error;
|
||||
void *data;
|
||||
|
||||
memCtx = talloc_zero (NULL, TALLOC_CTX);
|
||||
|
||||
[self getAvailableProperties: &availableProps inMemCtx: memCtx];
|
||||
|
||||
/* We exclude identity and versioning properties to facilitate copy
|
||||
operations. If they need to be set (move operations), the caller will need
|
||||
to take care of them. */
|
||||
exclusions = talloc_array (memCtx, bool, 65536);
|
||||
exclusions[PidTagRowType >> 16] = true;
|
||||
exclusions[PidTagInstanceKey >> 16] = true;
|
||||
exclusions[PidTagInstanceNum >> 16] = true;
|
||||
exclusions[PidTagInstID >> 16] = true;
|
||||
exclusions[PidTagAttachNumber >> 16] = true;
|
||||
exclusions[PidTagFolderId >> 16] = true;
|
||||
exclusions[PidTagMid >> 16] = true;
|
||||
exclusions[PidTagSourceKey >> 16] = true;
|
||||
exclusions[PidTagParentSourceKey >> 16] = true;
|
||||
exclusions[PidTagParentFolderId >> 16] = true;
|
||||
exclusions[PidTagChangeKey >> 16] = true;
|
||||
exclusions[PidTagChangeNumber >> 16] = true;
|
||||
exclusions[PidTagPredecessorChangeList >> 16] = true;
|
||||
|
||||
row.cValues = 0;
|
||||
row.lpProps = talloc_array (memCtx, struct SPropValue, 65535);
|
||||
|
||||
for (count = 0; count < availableProps->cValues; count++)
|
||||
{
|
||||
propTag = availableProps->aulPropTag[count];
|
||||
if (!exclusions[propTag >> 16])
|
||||
{
|
||||
error = [self getProperty: &data withTag: propTag inMemCtx: memCtx];
|
||||
if (error == MAPISTORE_SUCCESS && data)
|
||||
{
|
||||
set_SPropValue_proptag (row.lpProps + row.cValues, propTag, data);
|
||||
row.cValues++;
|
||||
}
|
||||
}
|
||||
}
|
||||
[newObject addPropertiesFromRow: &row];
|
||||
|
||||
talloc_free (memCtx);
|
||||
|
||||
}
|
||||
|
||||
/* subclasses */
|
||||
- (NSString *) nameInContainer
|
||||
{
|
||||
|
|
|
@ -639,8 +639,10 @@ sogo_folder_move_folder(void *folder_object, void *target_folder_object,
|
|||
else
|
||||
newFolderName = nil;
|
||||
|
||||
rc = [moveFolder moveToFolder: targetFolder
|
||||
withNewName: newFolderName];
|
||||
rc = [moveFolder moveCopyToFolder: targetFolder
|
||||
withNewName: newFolderName
|
||||
isMove: YES
|
||||
isRecursive: YES];
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue