Monotone-Parent: 5b4e61e92b3d68b92ea25f1513eb120e502250a1
Monotone-Revision: 1e529d97ad640de07982d342ce216985cba625f7 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2012-07-20T15:44:25 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
965cd9379e
commit
1476b93a45
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#import "MAPIStorePropertySelectors.h"
|
||||
#import "NSString+MAPIStore.h"
|
||||
|
||||
#import "MAPIStoreObjectProxy.h"
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue