Monotone-Parent: 5b4e61e92b3d68b92ea25f1513eb120e502250a1

Monotone-Revision: 1e529d97ad640de07982d342ce216985cba625f7

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2012-07-20T15:44:25
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2012-07-20 15:44:25 +00:00
parent 965cd9379e
commit 1476b93a45
5 changed files with 238 additions and 61 deletions

View File

@ -115,6 +115,30 @@
return self;
}
- (void) _setupAttachmentParts
{
NSUInteger count, max;
NSArray *events;
NSString *newKey;
MAPIStoreCalendarAttachment *attachment;
NSUInteger aid;
events = [calendar events];
max = [events count];
for (count = 1; count < max; count++)
{
attachment = [MAPIStoreCalendarAttachment
mapiStoreObjectInContainer: self];
/* we now that there are no attachments yet, so we can assume that the
right AID is 0 from the start */
aid = count - 1;
[attachment setAID: aid];
[attachment setEvent: [events objectAtIndex: count]];
newKey = [NSString stringWithFormat: @"%ul", aid];
[attachmentParts setObject: attachment forKey: newKey];
}
}
- (id) initWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newFolder
{
@ -140,6 +164,7 @@
origCalendar = [sogoObject calendar: YES secure: YES];
calendar = [origCalendar mutableCopy];
masterEvent = [[calendar events] objectAtIndex: 0];
[self _setupAttachmentParts];
}
context = [self context];
userContext = [self userContext];
@ -397,9 +422,51 @@
return rc;
}
- (void) _updateAttachedEvent: (MAPIStoreCalendarAttachment *) attachment
withUID: (NSString *) uid
{
iCalEvent *newEvent;
SOGoUser *activeUser;
newEvent = [iCalEvent groupWithTag: @"vevent"];
[calendar addToEvents: newEvent];
activeUser = [[self context] activeUser];
[newEvent setUid: uid];
[newEvent updateFromMAPIProperties: [attachment properties]
inUserContext: [self userContext]
withActiveUser: activeUser];
}
- (void) _updateAttachedEvents
{
NSMutableArray *otherEvents;
NSArray *allAttachments;
NSUInteger count, max;
NSString *uid;
/* cleanup all recurring events */
otherEvents = [[calendar events] mutableCopy];
[otherEvents removeObject: masterEvent];
[calendar removeChildren: otherEvents];
[otherEvents release];
uid = [masterEvent uid];
allAttachments = [attachmentParts allValues];
max = [allAttachments count];
for (count = 0; count < max; count++)
[self _updateAttachedEvent: [allAttachments objectAtIndex: count]
withUID: uid];
}
- (void) save
{
// iCalCalendar *vCalendar;
// NSCalendarDate *now;
NSString *uid;
// iCalEvent *newEvent;
// iCalPerson *userPerson;
SOGoUser *activeUser;
if (isNew)
{
@ -429,6 +496,7 @@
[masterEvent updateFromMAPIProperties: properties
inUserContext: [self userContext]
withActiveUser: activeUser];
[self _updateAttachedEvents];
[sogoObject updateContentWithCalendar: calendar
fromRequest: nil];

View File

@ -24,6 +24,7 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
#import <NGExtensions/NSObject+Logs.h>
@ -45,7 +46,7 @@
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
static Class EOKeyValueQualifierK;
static Class EOKeyValueQualifierK, SOGoMAPIDBFolderK;
static NSString *MAPIStoreRightReadItems = @"RightsReadItems";
static NSString *MAPIStoreRightCreateItems = @"RightsCreateItems";
@ -62,6 +63,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
+ (void) initialize
{
EOKeyValueQualifierK = [EOKeyValueQualifier class];
SOGoMAPIDBFolderK = [SOGoMAPIDBFolder class];
}
- (void) setupAuxiliaryObjects
@ -84,9 +86,40 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
withFID: (uint64_t) newFID
andKey: (NSString **) newKeyP
{
*newKeyP = [NSString stringWithFormat: @"0x%.16"PRIx64, (unsigned long long) newFID];
enum mapistore_error rc;
NSString *folderName, *nameInContainer;
SOGoMAPIDBFolder *newFolder;
struct SPropValue *value;
return MAPISTORE_SUCCESS;
value = get_SPropValue_SRow (aRow, PidTagDisplayName);
if (value)
folderName = [NSString stringWithUTF8String: value->value.lpszW];
else
{
value = get_SPropValue_SRow (aRow, PidTagDisplayName_string8);
if (value)
folderName = [NSString stringWithUTF8String: value->value.lpszA];
else
folderName = nil;
}
if (folderName)
{
nameInContainer = [NSString stringWithFormat: @"0x%.16"PRIx64,
(unsigned long long) newFID];
newFolder = [SOGoMAPIDBFolderK objectWithName: nameInContainer
inContainer: sogoObject];
[newFolder setIsNew: YES];
[[newFolder properties] setObject: folderName
forKey: MAPIPropertyKey (PidTagDisplayName)];
[newFolder save];
*newKeyP = nameInContainer;
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERR_INVALID_PARAMETER;
return rc;
}
- (MAPIStoreMessage *) createMessage
@ -134,6 +167,15 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
andSortOrderings: sortOrderings];
}
/* TODO: now that we are DB-based, this method can easily be implemented
- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum
andCN: (NSNumber **) cnNbrs
inTableType: (enum mapistore_table_type) tableType
{
}
*/
- (NSDate *) lastMessageModificationTime
{
NSUInteger count, max;

View File

@ -56,6 +56,7 @@
#include <mapistore/mapistore_errors.h>
static NSString *resourcesDir = nil;
static Class MAPIStoreFolderK = nil;
/* rtf conversion via unrtf */
static int
@ -130,6 +131,7 @@ rtf2html (NSData *compressedRTF)
resourcesDir = [[NSBundle bundleForClass: self] resourcePath];
[resourcesDir retain];
}
MAPIStoreFolderK = [MAPIStoreFolder class];
}
- (id) init
@ -442,61 +444,68 @@ rtf2html (NSData *compressedRTF)
|| (!isNew && [self subscriberCanModifyMessage])))
{
/* 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)
if ([container isKindOfClass: MAPIStoreFolderK])
{
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);
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];
/* table modified */
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count]
notifyChangesForChild: self];
if ([container isKindOfClass: MAPIStoreFolderK])
{
/* table modified */
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count]
notifyChangesForChild: self];
[container cleanupCaches];
}
[self setIsNew: NO];
[container cleanupCaches];
rc = MAPISTORE_SUCCESS;
}
else
@ -645,9 +654,19 @@ rtf2html (NSData *compressedRTF)
- (int) getPidTagMid: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongLongValue (memCtx, [self objectId]);
int rc;
uint64_t obId;
return MAPISTORE_SUCCESS;
obId = [self objectId];
if (obId == ULLONG_MAX)
rc = MAPISTORE_ERR_NOT_FOUND;
else
{
*data = MAPILongLongValue (memCtx, obId);
rc = MAPISTORE_SUCCESS;
}
return rc;
}
- (int) getPidTagMessageLocaleId: (void **) data

View File

@ -21,6 +21,7 @@
*/
#import "MAPIStorePropertySelectors.h"
#import "NSString+MAPIStore.h"
#import "MAPIStoreObjectProxy.h"

View File

@ -22,6 +22,7 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSSet.h>
#import <Foundation/NSString.h>
#import <NGExtensions/NSCalendarDate+misc.h>
@ -50,11 +51,13 @@
{
NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate;
NSString *monthDay, *month;
NSMutableSet *exceptionDates;
NSArray *realExDates;
iCalRecurrenceRule *rule;
iCalByDayMask *byDayMask;
iCalWeekOccurrence weekOccurrence;
iCalWeekOccurrences dayMaskDays;
NSUInteger count;
NSUInteger count, max;
NSInteger bySetPos;
unsigned char maskValue;
@ -209,7 +212,12 @@
rp->EndType];
}
/* exception dates */
/* exception dates:
- take all deleted instances
- remove all modified instances from the above set
- add remaining instances, in chronological order
*/
exceptionDates = [NSMutableSet set];
for (count = 0; count < rp->DeletedInstanceCount; count++)
{
exDate
@ -217,8 +225,23 @@
exDate = [exDate hour: [startDate hourOfDay]
minute: [startDate minuteOfHour]
second: [startDate secondOfMinute]];
[entity addToExceptionDates: exDate];
[exceptionDates addObject: exDate];
}
for (count = 0; count < rp->ModifiedInstanceCount; count++)
{
exDate
= [NSDate dateFromMinutesSince1601: rp->ModifiedInstanceDates[count]];
exDate = [exDate hour: [startDate hourOfDay]
minute: [startDate minuteOfHour]
second: [startDate secondOfMinute]];
[exceptionDates removeObject: exDate];
}
realExDates = [[exceptionDates allObjects]
sortedArrayUsingSelector: @selector (compare:)];
max = [realExDates count];
for (count = 0; count < max; count++)
[entity addToExceptionDates: [realExDates objectAtIndex: count]];
}
@end
@ -233,11 +256,14 @@
iCalRecurrenceFrequency freq;
iCalByDayMask *byDayMask;
NSString *byMonthDay, *bySetPos;
NSCalendarDate *startDate, *endDate, *untilDate, *beginOfWeek, *minimumDate, *moduloDate, *midnight;
NSCalendarDate *startDate, *endDate, *untilDate, *beginOfWeek, *minimumDate,
*moduloDate, *midnight;
iCalWeekOccurrences *days;
NSInteger dayOfWeek, repeatInterval, repeatCount, count, firstOccurrence, max;
NSInteger dayOfWeek, repeatInterval, repeatCount, count, firstOccurrence,
max;
uint32_t nbrMonths, mask;
NSArray *exDates;
NSArray *events;
NSMutableArray *deletedDates, *modifiedDates;
startDate = [event firstRecurrenceStartDate];
[startDate setTimeZone: timeZone];
@ -394,16 +420,37 @@
}
}
exDates = [[event exceptionDatesWithTimeZone: utcTZ]
sortedArrayUsingFunction: NSDateCompare
context: NULL];
max = [exDates count];
events = [[event parent] events];
max = [events count];
modifiedDates = [NSMutableArray arrayWithCapacity: max];
for (count = 1; count < max; count++)
{
startDate = [[events objectAtIndex: count] recurrenceId];
[modifiedDates addObject: startDate];
}
max = [modifiedDates count];
rp->ModifiedInstanceCount = max;
rp->ModifiedInstanceDates = talloc_array (memCtx, uint32_t, max);
for (count = 0; count < max; count++)
{
startDate = [[modifiedDates objectAtIndex: count]
hour: 0 minute: 0 second: 0];
*(rp->ModifiedInstanceDates + count) = [startDate asMinutesSince1601];
}
deletedDates = [modifiedDates mutableCopy];
[deletedDates autorelease];
[deletedDates
addObjectsFromArray: [event exceptionDatesWithTimeZone: utcTZ]];
[deletedDates sortUsingFunction: NSDateCompare context: NULL];
max = [deletedDates count];
rp->DeletedInstanceCount = max;
rp->DeletedInstanceDates = talloc_array (memCtx, uint32_t, max);
for (count = 0; count < max; count++)
{
startDate = [[exDates objectAtIndex: count] hour: 0 minute: 0 second: 0];
startDate = [[deletedDates objectAtIndex: count]
hour: 0 minute: 0 second: 0];
*(rp->DeletedInstanceDates + count) = [startDate asMinutesSince1601];
}
}