(feat) applied all changes as a patch coming from PR #180
parent
d05fd407bd
commit
ae6ed0c055
|
@ -145,7 +145,8 @@ $(DBMSGREADER_TOOL)_LIB_DIRS += \
|
||||||
-L../SoObjects/SOGo/SOGo.framework/sogo -lSOGo \
|
-L../SoObjects/SOGo/SOGo.framework/sogo -lSOGo \
|
||||||
-L../SOPE/GDLContentStore/obj/ -lGDLContentStore \
|
-L../SOPE/GDLContentStore/obj/ -lGDLContentStore \
|
||||||
-L../SOPE/NGCards/obj/ -lNGCards \
|
-L../SOPE/NGCards/obj/ -lNGCards \
|
||||||
-lNGObjWeb
|
-lNGObjWeb \
|
||||||
|
$(LIBMAPI_LIBS)
|
||||||
|
|
||||||
TEST_TOOL_NAME += $(PLREADER_TOOL) $(DBMSGREADER_TOOL)
|
TEST_TOOL_NAME += $(PLREADER_TOOL) $(DBMSGREADER_TOOL)
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#define MAPISTORECALENDARWRAPPER_H
|
#define MAPISTORECALENDARWRAPPER_H
|
||||||
|
|
||||||
#import <NGCards/iCalPerson.h>
|
#import <NGCards/iCalPerson.h>
|
||||||
|
#import <NGCards/iCalTimeZone.h>
|
||||||
#import <Appointments/iCalEntityObject+SOGo.h>
|
#import <Appointments/iCalEntityObject+SOGo.h>
|
||||||
|
|
||||||
#import "MAPIStoreObjectProxy.h"
|
#import "MAPIStoreObjectProxy.h"
|
||||||
|
@ -42,7 +43,7 @@
|
||||||
iCalCalendar *calendar;
|
iCalCalendar *calendar;
|
||||||
iCalEvent *firstEvent;
|
iCalEvent *firstEvent;
|
||||||
iCalEvent *event;
|
iCalEvent *event;
|
||||||
NSTimeZone *timeZone;
|
iCalTimeZone *timeZone;
|
||||||
SOGoUser *user;
|
SOGoUser *user;
|
||||||
NSString *senderEmail;
|
NSString *senderEmail;
|
||||||
NSData *globalObjectId;
|
NSData *globalObjectId;
|
||||||
|
@ -57,12 +58,10 @@
|
||||||
+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent
|
+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent
|
||||||
andUser: (SOGoUser *) newUser
|
andUser: (SOGoUser *) newUser
|
||||||
andSenderEmail: (NSString *) newSenderEmail
|
andSenderEmail: (NSString *) newSenderEmail
|
||||||
inTimeZone: (NSTimeZone *) newTimeZone
|
|
||||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
|
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
|
||||||
- (id) initWithICalEvent: (iCalEvent *) newEvent
|
- (id) initWithICalEvent: (iCalEvent *) newEvent
|
||||||
andUser: (SOGoUser *) newUser
|
andUser: (SOGoUser *) newUser
|
||||||
andSenderEmail: (NSString *) newSenderEmail
|
andSenderEmail: (NSString *) newSenderEmail
|
||||||
inTimeZone: (NSTimeZone *) newTimeZone
|
|
||||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
|
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo;
|
||||||
|
|
||||||
/* getters */
|
/* getters */
|
||||||
|
|
|
@ -37,7 +37,9 @@
|
||||||
#import <NGCards/iCalEventChanges.h>
|
#import <NGCards/iCalEventChanges.h>
|
||||||
#import <NGCards/iCalPerson.h>
|
#import <NGCards/iCalPerson.h>
|
||||||
#import <NGCards/iCalTrigger.h>
|
#import <NGCards/iCalTrigger.h>
|
||||||
|
#import <NGCards/iCalTimeZonePeriod.h>
|
||||||
#import <NGCards/NSString+NGCards.h>
|
#import <NGCards/NSString+NGCards.h>
|
||||||
|
#import <SOGo/SOGoDomainDefaults.h>
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
#import <SOGo/SOGoUserManager.h>
|
#import <SOGo/SOGoUserManager.h>
|
||||||
|
|
||||||
|
@ -80,7 +82,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent
|
+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent
|
||||||
andUser: (SOGoUser *) newUser
|
andUser: (SOGoUser *) newUser
|
||||||
andSenderEmail: (NSString *) newSenderEmail
|
andSenderEmail: (NSString *) newSenderEmail
|
||||||
inTimeZone: (NSTimeZone *) newTimeZone
|
|
||||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
||||||
{
|
{
|
||||||
MAPIStoreAppointmentWrapper *wrapper;
|
MAPIStoreAppointmentWrapper *wrapper;
|
||||||
|
@ -88,7 +89,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
wrapper = [[self alloc] initWithICalEvent: newEvent
|
wrapper = [[self alloc] initWithICalEvent: newEvent
|
||||||
andUser: newUser
|
andUser: newUser
|
||||||
andSenderEmail: newSenderEmail
|
andSenderEmail: newSenderEmail
|
||||||
inTimeZone: newTimeZone
|
|
||||||
withConnectionInfo: newConnInfo];
|
withConnectionInfo: newConnInfo];
|
||||||
[wrapper autorelease];
|
[wrapper autorelease];
|
||||||
|
|
||||||
|
@ -182,10 +182,10 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
- (id) initWithICalEvent: (iCalEvent *) newEvent
|
- (id) initWithICalEvent: (iCalEvent *) newEvent
|
||||||
andUser: (SOGoUser *) newUser
|
andUser: (SOGoUser *) newUser
|
||||||
andSenderEmail: (NSString *) newSenderEmail
|
andSenderEmail: (NSString *) newSenderEmail
|
||||||
inTimeZone: (NSTimeZone *) newTimeZone
|
|
||||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
||||||
{
|
{
|
||||||
NSArray *events;
|
NSArray *events;
|
||||||
|
iCalTimeZone *tz;
|
||||||
|
|
||||||
if ((self = [self init]))
|
if ((self = [self init]))
|
||||||
{
|
{
|
||||||
|
@ -194,9 +194,20 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
event = newEvent;
|
event = newEvent;
|
||||||
events = [calendar events];
|
events = [calendar events];
|
||||||
firstEvent = [events objectAtIndex: 0];
|
firstEvent = [events objectAtIndex: 0];
|
||||||
ASSIGN (timeZone, newTimeZone);
|
|
||||||
ASSIGN (user, newUser);
|
ASSIGN (user, newUser);
|
||||||
ASSIGN (senderEmail, newSenderEmail);
|
ASSIGN (senderEmail, newSenderEmail);
|
||||||
|
/* If newEvent comes from the client, we set its time zone in
|
||||||
|
updateFromMAPIProperties. If it is not present, we use the
|
||||||
|
time zone of the user */
|
||||||
|
tz = (iCalTimeZone *) [calendar firstChildWithTag: @"vtimezone"];
|
||||||
|
if (!tz)
|
||||||
|
{
|
||||||
|
tz = [iCalTimeZone timeZoneForName: [[[user userDefaults] timeZone] name]];
|
||||||
|
if (!tz)
|
||||||
|
[self logWithFormat: @"no time zone could be set"];
|
||||||
|
}
|
||||||
|
ASSIGN (timeZone, tz);
|
||||||
|
|
||||||
[self _setupITIPContext];
|
[self _setupITIPContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +277,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
{
|
{
|
||||||
username = [contactInfos objectForKey: @"sAMAccountName"];
|
username = [contactInfos objectForKey: @"sAMAccountName"];
|
||||||
recipient->username = [username asUnicodeInMemCtx: msgData];
|
recipient->username = [username asUnicodeInMemCtx: msgData];
|
||||||
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, username);
|
entryId = MAPIStoreInternalEntryId (connInfo, username);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -367,7 +378,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
{
|
{
|
||||||
username = [contactInfos objectForKey: @"sAMAccountName"];
|
username = [contactInfos objectForKey: @"sAMAccountName"];
|
||||||
recipient->username = [username asUnicodeInMemCtx: msgData];
|
recipient->username = [username asUnicodeInMemCtx: msgData];
|
||||||
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, username);
|
entryId = MAPIStoreInternalEntryId (connInfo, username);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -721,20 +732,13 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
NSCalendarDate *dateValue;
|
NSCalendarDate *dateValue;
|
||||||
NSInteger offset;
|
|
||||||
|
|
||||||
// if ([event isRecurrent])
|
// if ([event isRecurrent])
|
||||||
// dateValue = [event firstRecurrenceStartDate];
|
// dateValue = [event firstRecurrenceStartDate];
|
||||||
// else
|
// else
|
||||||
dateValue = [event startDate];
|
dateValue = [event startDate];
|
||||||
if ([event isAllDay])
|
if ([event isAllDay])
|
||||||
{
|
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||||
offset = -[timeZone secondsFromGMTForDate: dateValue];
|
|
||||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
|
||||||
hours: 0 minutes: 0
|
|
||||||
seconds: offset];
|
|
||||||
}
|
|
||||||
[dateValue setTimeZone: utcTZ];
|
|
||||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
|
@ -749,20 +753,12 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
exceptions, where it is the normal start date for the day of the
|
exceptions, where it is the normal start date for the day of the
|
||||||
exception. */
|
exception. */
|
||||||
NSCalendarDate *dateValue;
|
NSCalendarDate *dateValue;
|
||||||
NSInteger offset;
|
|
||||||
|
|
||||||
dateValue = [event recurrenceId];
|
dateValue = [event recurrenceId];
|
||||||
if (!dateValue)
|
if (!dateValue)
|
||||||
dateValue = [event startDate];
|
dateValue = [event startDate];
|
||||||
[dateValue setTimeZone: timeZone];
|
|
||||||
if ([event isAllDay])
|
if ([event isAllDay])
|
||||||
{
|
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||||
offset = -[timeZone secondsFromGMTForDate: dateValue];
|
|
||||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
|
||||||
hours: 0 minutes: 0
|
|
||||||
seconds: offset];
|
|
||||||
}
|
|
||||||
[dateValue setTimeZone: utcTZ];
|
|
||||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
|
@ -772,17 +768,10 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
NSCalendarDate *dateValue;
|
NSCalendarDate *dateValue;
|
||||||
NSInteger offset;
|
|
||||||
|
|
||||||
dateValue = [firstEvent startDate];
|
dateValue = [firstEvent startDate];
|
||||||
if ([firstEvent isAllDay])
|
if ([firstEvent isAllDay])
|
||||||
{
|
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||||
offset = -[timeZone secondsFromGMTForDate: dateValue];
|
|
||||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
|
||||||
hours: 0 minutes: 0
|
|
||||||
seconds: offset];
|
|
||||||
}
|
|
||||||
[dateValue setTimeZone: utcTZ];
|
|
||||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
|
@ -804,8 +793,8 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
month: [start monthOfYear]
|
month: [start monthOfYear]
|
||||||
day: [start dayOfMonth]
|
day: [start dayOfMonth]
|
||||||
hour: 0 minute: 0 second: 0
|
hour: 0 minute: 0 second: 0
|
||||||
timeZone: timeZone];
|
timeZone: utcTZ];
|
||||||
[dateValue setTimeZone: utcTZ];
|
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||||
rc = MAPISTORE_SUCCESS;
|
rc = MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -829,7 +818,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
dateValue = [event startDate];
|
dateValue = [event startDate];
|
||||||
offset = [event durationAsTimeInterval];
|
offset = [event durationAsTimeInterval];
|
||||||
if ([event isAllDay])
|
if ([event isAllDay])
|
||||||
offset -= [timeZone secondsFromGMTForDate: dateValue];
|
offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT];
|
||||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||||
hours: 0 minutes: 0
|
hours: 0 minutes: 0
|
||||||
seconds: offset];
|
seconds: offset];
|
||||||
|
@ -847,10 +836,9 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
dateValue = [event recurrenceId];
|
dateValue = [event recurrenceId];
|
||||||
if (!dateValue)
|
if (!dateValue)
|
||||||
dateValue = [event startDate];
|
dateValue = [event startDate];
|
||||||
[dateValue setTimeZone: timeZone];
|
|
||||||
offset = [firstEvent durationAsTimeInterval];
|
offset = [firstEvent durationAsTimeInterval];
|
||||||
if ([firstEvent isAllDay])
|
if ([firstEvent isAllDay])
|
||||||
offset -= [timeZone secondsFromGMTForDate: dateValue];
|
offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT];
|
||||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||||
hours: 0 minutes: 0
|
hours: 0 minutes: 0
|
||||||
seconds: offset];
|
seconds: offset];
|
||||||
|
@ -871,7 +859,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
dateValue = [firstEvent startDate];
|
dateValue = [firstEvent startDate];
|
||||||
offset = [firstEvent durationAsTimeInterval];
|
offset = [firstEvent durationAsTimeInterval];
|
||||||
if ([event isAllDay])
|
if ([event isAllDay])
|
||||||
offset -= [timeZone secondsFromGMTForDate: dateValue];
|
offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT];
|
||||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
||||||
hours: 0 minutes: 0
|
hours: 0 minutes: 0
|
||||||
seconds: offset];
|
seconds: offset];
|
||||||
|
@ -885,23 +873,14 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
{
|
{
|
||||||
enum mapistore_error rc;
|
enum mapistore_error rc;
|
||||||
NSCalendarDate *dateValue;
|
NSCalendarDate *dateValue;
|
||||||
NSInteger offset;
|
|
||||||
iCalRecurrenceRule *rrule;
|
iCalRecurrenceRule *rrule;
|
||||||
|
|
||||||
if ([event isRecurrent])
|
if ([event isRecurrent])
|
||||||
{
|
{
|
||||||
rrule = [[event recurrenceRules] objectAtIndex: 0];
|
rrule = [[event recurrenceRules] objectAtIndex: 0];
|
||||||
dateValue = [rrule untilDate];
|
dateValue = [rrule untilDate];
|
||||||
if (dateValue)
|
if (dateValue && [event isAllDay])
|
||||||
{
|
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||||
if ([event isAllDay])
|
|
||||||
offset = -[timeZone secondsFromGMTForDate: dateValue];
|
|
||||||
else
|
|
||||||
offset = 0;
|
|
||||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
|
||||||
hours: 0 minutes: 0
|
|
||||||
seconds: offset];
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
dateValue = [NSCalendarDate dateWithYear: 4500 month: 8 day: 31
|
dateValue = [NSCalendarDate dateWithYear: 4500 month: 8 day: 31
|
||||||
hour: 23 minute: 59 second: 00
|
hour: 23 minute: 59 second: 00
|
||||||
|
@ -932,7 +911,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
if (contactInfos)
|
if (contactInfos)
|
||||||
{
|
{
|
||||||
username = [contactInfos objectForKey: @"sAMAccountName"];
|
username = [contactInfos objectForKey: @"sAMAccountName"];
|
||||||
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, username);
|
entryId = MAPIStoreInternalEntryId (connInfo, username);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
entryId = MAPIStoreExternalEntryId (cn, email);
|
entryId = MAPIStoreExternalEntryId (cn, email);
|
||||||
|
@ -1338,7 +1317,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
{
|
{
|
||||||
enum mapistore_error rc;
|
enum mapistore_error rc;
|
||||||
NSCalendarDate *dateValue;
|
NSCalendarDate *dateValue;
|
||||||
NSInteger offset;
|
|
||||||
|
|
||||||
dateValue = [event recurrenceId];
|
dateValue = [event recurrenceId];
|
||||||
if (dateValue)
|
if (dateValue)
|
||||||
|
@ -1346,13 +1324,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
rc = MAPISTORE_SUCCESS;
|
rc = MAPISTORE_SUCCESS;
|
||||||
|
|
||||||
if ([event isAllDay])
|
if ([event isAllDay])
|
||||||
{
|
dateValue = [timeZone shiftedCalendarDateForDate: dateValue];
|
||||||
offset = -[timeZone secondsFromGMTForDate: dateValue];
|
|
||||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
|
||||||
hours: 0 minutes: 0
|
|
||||||
seconds: offset];
|
|
||||||
}
|
|
||||||
[dateValue setTimeZone: utcTZ];
|
|
||||||
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
*data = [dateValue asFileTimeInMemCtx: memCtx];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1377,7 +1349,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
iCalEventChanges *changes;
|
iCalEventChanges *changes;
|
||||||
NSArray *changedProperties;
|
NSArray *changedProperties;
|
||||||
NSCalendarDate *dateValue;
|
NSCalendarDate *dateValue;
|
||||||
NSInteger offset;
|
|
||||||
|
|
||||||
changes = [iCalEventChanges changesFromEvent: event toEvent: exceptionEvent];
|
changes = [iCalEventChanges changesFromEvent: event toEvent: exceptionEvent];
|
||||||
|
|
||||||
|
@ -1385,28 +1356,17 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
memset (extendedException, 0, sizeof (struct ExtendedException));
|
memset (extendedException, 0, sizeof (struct ExtendedException));
|
||||||
extendedException->ChangeHighlight.Size = sizeof (uint32_t);
|
extendedException->ChangeHighlight.Size = sizeof (uint32_t);
|
||||||
|
|
||||||
dateValue = [exceptionEvent startDate];
|
dateValue = [timeZone computedDateForDate: [exceptionEvent startDate]];
|
||||||
offset = [timeZone secondsFromGMTForDate: dateValue];
|
|
||||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
|
||||||
hours: 0 minutes: 0
|
|
||||||
seconds: offset];
|
|
||||||
exceptionInfo->StartDateTime = [dateValue asMinutesSince1601];
|
exceptionInfo->StartDateTime = [dateValue asMinutesSince1601];
|
||||||
extendedException->ChangeHighlight.Value = BIT_CH_START;
|
extendedException->ChangeHighlight.Value = BIT_CH_START;
|
||||||
extendedException->StartDateTime = exceptionInfo->StartDateTime;
|
extendedException->StartDateTime = exceptionInfo->StartDateTime;
|
||||||
|
|
||||||
dateValue = [exceptionEvent endDate];
|
dateValue = [timeZone computedDateForDate: [exceptionEvent endDate]];
|
||||||
offset = [timeZone secondsFromGMTForDate: dateValue];
|
|
||||||
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
|
|
||||||
hours: 0 minutes: 0
|
|
||||||
seconds: offset];
|
|
||||||
exceptionInfo->EndDateTime = [dateValue asMinutesSince1601];
|
exceptionInfo->EndDateTime = [dateValue asMinutesSince1601];
|
||||||
extendedException->ChangeHighlight.Value |= BIT_CH_END;
|
extendedException->ChangeHighlight.Value |= BIT_CH_END;
|
||||||
extendedException->EndDateTime = exceptionInfo->EndDateTime;
|
extendedException->EndDateTime = exceptionInfo->EndDateTime;
|
||||||
|
|
||||||
dateValue = [[exceptionEvent recurrenceId]
|
dateValue = [timeZone computedDateForDate: [exceptionEvent recurrenceId]];
|
||||||
dateByAddingYears: 0 months: 0 days: 0
|
|
||||||
hours: 0 minutes: 0
|
|
||||||
seconds: offset];
|
|
||||||
exceptionInfo->OriginalStartDate = [dateValue asMinutesSince1601];
|
exceptionInfo->OriginalStartDate = [dateValue asMinutesSince1601];
|
||||||
extendedException->OriginalStartDate = exceptionInfo->OriginalStartDate;
|
extendedException->OriginalStartDate = exceptionInfo->OriginalStartDate;
|
||||||
|
|
||||||
|
@ -1464,7 +1424,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
arp = talloc_zero (NULL, struct AppointmentRecurrencePattern);
|
arp = talloc_zero (NULL, struct AppointmentRecurrencePattern);
|
||||||
[rule fillRecurrencePattern: &arp->RecurrencePattern
|
[rule fillRecurrencePattern: &arp->RecurrencePattern
|
||||||
withEvent: event
|
withEvent: event
|
||||||
inTimeZone: timeZone
|
|
||||||
inMemCtx: arp];
|
inMemCtx: arp];
|
||||||
arp->ReaderVersion2 = 0x00003006;
|
arp->ReaderVersion2 = 0x00003006;
|
||||||
arp->WriterVersion2 = 0x00003008; /* 0x3008 for compatibility with
|
arp->WriterVersion2 = 0x00003008; /* 0x3008 for compatibility with
|
||||||
|
@ -1475,7 +1434,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
fields are relative to midnight of those days ([MS-OXOCAL] 2.2.1.44.5),
|
fields are relative to midnight of those days ([MS-OXOCAL] 2.2.1.44.5),
|
||||||
so no time zone adjustment is needed */
|
so no time zone adjustment is needed */
|
||||||
if (![event isAllDay])
|
if (![event isAllDay])
|
||||||
[firstStartDate setTimeZone: timeZone];
|
firstStartDate = [timeZone computedDateForDate: firstStartDate];
|
||||||
startMinutes = ([firstStartDate hourOfDay] * 60
|
startMinutes = ([firstStartDate hourOfDay] * 60
|
||||||
+ [firstStartDate minuteOfHour]);
|
+ [firstStartDate minuteOfHour]);
|
||||||
arp->StartTimeOffset = startMinutes;
|
arp->StartTimeOffset = startMinutes;
|
||||||
|
@ -1701,15 +1660,16 @@ ReservedBlockEE2Size: 00 00 00 00
|
||||||
fromDate: (NSCalendarDate *) instanceDate;
|
fromDate: (NSCalendarDate *) instanceDate;
|
||||||
{
|
{
|
||||||
uint16_t year;
|
uint16_t year;
|
||||||
|
NSCalendarDate *dateValue;
|
||||||
|
|
||||||
if (instanceDate)
|
if (instanceDate)
|
||||||
{
|
{
|
||||||
[instanceDate setTimeZone: timeZone];
|
dateValue = [timeZone computedDateForDate: instanceDate];
|
||||||
year = [instanceDate yearOfCommonEra];
|
year = [dateValue yearOfCommonEra];
|
||||||
newGlobalId->YH = year >> 8;
|
newGlobalId->YH = year >> 8;
|
||||||
newGlobalId->YL = year & 0xff;
|
newGlobalId->YL = year & 0xff;
|
||||||
newGlobalId->Month = [instanceDate monthOfYear];
|
newGlobalId->Month = [dateValue monthOfYear];
|
||||||
newGlobalId->D = [instanceDate dayOfMonth];
|
newGlobalId->D = [dateValue dayOfMonth];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1974,7 +1934,6 @@ ReservedBlockEE2Size: 00 00 00 00
|
||||||
if (alarm)
|
if (alarm)
|
||||||
{
|
{
|
||||||
alarmDate = [alarm nextAlarmDate];
|
alarmDate = [alarm nextAlarmDate];
|
||||||
[alarmDate setTimeZone: utcTZ];
|
|
||||||
*data = [alarmDate asFileTimeInMemCtx: memCtx];
|
*data = [alarmDate asFileTimeInMemCtx: memCtx];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2036,8 +1995,7 @@ ReservedBlockEE2Size: 00 00 00 00
|
||||||
enum mapistore_error rc;
|
enum mapistore_error rc;
|
||||||
NSString *tzid;
|
NSString *tzid;
|
||||||
|
|
||||||
tzid = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"]
|
tzid = [timeZone tzId];
|
||||||
value: 0 ofAttribute: @"tzid"];
|
|
||||||
if ([tzid length] > 0)
|
if ([tzid length] > 0)
|
||||||
{
|
{
|
||||||
*data = [tzid asUnicodeInMemCtx: memCtx];
|
*data = [tzid asUnicodeInMemCtx: memCtx];
|
||||||
|
@ -2053,16 +2011,9 @@ ReservedBlockEE2Size: 00 00 00 00
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
enum mapistore_error rc;
|
enum mapistore_error rc;
|
||||||
iCalTimeZone *icalTZ;
|
|
||||||
|
|
||||||
icalTZ = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"] timeZone];
|
*data = [timeZone asTimeZoneStructInMemCtx: memCtx];
|
||||||
if (icalTZ)
|
rc = MAPISTORE_SUCCESS;
|
||||||
{
|
|
||||||
*data = [icalTZ asTimeZoneStructInMemCtx: memCtx];
|
|
||||||
rc = MAPISTORE_SUCCESS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -2071,24 +2022,16 @@ ReservedBlockEE2Size: 00 00 00 00
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
enum mapistore_error rc;
|
enum mapistore_error rc;
|
||||||
iCalTimeZone *icalTZ;
|
|
||||||
|
|
||||||
/* [MS-OXOCAL] 3.1.5.5.1: This property is used in floating (all-day) events,
|
/* [MS-OXOCAL] 3.1.5.5.1: This property is used in floating (all-day) events,
|
||||||
specified in floating time, to convert the start date from UTC to the user's
|
specified in floating time, to convert the start date from UTC to the user's
|
||||||
time zone */
|
time zone */
|
||||||
if ([event isAllDay])
|
if ([event isAllDay] | [event isRecurrent])
|
||||||
icalTZ = [iCalTimeZone timeZoneForName: [timeZone timeZoneName]];
|
|
||||||
else if ([event isRecurrent])
|
|
||||||
icalTZ = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"] timeZone];
|
|
||||||
else
|
|
||||||
icalTZ = nil;
|
|
||||||
|
|
||||||
if (icalTZ)
|
|
||||||
{
|
{
|
||||||
/* [MS-OXOCAL] 2.2.1.42: This property can only have the E flag set in the
|
/* [MS-OXOCAL] 2.2.1.42: This property can only have the E flag set in the
|
||||||
TimeZoneDefinition struct */
|
TimeZoneDefinition struct */
|
||||||
*data = [icalTZ asZoneTimeDefinitionWithFlags: TZRULE_FLAG_EFFECTIVE_TZREG
|
*data = [timeZone asZoneTimeDefinitionWithFlags: TZRULE_FLAG_EFFECTIVE_TZREG
|
||||||
inMemCtx: memCtx];
|
inMemCtx: memCtx];
|
||||||
rc = MAPISTORE_SUCCESS;
|
rc = MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -58,7 +58,6 @@
|
||||||
wrapperWithICalEvent: [newContainer event]
|
wrapperWithICalEvent: [newContainer event]
|
||||||
andUser: [userContext sogoUser]
|
andUser: [userContext sogoUser]
|
||||||
andSenderEmail: nil
|
andSenderEmail: nil
|
||||||
inTimeZone: [userContext timeZone]
|
|
||||||
withConnectionInfo: [context connectionInfo]];
|
withConnectionInfo: [context connectionInfo]];
|
||||||
[self addProxy: appointmentWrapper];
|
[self addProxy: appointmentWrapper];
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,11 +117,11 @@
|
||||||
if ([roles containsObject: SOGoRole_ObjectCreator])
|
if ([roles containsObject: SOGoRole_ObjectCreator])
|
||||||
rights |= RightsCreateItems;
|
rights |= RightsCreateItems;
|
||||||
if ([roles containsObject: SOGoRole_ObjectEraser])
|
if ([roles containsObject: SOGoRole_ObjectEraser])
|
||||||
rights |= RightsDeleteAll;
|
rights |= RightsDeleteAll | RightsDeleteOwn;
|
||||||
if ([roles containsObject: SOGoCalendarRole_PublicModifier]
|
if ([roles containsObject: SOGoCalendarRole_PublicModifier]
|
||||||
&& [roles containsObject: SOGoCalendarRole_PrivateModifier]
|
&& [roles containsObject: SOGoCalendarRole_PrivateModifier]
|
||||||
&& [roles containsObject: SOGoCalendarRole_ConfidentialModifier])
|
&& [roles containsObject: SOGoCalendarRole_ConfidentialModifier])
|
||||||
rights |= RightsReadItems | RightsEditAll;
|
rights |= RightsReadItems | RightsEditAll | RightsEditOwn;
|
||||||
else if ([roles containsObject: SOGoCalendarRole_PublicViewer]
|
else if ([roles containsObject: SOGoCalendarRole_PublicViewer]
|
||||||
&& [roles containsObject: SOGoCalendarRole_PrivateViewer]
|
&& [roles containsObject: SOGoCalendarRole_PrivateViewer]
|
||||||
&& [roles containsObject: SOGoCalendarRole_ConfidentialViewer])
|
&& [roles containsObject: SOGoCalendarRole_ConfidentialViewer])
|
||||||
|
|
|
@ -197,7 +197,6 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK;
|
||||||
= [MAPIStoreAppointmentWrapper wrapperWithICalEvent: masterEvent
|
= [MAPIStoreAppointmentWrapper wrapperWithICalEvent: masterEvent
|
||||||
andUser: [userContext sogoUser]
|
andUser: [userContext sogoUser]
|
||||||
andSenderEmail: nil
|
andSenderEmail: nil
|
||||||
inTimeZone: [userContext timeZone]
|
|
||||||
withConnectionInfo: [context connectionInfo]];
|
withConnectionInfo: [context connectionInfo]];
|
||||||
[self addProxy: appointmentWrapper];
|
[self addProxy: appointmentWrapper];
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,9 +96,9 @@
|
||||||
if ([roles containsObject: SOGoRole_ObjectCreator])
|
if ([roles containsObject: SOGoRole_ObjectCreator])
|
||||||
rights |= RightsCreateItems;
|
rights |= RightsCreateItems;
|
||||||
if ([roles containsObject: SOGoRole_ObjectEraser])
|
if ([roles containsObject: SOGoRole_ObjectEraser])
|
||||||
rights |= RightsDeleteAll;
|
rights |= RightsDeleteAll | RightsDeleteOwn;
|
||||||
if ([roles containsObject: SOGoRole_ObjectEditor])
|
if ([roles containsObject: SOGoRole_ObjectEditor])
|
||||||
rights |= RightsEditAll;
|
rights |= RightsEditAll | RightsEditOwn;
|
||||||
if ([roles containsObject: SOGoRole_ObjectViewer])
|
if ([roles containsObject: SOGoRole_ObjectViewer])
|
||||||
rights |= RightsReadItems;
|
rights |= RightsReadItems;
|
||||||
if (rights != 0)
|
if (rights != 0)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -102,7 +102,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||||
{
|
{
|
||||||
value = get_SPropValue_SRow (aRow, PidTagDisplayName_string8);
|
value = get_SPropValue_SRow (aRow, PidTagDisplayName_string8);
|
||||||
if (value)
|
if (value)
|
||||||
folderName = [NSString stringWithUTF8String: value->value.lpszA];
|
folderName = [NSString stringWithUTF8String: (const char *) value->value.lpszA];
|
||||||
else
|
else
|
||||||
folderName = nil;
|
folderName = nil;
|
||||||
}
|
}
|
||||||
|
@ -321,9 +321,9 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||||
if ([roles containsObject: MAPIStoreRightDeleteOwn])
|
if ([roles containsObject: MAPIStoreRightDeleteOwn])
|
||||||
rights |= RightsDeleteOwn;
|
rights |= RightsDeleteOwn;
|
||||||
if ([roles containsObject: MAPIStoreRightEditAll])
|
if ([roles containsObject: MAPIStoreRightEditAll])
|
||||||
rights |= RightsEditAll;
|
rights |= RightsEditAll | RightsEditOwn;
|
||||||
if ([roles containsObject: MAPIStoreRightDeleteAll])
|
if ([roles containsObject: MAPIStoreRightDeleteAll])
|
||||||
rights |= RightsDeleteAll;
|
rights |= RightsDeleteAll | RightsDeleteOwn;
|
||||||
if ([roles containsObject: MAPIStoreRightCreateSubfolders])
|
if ([roles containsObject: MAPIStoreRightCreateSubfolders])
|
||||||
rights |= RightsCreateSubfolders;
|
rights |= RightsCreateSubfolders;
|
||||||
if ([roles containsObject: MAPIStoreRightFolderOwner])
|
if ([roles containsObject: MAPIStoreRightFolderOwner])
|
||||||
|
|
|
@ -109,18 +109,70 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) description
|
||||||
|
{
|
||||||
|
id key, value;
|
||||||
|
NSEnumerator *propEnumerator;
|
||||||
|
NSMutableString *description;
|
||||||
|
|
||||||
|
description = [NSMutableString stringWithFormat: @"%@ %@. Properties: {", NSStringFromClass ([self class]),
|
||||||
|
[self url]];
|
||||||
|
|
||||||
|
propEnumerator = [properties keyEnumerator];
|
||||||
|
while ((key = [propEnumerator nextObject]))
|
||||||
|
{
|
||||||
|
uint32_t proptag = 0;
|
||||||
|
if ([key isKindOfClass: [NSString class]] && [(NSString *)key intValue] > 0)
|
||||||
|
proptag = [(NSString *)key intValue];
|
||||||
|
else if ([key isKindOfClass: [NSNumber class]])
|
||||||
|
proptag = [key unsignedLongValue];
|
||||||
|
|
||||||
|
if (proptag > 0)
|
||||||
|
{
|
||||||
|
const char *propTagName = get_proptag_name ([key unsignedLongValue]);
|
||||||
|
NSString *propName;
|
||||||
|
|
||||||
|
if (propTagName)
|
||||||
|
propName = [NSString stringWithCString: propTagName
|
||||||
|
encoding: NSUTF8StringEncoding];
|
||||||
|
else
|
||||||
|
propName = [NSString stringWithFormat: @"0x%.4x", [key unsignedLongValue]];
|
||||||
|
|
||||||
|
[description appendFormat: @"'%@': ", propName];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[description appendFormat: @"'%@': ", key];
|
||||||
|
|
||||||
|
value = [properties objectForKey: key];
|
||||||
|
[description appendFormat: @"%@ (%@), ", value, NSStringFromClass ([value class])];
|
||||||
|
}
|
||||||
|
|
||||||
|
[description appendString: @"}\n"];
|
||||||
|
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
- (uint64_t) objectVersion
|
- (uint64_t) objectVersion
|
||||||
{
|
{
|
||||||
NSNumber *versionNbr;
|
/* Return the global counter from CN structure.
|
||||||
|
See [MS-OXCFXICS] Section 2.2.2.1 */
|
||||||
|
NSNumber *versionNbr, *cn;
|
||||||
uint64_t objectVersion;
|
uint64_t objectVersion;
|
||||||
|
|
||||||
[(SOGoMAPIDBMessage *) sogoObject reloadIfNeeded];
|
[(SOGoMAPIDBMessage *) sogoObject reloadIfNeeded];
|
||||||
versionNbr = [properties objectForKey: @"version"];
|
versionNbr = [properties objectForKey: @"version_number"];
|
||||||
if (versionNbr)
|
if (versionNbr)
|
||||||
objectVersion = (([versionNbr unsignedLongLongValue] >> 16)
|
objectVersion = exchange_globcnt ([versionNbr unsignedLongLongValue]);
|
||||||
& 0x0000ffffffffffffLL);
|
|
||||||
else
|
else
|
||||||
objectVersion = ULLONG_MAX;
|
{
|
||||||
|
/* Old version which stored the CN structure not useful for searching */
|
||||||
|
cn = [properties objectForKey: @"version"];
|
||||||
|
if (cn)
|
||||||
|
objectVersion = (([cn unsignedLongLongValue] >> 16)
|
||||||
|
& 0x0000ffffffffffffLL);
|
||||||
|
else
|
||||||
|
objectVersion = ULLONG_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
return objectVersion;
|
return objectVersion;
|
||||||
}
|
}
|
||||||
|
@ -283,13 +335,19 @@
|
||||||
[properties setObject: attachmentParts forKey: @"attachments"];
|
[properties setObject: attachmentParts forKey: @"attachments"];
|
||||||
|
|
||||||
newVersion = [[self context] getNewChangeNumber];
|
newVersion = [[self context] getNewChangeNumber];
|
||||||
|
newVersion = exchange_globcnt ((newVersion >> 16) & 0x0000ffffffffffffLL);
|
||||||
|
|
||||||
[properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion]
|
[properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion]
|
||||||
forKey: @"version"];
|
forKey: @"version_number"];
|
||||||
|
|
||||||
|
/* Remove old version */
|
||||||
|
[properties removeObjectForKey: @"version"];
|
||||||
|
|
||||||
/* Update PredecessorChangeList accordingly */
|
/* Update PredecessorChangeList accordingly */
|
||||||
[self _updatePredecessorChangeList];
|
[self _updatePredecessorChangeList];
|
||||||
|
|
||||||
[self logWithFormat: @"%d props in dict", [properties count]];
|
// [self logWithFormat: @"Saving %@", [self description]];
|
||||||
|
// [self logWithFormat: @"%d props in dict", [properties count]];
|
||||||
|
|
||||||
[sogoObject save];
|
[sogoObject save];
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,14 +61,15 @@ static Class MAPIStoreDBMessageK = Nil;
|
||||||
|
|
||||||
if ((uint32_t) res->ulPropTag == PidTagChangeNumber)
|
if ((uint32_t) res->ulPropTag == PidTagChangeNumber)
|
||||||
{
|
{
|
||||||
|
SEL operator;
|
||||||
|
|
||||||
value = NSObjectFromMAPISPropValue (&res->lpProp);
|
value = NSObjectFromMAPISPropValue (&res->lpProp);
|
||||||
cVersion = exchange_globcnt (([value unsignedLongLongValue] >> 16)
|
cVersion = exchange_globcnt (([value unsignedLongLongValue] >> 16)
|
||||||
& 0x0000ffffffffffffLL);
|
& 0x0000ffffffffffffLL);
|
||||||
version = [NSNumber numberWithUnsignedLongLong: cVersion];
|
version = [NSNumber numberWithUnsignedLongLong: cVersion];
|
||||||
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
|
operator = [self operatorFromRestrictionOperator: res->relop];
|
||||||
[self logWithFormat: @" version: %.16lx", cVersion];
|
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version_number"
|
||||||
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version"
|
operatorSelector: operator
|
||||||
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
|
|
||||||
value: version];
|
value: version];
|
||||||
[*qualifier autorelease];
|
[*qualifier autorelease];
|
||||||
rc = MAPIRestrictionStateNeedsEval;
|
rc = MAPIRestrictionStateNeedsEval;
|
||||||
|
|
|
@ -1549,7 +1549,6 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
struct Binary_r bin32;
|
struct Binary_r bin32;
|
||||||
struct AddressBookEntryId *entryId;
|
struct AddressBookEntryId *entryId;
|
||||||
NSString *username;
|
NSString *username;
|
||||||
struct ldb_context *samCtx;
|
|
||||||
|
|
||||||
if (bin && bin->cb)
|
if (bin && bin->cb)
|
||||||
{
|
{
|
||||||
|
@ -1559,8 +1558,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
entryId = get_AddressBookEntryId (NULL, &bin32);
|
entryId = get_AddressBookEntryId (NULL, &bin32);
|
||||||
if (entryId)
|
if (entryId)
|
||||||
{
|
{
|
||||||
samCtx = [[self context] connectionInfo]->sam_ctx;
|
username = MAPIStoreSamDBUserAttribute ([[self context] connectionInfo],
|
||||||
username = MAPIStoreSamDBUserAttribute (samCtx, @"legacyExchangeDN",
|
@"legacyExchangeDN",
|
||||||
[NSString stringWithUTF8String: entryId->X500DN],
|
[NSString stringWithUTF8String: entryId->X500DN],
|
||||||
@"sAMAccountName");
|
@"sAMAccountName");
|
||||||
}
|
}
|
||||||
|
|
|
@ -681,12 +681,12 @@ static Class NSNumberK;
|
||||||
- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSString *) changeNumber
|
- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSString *) changeNumber
|
||||||
{
|
{
|
||||||
NSDictionary *mapping;
|
NSDictionary *mapping;
|
||||||
NSNumber *modseq;
|
NSNumber *lastModified;
|
||||||
|
|
||||||
mapping = [[versionsMessage properties] objectForKey: @"VersionMapping"];
|
mapping = [[versionsMessage properties] objectForKey: @"VersionMapping"];
|
||||||
modseq = [mapping objectForKey: changeNumber];
|
lastModified = [mapping objectForKey: changeNumber];
|
||||||
|
|
||||||
return modseq;
|
return lastModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) changeNumberForMessageWithKey: (NSString *) messageKey
|
- (NSString *) changeNumberForMessageWithKey: (NSString *) messageKey
|
||||||
|
|
|
@ -140,9 +140,16 @@
|
||||||
[parentFolder synchroniseCache];
|
[parentFolder synchroniseCache];
|
||||||
changeKey = [parentFolder changeKeyForMessageWithKey: nameInContainer];
|
changeKey = [parentFolder changeKeyForMessageWithKey: nameInContainer];
|
||||||
}
|
}
|
||||||
if (!changeKey)
|
if (changeKey)
|
||||||
abort ();
|
*data = [changeKey asBinaryInMemCtx: memCtx];
|
||||||
*data = [changeKey asBinaryInMemCtx: memCtx];
|
else
|
||||||
|
{
|
||||||
|
[self warnWithFormat: @"No change key for %@ in folder %@",
|
||||||
|
nameInContainer,
|
||||||
|
[parentFolder url]
|
||||||
|
];
|
||||||
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
|
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
#import <NGExtensions/NSObject+Values.h>
|
||||||
|
|
||||||
#import <EOControl/EOFetchSpecification.h>
|
#import <EOControl/EOFetchSpecification.h>
|
||||||
#import <EOControl/EOQualifier.h>
|
#import <EOControl/EOQualifier.h>
|
||||||
|
@ -38,7 +39,6 @@
|
||||||
|
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
#import "MAPIStoreGCSFolder.h"
|
#import "MAPIStoreGCSFolder.h"
|
||||||
|
|
||||||
#import "MAPIStoreGCSMessageTable.h"
|
#import "MAPIStoreGCSMessageTable.h"
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
@ -89,21 +89,31 @@
|
||||||
|
|
||||||
if (res->ulPropTag == PidTagChangeNumber)
|
if (res->ulPropTag == PidTagChangeNumber)
|
||||||
{
|
{
|
||||||
|
NSString *changeNumber;
|
||||||
|
|
||||||
value = NSObjectFromMAPISPropValue (&res->lpProp);
|
value = NSObjectFromMAPISPropValue (&res->lpProp);
|
||||||
|
changeNumber = [NSString stringWithUnsignedLongLong: [(NSNumber *)value unsignedLongLongValue]];
|
||||||
lastModified = [(MAPIStoreGCSFolder *)
|
lastModified = [(MAPIStoreGCSFolder *)
|
||||||
container lastModifiedFromMessageChangeNumber: value];
|
container lastModifiedFromMessageChangeNumber: changeNumber];
|
||||||
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
|
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
|
||||||
//[self logWithFormat: @" c_lastmodified: %@", lastModified];
|
//[self logWithFormat: @" c_lastmodified: %@", lastModified];
|
||||||
if (lastModified)
|
if (lastModified)
|
||||||
{
|
{
|
||||||
|
SEL operator;
|
||||||
|
|
||||||
|
operator = [self operatorFromRestrictionOperator: res->relop];
|
||||||
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_lastmodified"
|
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_lastmodified"
|
||||||
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
|
operatorSelector: operator
|
||||||
value: lastModified];
|
value: lastModified];
|
||||||
[*qualifier autorelease];
|
[*qualifier autorelease];
|
||||||
rc = MAPIRestrictionStateNeedsEval;
|
rc = MAPIRestrictionStateNeedsEval;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rc = MAPIRestrictionStateAlwaysTrue;
|
{
|
||||||
|
[self logWithFormat: @"No last modified found for: 0x%.16"PRIx64". Then no restriction applied",
|
||||||
|
[value unsignedLongLongValue]];
|
||||||
|
rc = MAPIRestrictionStateAlwaysTrue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,6 +74,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
|
||||||
#include <util/attr.h>
|
#include <util/attr.h>
|
||||||
#include <libmapi/libmapi.h>
|
#include <libmapi/libmapi.h>
|
||||||
#include <libmapiproxy.h>
|
#include <libmapiproxy.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <mapistore/mapistore.h>
|
#include <mapistore/mapistore.h>
|
||||||
#include <mapistore/mapistore_errors.h>
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
|
||||||
|
@ -181,7 +182,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
|
||||||
if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME_UNICODE)
|
if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME_UNICODE)
|
||||||
folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszW];
|
folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszW];
|
||||||
else if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME)
|
else if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME)
|
||||||
folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszA];
|
folderName = [NSString stringWithUTF8String: (const char *) aRow->lpProps[i].value.lpszA];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (folderName)
|
if (folderName)
|
||||||
|
@ -257,6 +258,67 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (EOQualifier *) simplifyQualifier: (EOQualifier *) qualifier
|
||||||
|
{
|
||||||
|
/* Hack: Reduce the number of MODSEQ constraints to a single one as
|
||||||
|
we assume the difference among MODSEQs will be small enough to
|
||||||
|
return a small number of UIDs.
|
||||||
|
|
||||||
|
This is the only case we do simplify:
|
||||||
|
MODSEQ >= x | MODSEQ >= y | MODSEQ >= z => MODSEQ >= min(x,y,z)
|
||||||
|
*/
|
||||||
|
if (qualifier && [qualifier isKindOfClass: [EOOrQualifier class]])
|
||||||
|
{
|
||||||
|
EOQualifier *simplifiedQualifier;
|
||||||
|
NSArray *quals;
|
||||||
|
NSNumber *minModseq;
|
||||||
|
NSUInteger i, count;
|
||||||
|
|
||||||
|
quals = [(EOOrQualifier *)qualifier qualifiers];
|
||||||
|
count = [quals count];
|
||||||
|
if (count < 2)
|
||||||
|
return qualifier;
|
||||||
|
|
||||||
|
minModseq = [NSNumber numberWithUnsignedLongLong: ULLONG_MAX];
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
EOQualifier *subQualifier;
|
||||||
|
|
||||||
|
subQualifier = [quals objectAtIndex: i];
|
||||||
|
if ([subQualifier isKindOfClass: [EOAndQualifier class]]
|
||||||
|
&& [[(EOAndQualifier *)subQualifier qualifiers] count] == 1)
|
||||||
|
subQualifier = [[(EOAndQualifier *)subQualifier qualifiers] objectAtIndex: 0];
|
||||||
|
|
||||||
|
if ([subQualifier isKindOfClass: [EOKeyValueQualifier class]]
|
||||||
|
&& [[(EOKeyValueQualifier *)subQualifier key] isEqualToString: @"MODSEQ"])
|
||||||
|
{
|
||||||
|
NSNumber *value;
|
||||||
|
|
||||||
|
value = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value];
|
||||||
|
if ([minModseq compare: value] == NSOrderedDescending
|
||||||
|
&& [value unsignedLongLongValue] > 0)
|
||||||
|
minModseq = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value];
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return qualifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([minModseq unsignedLongLongValue] > 0 && [minModseq unsignedLongLongValue] < ULLONG_MAX)
|
||||||
|
{
|
||||||
|
simplifiedQualifier = [[EOKeyValueQualifier alloc]
|
||||||
|
initWithKey: @"MODSEQ"
|
||||||
|
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
|
||||||
|
value: minModseq];
|
||||||
|
[simplifiedQualifier autorelease];
|
||||||
|
return simplifiedQualifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qualifier;
|
||||||
|
}
|
||||||
|
|
||||||
- (EOQualifier *) nonDeletedQualifier
|
- (EOQualifier *) nonDeletedQualifier
|
||||||
{
|
{
|
||||||
static EOQualifier *nonDeletedQualifier = nil;
|
static EOQualifier *nonDeletedQualifier = nil;
|
||||||
|
@ -281,7 +343,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
|
||||||
andSortOrderings: (NSArray *) sortOrderings
|
andSortOrderings: (NSArray *) sortOrderings
|
||||||
{
|
{
|
||||||
NSArray *uidKeys;
|
NSArray *uidKeys;
|
||||||
EOQualifier *fetchQualifier;
|
EOQualifier *fetchQualifier, *simplifiedQualifier;
|
||||||
|
|
||||||
if ([self ensureFolderExists])
|
if ([self ensureFolderExists])
|
||||||
{
|
{
|
||||||
|
@ -290,9 +352,10 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
|
||||||
|
|
||||||
if (qualifier)
|
if (qualifier)
|
||||||
{
|
{
|
||||||
|
simplifiedQualifier = [self simplifyQualifier: qualifier];
|
||||||
fetchQualifier
|
fetchQualifier
|
||||||
= [[EOAndQualifier alloc] initWithQualifiers:
|
= [[EOAndQualifier alloc] initWithQualifiers:
|
||||||
[self nonDeletedQualifier], qualifier,
|
[self nonDeletedQualifier], simplifiedQualifier,
|
||||||
nil];
|
nil];
|
||||||
[fetchQualifier autorelease];
|
[fetchQualifier autorelease];
|
||||||
}
|
}
|
||||||
|
@ -599,7 +662,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
|
||||||
uint64_t lastModseqNbr;
|
uint64_t lastModseqNbr;
|
||||||
EOQualifier *searchQualifier;
|
EOQualifier *searchQualifier;
|
||||||
NSArray *uids, *changeNumbers;
|
NSArray *uids, *changeNumbers;
|
||||||
NSUInteger count, max;
|
NSUInteger count, max, nFetched;
|
||||||
NSArray *fetchResults;
|
NSArray *fetchResults;
|
||||||
NSDictionary *result;
|
NSDictionary *result;
|
||||||
NSData *changeKey;
|
NSData *changeKey;
|
||||||
|
@ -678,6 +741,13 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
|
||||||
= [fetchResults sortedArrayUsingFunction: _compareFetchResultsByMODSEQ
|
= [fetchResults sortedArrayUsingFunction: _compareFetchResultsByMODSEQ
|
||||||
context: NULL];
|
context: NULL];
|
||||||
|
|
||||||
|
nFetched = [fetchResults count];
|
||||||
|
if (nFetched != max) {
|
||||||
|
[self errorWithFormat: @"Error fetching UIDs. Asked: %d Received: %d."
|
||||||
|
@"Check the IMAP conversation for details", max, nFetched];
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
for (count = 0; count < max; count++)
|
for (count = 0; count < max; count++)
|
||||||
{
|
{
|
||||||
result = [fetchResults objectAtIndex: count];
|
result = [fetchResults objectAtIndex: count];
|
||||||
|
@ -1641,10 +1711,10 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
||||||
rights |= RightsCreateItems;
|
rights |= RightsCreateItems;
|
||||||
if ([roles containsObject: SOGoRole_ObjectEraser]
|
if ([roles containsObject: SOGoRole_ObjectEraser]
|
||||||
&& [roles containsObject: SOGoRole_FolderEraser])
|
&& [roles containsObject: SOGoRole_FolderEraser])
|
||||||
rights |= RightsDeleteAll;
|
rights |= RightsDeleteAll | RightsDeleteOwn;
|
||||||
|
|
||||||
if ([roles containsObject: SOGoRole_ObjectEditor])
|
if ([roles containsObject: SOGoRole_ObjectEditor])
|
||||||
rights |= RightsEditAll;
|
rights |= RightsEditAll | RightsEditOwn;
|
||||||
if ([roles containsObject: SOGoRole_ObjectViewer])
|
if ([roles containsObject: SOGoRole_ObjectViewer])
|
||||||
rights |= RightsReadItems;
|
rights |= RightsReadItems;
|
||||||
if ([roles containsObject: SOGoRole_FolderCreator])
|
if ([roles containsObject: SOGoRole_FolderCreator])
|
||||||
|
|
|
@ -340,7 +340,6 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||||
wrapperWithICalEvent: event
|
wrapperWithICalEvent: event
|
||||||
andUser: [context activeUser]
|
andUser: [context activeUser]
|
||||||
andSenderEmail: senderEmail
|
andSenderEmail: senderEmail
|
||||||
inTimeZone: [[self userContext] timeZone]
|
|
||||||
withConnectionInfo: [context connectionInfo]];
|
withConnectionInfo: [context connectionInfo]];
|
||||||
[appointmentWrapper retain];
|
[appointmentWrapper retain];
|
||||||
}
|
}
|
||||||
|
@ -522,6 +521,9 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||||
NSUInteger colIdx;
|
NSUInteger colIdx;
|
||||||
NSString *stringValue;
|
NSString *stringValue;
|
||||||
|
|
||||||
|
/* As specified in [MS-OXCMAIL] 2.2.3.2.6.1, if there are three
|
||||||
|
or less characters followed by a colon at the beginning of
|
||||||
|
the subject, we can assume that's the subject prefix */
|
||||||
subject = [self subject];
|
subject = [self subject];
|
||||||
colIdx = [subject rangeOfString: @":"].location;
|
colIdx = [subject rangeOfString: @":"].location;
|
||||||
if (colIdx != NSNotFound && colIdx < 4)
|
if (colIdx != NSNotFound && colIdx < 4)
|
||||||
|
@ -537,17 +539,45 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||||
- (int) getPidTagNormalizedSubject: (void **) data
|
- (int) getPidTagNormalizedSubject: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
NSString *subject;
|
NSString *stringValue, *subject;
|
||||||
NSUInteger colIdx;
|
NSUInteger quoteStartIdx, quoteEndIdx, colIdx;
|
||||||
NSString *stringValue;
|
NSRange quoteRange;
|
||||||
|
|
||||||
|
if (!headerSetup)
|
||||||
|
[self _fetchHeaderData];
|
||||||
|
|
||||||
subject = [self subject];
|
subject = [self subject];
|
||||||
colIdx = [subject rangeOfString: @":"].location;
|
if (mailIsMeetingRequest)
|
||||||
if (colIdx != NSNotFound && colIdx < 4)
|
{
|
||||||
stringValue = [[subject substringFromIndex: colIdx + 1]
|
|
||||||
stringByTrimmingLeadSpaces];
|
/* SOGo "spices up" the invitation/update mail's subject, but
|
||||||
|
the client uses it to name the attendee's event, so we keep
|
||||||
|
only what's inside the quotes */
|
||||||
|
quoteStartIdx = [subject rangeOfString: @"\""].location;
|
||||||
|
quoteEndIdx = [subject rangeOfString: @"\""
|
||||||
|
options: NSBackwardsSearch].location;
|
||||||
|
if (quoteStartIdx != NSNotFound
|
||||||
|
&& quoteEndIdx != NSNotFound
|
||||||
|
&& quoteStartIdx != quoteEndIdx)
|
||||||
|
{
|
||||||
|
quoteRange = NSMakeRange(quoteStartIdx + 1, quoteEndIdx - quoteStartIdx - 1);
|
||||||
|
stringValue = [subject substringWithRange: quoteRange];
|
||||||
|
}
|
||||||
|
else stringValue = subject;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
stringValue = subject;
|
{
|
||||||
|
|
||||||
|
/* As specified in [MS-OXCMAIL] 2.2.3.2.6.1, if there are three
|
||||||
|
or less characters followed by a colon at the beginning of
|
||||||
|
the subject, we can assume that's the subject prefix */
|
||||||
|
colIdx = [subject rangeOfString: @":"].location;
|
||||||
|
if (colIdx != NSNotFound && colIdx < 4)
|
||||||
|
stringValue = [[subject substringFromIndex: colIdx + 1]
|
||||||
|
stringByTrimmingLeadSpaces];
|
||||||
|
else
|
||||||
|
stringValue = subject;
|
||||||
|
}
|
||||||
if (!stringValue)
|
if (!stringValue)
|
||||||
stringValue = @"";
|
stringValue = @"";
|
||||||
*data = [stringValue asUnicodeInMemCtx: memCtx];
|
*data = [stringValue asUnicodeInMemCtx: memCtx];
|
||||||
|
@ -780,7 +810,6 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||||
NSDictionary *contactInfos;
|
NSDictionary *contactInfos;
|
||||||
NGMailAddress *ngAddress;
|
NGMailAddress *ngAddress;
|
||||||
NSData *entryId;
|
NSData *entryId;
|
||||||
struct ldb_context *samCtx;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (fullMail)
|
if (fullMail)
|
||||||
|
@ -803,8 +832,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||||
if (contactInfos)
|
if (contactInfos)
|
||||||
{
|
{
|
||||||
username = [contactInfos objectForKey: @"sAMAccountName"];
|
username = [contactInfos objectForKey: @"sAMAccountName"];
|
||||||
samCtx = [[self context] connectionInfo]->sam_ctx;
|
entryId = MAPIStoreInternalEntryId([[self context] connectionInfo], username);
|
||||||
entryId = MAPIStoreInternalEntryId (samCtx, username);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
entryId = MAPIStoreExternalEntryId (cn, email);
|
entryId = MAPIStoreExternalEntryId (cn, email);
|
||||||
|
@ -1447,11 +1475,9 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||||
NSData *entryId;
|
NSData *entryId;
|
||||||
NSDictionary *contactInfos;
|
NSDictionary *contactInfos;
|
||||||
SOGoUserManager *mgr;
|
SOGoUserManager *mgr;
|
||||||
struct ldb_context *samCtx;
|
|
||||||
struct mapistore_message *msgData;
|
struct mapistore_message *msgData;
|
||||||
struct mapistore_message_recipient *recipient;
|
struct mapistore_message_recipient *recipient;
|
||||||
|
|
||||||
samCtx = [[self context] connectionInfo]->sam_ctx;
|
|
||||||
[super getMessageData: &msgData inMemCtx: memCtx];
|
[super getMessageData: &msgData inMemCtx: memCtx];
|
||||||
|
|
||||||
if (!headerSetup)
|
if (!headerSetup)
|
||||||
|
@ -1505,7 +1531,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||||
{
|
{
|
||||||
username = [contactInfos objectForKey: @"sAMAccountName"];
|
username = [contactInfos objectForKey: @"sAMAccountName"];
|
||||||
recipient->username = [username asUnicodeInMemCtx: msgData];
|
recipient->username = [username asUnicodeInMemCtx: msgData];
|
||||||
entryId = MAPIStoreInternalEntryId (samCtx, username);
|
entryId = MAPIStoreInternalEntryId ([[self context] connectionInfo], username);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -181,8 +181,8 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Ignore other operations as IMAP only support MODSEQ >= X */
|
/* Ignore other operations as IMAP only support MODSEQ >= X */
|
||||||
[self warnWithFormat: @"Ignoring %@ as only supported operators are > and >=",
|
[self warnWithFormat: @"Ignoring '%@' as only supported operators are > and >=",
|
||||||
[self operatorFromRestrictionOperator: res->relop]];
|
NSStringFromSelector ([self operatorFromRestrictionOperator: res->relop])];
|
||||||
rc = MAPIRestrictionStateAlwaysTrue;
|
rc = MAPIRestrictionStateAlwaysTrue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,13 +338,10 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
||||||
NSData *entryId;
|
NSData *entryId;
|
||||||
NSDictionary *allRecipients, *dict, *contactInfos;
|
NSDictionary *allRecipients, *dict, *contactInfos;
|
||||||
SOGoUserManager *mgr;
|
SOGoUserManager *mgr;
|
||||||
struct ldb_context *samCtx;
|
|
||||||
struct mapistore_message *msgData;
|
struct mapistore_message *msgData;
|
||||||
struct mapistore_message_recipient *recipient;
|
struct mapistore_message_recipient *recipient;
|
||||||
enum ulRecipClass type;
|
enum ulRecipClass type;
|
||||||
|
|
||||||
samCtx = [[self context] connectionInfo]->sam_ctx;
|
|
||||||
|
|
||||||
// [super getMessageData: &msgData inMemCtx: memCtx];
|
// [super getMessageData: &msgData inMemCtx: memCtx];
|
||||||
|
|
||||||
msgData = talloc_zero (memCtx, struct mapistore_message);
|
msgData = talloc_zero (memCtx, struct mapistore_message);
|
||||||
|
@ -389,7 +386,7 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
||||||
{
|
{
|
||||||
username = [contactInfos objectForKey: @"sAMAccountName"];
|
username = [contactInfos objectForKey: @"sAMAccountName"];
|
||||||
recipient->username = [username asUnicodeInMemCtx: msgData];
|
recipient->username = [username asUnicodeInMemCtx: msgData];
|
||||||
entryId = MAPIStoreInternalEntryId (samCtx, username);
|
entryId = MAPIStoreInternalEntryId ([[self context] connectionInfo], username);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -682,6 +679,14 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
|
||||||
|
|
||||||
if (!fromResolved)
|
if (!fromResolved)
|
||||||
{
|
{
|
||||||
|
TALLOC_CTX *local_mem_ctx;
|
||||||
|
local_mem_ctx = talloc_new(NULL);
|
||||||
|
if (!local_mem_ctx)
|
||||||
|
{
|
||||||
|
NSLog (@"%s: Out of memory", __PRETTY_FUNCTION__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NSLog (@"Message without an orig from, try to guess it from PidTagSenderEntryId");
|
NSLog (@"Message without an orig from, try to guess it from PidTagSenderEntryId");
|
||||||
senderEntryId = [mailProperties objectForKey: MAPIPropertyKey (PR_SENDER_ENTRYID)];
|
senderEntryId = [mailProperties objectForKey: MAPIPropertyKey (PR_SENDER_ENTRYID)];
|
||||||
if (senderEntryId)
|
if (senderEntryId)
|
||||||
|
@ -695,12 +700,12 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
|
||||||
|
|
||||||
bin32.cb = [senderEntryId length];
|
bin32.cb = [senderEntryId length];
|
||||||
bin32.lpb = (uint8_t *) [senderEntryId bytes];
|
bin32.lpb = (uint8_t *) [senderEntryId bytes];
|
||||||
addrBookEntryId = get_AddressBookEntryId (connInfo->sam_ctx, &bin32);
|
addrBookEntryId = get_AddressBookEntryId (local_mem_ctx, &bin32);
|
||||||
if (addrBookEntryId && [[NSString stringWithGUID: &addrBookEntryId->ProviderUID]
|
if (addrBookEntryId && [[NSString stringWithGUID: &addrBookEntryId->ProviderUID]
|
||||||
hasSuffix: @"08002b2fe182"])
|
hasSuffix: @"08002b2fe182"])
|
||||||
{
|
{
|
||||||
/* TODO: better way to distinguish local and other ones */
|
/* TODO: better way to distinguish local and other ones */
|
||||||
username = MAPIStoreSamDBUserAttribute (connInfo->sam_ctx, @"legacyExchangeDN",
|
username = MAPIStoreSamDBUserAttribute (connInfo, @"legacyExchangeDN",
|
||||||
[NSString stringWithUTF8String: addrBookEntryId->X500DN], @"sAMAccountName");
|
[NSString stringWithUTF8String: addrBookEntryId->X500DN], @"sAMAccountName");
|
||||||
if (username)
|
if (username)
|
||||||
{
|
{
|
||||||
|
@ -721,7 +726,7 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
|
||||||
/* Try with One-Off EntryId */
|
/* Try with One-Off EntryId */
|
||||||
struct OneOffEntryId *oneOffEntryId;
|
struct OneOffEntryId *oneOffEntryId;
|
||||||
|
|
||||||
oneOffEntryId = get_OneOffEntryId (connInfo->sam_ctx, &bin32);
|
oneOffEntryId = get_OneOffEntryId (local_mem_ctx, &bin32);
|
||||||
if (oneOffEntryId && [[NSString stringWithGUID: &oneOffEntryId->ProviderUID]
|
if (oneOffEntryId && [[NSString stringWithGUID: &oneOffEntryId->ProviderUID]
|
||||||
hasSuffix: @"00dd010f5402"])
|
hasSuffix: @"00dd010f5402"])
|
||||||
{
|
{
|
||||||
|
@ -730,9 +735,7 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
|
||||||
[fromRecipient setObject: [NSString stringWithUTF8String: oneOffEntryId->EmailAddress.lpszW]
|
[fromRecipient setObject: [NSString stringWithUTF8String: oneOffEntryId->EmailAddress.lpszW]
|
||||||
forKey: @"email"];
|
forKey: @"email"];
|
||||||
}
|
}
|
||||||
talloc_free (oneOffEntryId);
|
|
||||||
}
|
}
|
||||||
talloc_free (addrBookEntryId);
|
|
||||||
|
|
||||||
if ([[fromRecipient allKeys] count] > 0)
|
if ([[fromRecipient allKeys] count] > 0)
|
||||||
{
|
{
|
||||||
|
@ -742,6 +745,8 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/* Free entryId */
|
||||||
|
talloc_free(local_mem_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recipients)
|
if (!recipients)
|
||||||
|
@ -1048,6 +1053,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
|
||||||
|
|
||||||
- (int) submitWithFlags: (enum SubmitFlags) flags
|
- (int) submitWithFlags: (enum SubmitFlags) flags
|
||||||
{
|
{
|
||||||
|
enum mapistore_error rc = MAPISTORE_SUCCESS;
|
||||||
NSDictionary *recipients;
|
NSDictionary *recipients;
|
||||||
NSData *messageData;
|
NSData *messageData;
|
||||||
NSMutableArray *recipientEmails;
|
NSMutableArray *recipientEmails;
|
||||||
|
@ -1094,7 +1100,10 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
|
||||||
withAuthenticator: authenticator
|
withAuthenticator: authenticator
|
||||||
inContext: woContext];
|
inContext: woContext];
|
||||||
if (error)
|
if (error)
|
||||||
[self logWithFormat: @"an error occurred: '%@'", error];
|
{
|
||||||
|
[self errorWithFormat: @"an error occurred: '%@'", error];
|
||||||
|
rc = MAPISTORE_ERR_MSG_SEND;
|
||||||
|
}
|
||||||
|
|
||||||
// mapping = [self mapping];
|
// mapping = [self mapping];
|
||||||
// [mapping unregisterURLWithID: [self objectId]];
|
// [mapping unregisterURLWithID: [self objectId]];
|
||||||
|
@ -1106,7 +1115,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
|
||||||
[self logWithFormat: @"skipping submit of message with class '%@'",
|
[self logWithFormat: @"skipping submit of message with class '%@'",
|
||||||
msgClass];
|
msgClass];
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) save: (TALLOC_CTX *) memCtx
|
- (void) save: (TALLOC_CTX *) memCtx
|
||||||
|
|
|
@ -103,7 +103,7 @@
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
connInfo = [(MAPIStoreContext *) [container context] connectionInfo];
|
connInfo = [(MAPIStoreContext *) [container context] connectionInfo];
|
||||||
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, userId);
|
entryId = MAPIStoreInternalEntryId (connInfo, userId);
|
||||||
}
|
}
|
||||||
*data = [entryId asBinaryInMemCtx: memCtx];
|
*data = [entryId asBinaryInMemCtx: memCtx];
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,9 @@
|
||||||
|
|
||||||
#include <talloc.h>
|
#include <talloc.h>
|
||||||
|
|
||||||
#import <Foundation/NSTimeZone.h>
|
|
||||||
|
|
||||||
#import <NGCards/iCalCalendar.h>
|
#import <NGCards/iCalCalendar.h>
|
||||||
#import <NGCards/iCalRecurrenceRule.h>
|
#import <NGCards/iCalRecurrenceRule.h>
|
||||||
|
#import <NGCards/iCalTimeZone.h>
|
||||||
@class NSTimeZone;
|
|
||||||
|
|
||||||
@class iCalEvent;
|
@class iCalEvent;
|
||||||
@class iCalRepeatableEntityObject;
|
@class iCalRepeatableEntityObject;
|
||||||
|
@ -46,7 +43,7 @@
|
||||||
fromRecurrencePattern: (struct RecurrencePattern *) rp
|
fromRecurrencePattern: (struct RecurrencePattern *) rp
|
||||||
withExceptions: (struct ExceptionInfo *) exInfos
|
withExceptions: (struct ExceptionInfo *) exInfos
|
||||||
andExceptionCount: (uint16_t) exInfoCount
|
andExceptionCount: (uint16_t) exInfoCount
|
||||||
inTimeZone: (NSTimeZone *) tz;
|
inTimeZone: (iCalTimeZone *) tz;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -54,7 +51,6 @@
|
||||||
|
|
||||||
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
||||||
withEvent: (iCalEvent *) event
|
withEvent: (iCalEvent *) event
|
||||||
inTimeZone: (NSTimeZone *) timeZone
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#import <Foundation/NSCalendarDate.h>
|
#import <Foundation/NSCalendarDate.h>
|
||||||
#import <Foundation/NSSet.h>
|
#import <Foundation/NSSet.h>
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
#import <Foundation/NSTimeZone.h>
|
|
||||||
|
|
||||||
#import <NGExtensions/NSCalendarDate+misc.h>
|
#import <NGExtensions/NSCalendarDate+misc.h>
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
@ -35,6 +34,7 @@
|
||||||
#import <NGCards/iCalRepeatableEntityObject.h>
|
#import <NGCards/iCalRepeatableEntityObject.h>
|
||||||
#import <NGCards/iCalRecurrenceRule.h>
|
#import <NGCards/iCalRecurrenceRule.h>
|
||||||
#import <NGCards/iCalTimeZone.h>
|
#import <NGCards/iCalTimeZone.h>
|
||||||
|
#import <NGCards/iCalTimeZonePeriod.h>
|
||||||
|
|
||||||
#import "NSDate+MAPIStore.h"
|
#import "NSDate+MAPIStore.h"
|
||||||
#import "MAPIStoreRecurrenceUtils.h"
|
#import "MAPIStoreRecurrenceUtils.h"
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
fromRecurrencePattern: (struct RecurrencePattern *) rp
|
fromRecurrencePattern: (struct RecurrencePattern *) rp
|
||||||
withExceptions: (struct ExceptionInfo *) exInfos
|
withExceptions: (struct ExceptionInfo *) exInfos
|
||||||
andExceptionCount: (uint16_t) exInfoCount
|
andExceptionCount: (uint16_t) exInfoCount
|
||||||
inTimeZone: (NSTimeZone *) tz
|
inTimeZone: (iCalTimeZone *) tz
|
||||||
|
|
||||||
{
|
{
|
||||||
NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate;
|
NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate;
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
iCalWeekOccurrence weekOccurrence;
|
iCalWeekOccurrence weekOccurrence;
|
||||||
iCalWeekOccurrences dayMaskDays;
|
iCalWeekOccurrences dayMaskDays;
|
||||||
NSUInteger count, max;
|
NSUInteger count, max;
|
||||||
NSInteger bySetPos;
|
NSInteger bySetPos, tzOffset;
|
||||||
unsigned char maskValue;
|
unsigned char maskValue;
|
||||||
|
|
||||||
[entity removeAllRecurrenceRules];
|
[entity removeAllRecurrenceRules];
|
||||||
|
@ -242,9 +242,10 @@
|
||||||
{
|
{
|
||||||
/* The OriginalStartDate is in local time */
|
/* The OriginalStartDate is in local time */
|
||||||
exDate = [NSDate dateFromMinutesSince1601: exInfos[count].OriginalStartDate];
|
exDate = [NSDate dateFromMinutesSince1601: exInfos[count].OriginalStartDate];
|
||||||
|
tzOffset = -[[tz periodForDate: exDate] secondsOffsetFromGMT];
|
||||||
exDate = [exDate dateByAddingYears: 0 months: 0 days: 0
|
exDate = [exDate dateByAddingYears: 0 months: 0 days: 0
|
||||||
hours: 0 minutes: 0
|
hours: 0 minutes: 0
|
||||||
seconds: - [tz secondsFromGMT]];
|
seconds: tzOffset];
|
||||||
[exceptionDates removeObject: exDate];
|
[exceptionDates removeObject: exDate];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,7 +264,6 @@
|
||||||
|
|
||||||
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
||||||
withEvent: (iCalEvent *) event
|
withEvent: (iCalEvent *) event
|
||||||
inTimeZone: (NSTimeZone *) timeZone
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
iCalRecurrenceFrequency freq;
|
iCalRecurrenceFrequency freq;
|
||||||
|
@ -279,9 +279,7 @@
|
||||||
NSMutableArray *deletedDates, *modifiedDates;
|
NSMutableArray *deletedDates, *modifiedDates;
|
||||||
|
|
||||||
startDate = [event firstRecurrenceStartDate];
|
startDate = [event firstRecurrenceStartDate];
|
||||||
[startDate setTimeZone: timeZone];
|
|
||||||
endDate = [event lastPossibleRecurrenceStartDate];
|
endDate = [event lastPossibleRecurrenceStartDate];
|
||||||
[endDate setTimeZone: timeZone];
|
|
||||||
|
|
||||||
rp->ReaderVersion = 0x3004;
|
rp->ReaderVersion = 0x3004;
|
||||||
rp->WriterVersion = 0x3004;
|
rp->WriterVersion = 0x3004;
|
||||||
|
|
|
@ -197,6 +197,7 @@ static Class MAPIStoreFolderK;
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
struct mapistore_connection_info *connInfo;
|
||||||
uint64_t obVersion;
|
uint64_t obVersion;
|
||||||
|
|
||||||
obVersion = [self objectVersion];
|
obVersion = [self objectVersion];
|
||||||
|
@ -204,8 +205,9 @@ static Class MAPIStoreFolderK;
|
||||||
rc = MAPISTORE_ERR_NOT_FOUND;
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
connInfo = [[self context] connectionInfo];
|
||||||
*data = MAPILongLongValue (memCtx, ((obVersion << 16)
|
*data = MAPILongLongValue (memCtx, ((obVersion << 16)
|
||||||
| 0x0001));
|
| connInfo->repl_id));
|
||||||
rc = MAPISTORE_SUCCESS;
|
rc = MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,13 +25,13 @@
|
||||||
|
|
||||||
@class NSString;
|
@class NSString;
|
||||||
|
|
||||||
struct ldb_context;
|
#include <mapistore/mapistore.h>
|
||||||
|
|
||||||
NSString *MAPIStoreSamDBUserAttribute (struct ldb_context *samCtx,
|
NSString *MAPIStoreSamDBUserAttribute (struct mapistore_connection_info *connInfo,
|
||||||
NSString *userKey,
|
NSString *userKey,
|
||||||
NSString *value,
|
NSString *value,
|
||||||
NSString *attributeName);
|
NSString *attributeName);
|
||||||
NSData *MAPIStoreInternalEntryId (struct ldb_context *, NSString *username);
|
NSData *MAPIStoreInternalEntryId (struct mapistore_connection_info *connInfo, NSString *username);
|
||||||
NSData *MAPIStoreExternalEntryId (NSString *cn, NSString *email);
|
NSData *MAPIStoreExternalEntryId (NSString *cn, NSString *email);
|
||||||
|
|
||||||
#endif /* MAPISTORESAMDBUTILS_H */
|
#endif /* MAPISTORESAMDBUTILS_H */
|
||||||
|
|
|
@ -24,13 +24,18 @@
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
#include <talloc.h>
|
#include <talloc.h>
|
||||||
#include <ldb.h>
|
#include <ldb.h>
|
||||||
|
#include <libmapiproxy.h>
|
||||||
|
#include <samba/version.h>
|
||||||
|
|
||||||
#import "NSData+MAPIStore.h"
|
#import "NSData+MAPIStore.h"
|
||||||
|
|
||||||
#import "MAPIStoreSamDBUtils.h"
|
#import "MAPIStoreSamDBUtils.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NSString *
|
NSString *
|
||||||
MAPIStoreSamDBUserAttribute (struct ldb_context *samCtx,
|
MAPIStoreSamDBUserAttribute (struct mapistore_connection_info *connInfo,
|
||||||
NSString *userKey,
|
NSString *userKey,
|
||||||
NSString *value,
|
NSString *value,
|
||||||
NSString *attributeName)
|
NSString *attributeName)
|
||||||
|
@ -48,10 +53,20 @@ MAPIStoreSamDBUserAttribute (struct ldb_context *samCtx,
|
||||||
attrs[0] = [attributeName UTF8String];
|
attrs[0] = [attributeName UTF8String];
|
||||||
searchFormat
|
searchFormat
|
||||||
= [NSString stringWithFormat: @"(&(objectClass=user)(%@=%%s))", userKey];
|
= [NSString stringWithFormat: @"(&(objectClass=user)(%@=%%s))", userKey];
|
||||||
ret = ldb_search (samCtx, memCtx, &res, ldb_get_default_basedn(samCtx),
|
#if SAMBA_VERSION_MAJOR <= 4 && SAMBA_VERSION_MINOR < 3
|
||||||
|
ret = ldb_search (connInfo->sam_ctx, memCtx, &res,
|
||||||
|
ldb_get_default_basedn(connInfo->sam_ctx),
|
||||||
LDB_SCOPE_SUBTREE, attrs,
|
LDB_SCOPE_SUBTREE, attrs,
|
||||||
[searchFormat UTF8String],
|
[searchFormat UTF8String],
|
||||||
[value UTF8String]);
|
[value UTF8String]);
|
||||||
|
#else
|
||||||
|
ret = safe_ldb_search (&connInfo->sam_ctx, memCtx, &res,
|
||||||
|
ldb_get_default_basedn(connInfo->sam_ctx),
|
||||||
|
LDB_SCOPE_SUBTREE, attrs,
|
||||||
|
[searchFormat UTF8String],
|
||||||
|
[value UTF8String]);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ret == LDB_SUCCESS && res->count == 1)
|
if (ret == LDB_SUCCESS && res->count == 1)
|
||||||
{
|
{
|
||||||
result = ldb_msg_find_attr_as_string (res->msgs[0], attrs[0], NULL);
|
result = ldb_msg_find_attr_as_string (res->msgs[0], attrs[0], NULL);
|
||||||
|
@ -65,7 +80,7 @@ MAPIStoreSamDBUserAttribute (struct ldb_context *samCtx,
|
||||||
}
|
}
|
||||||
|
|
||||||
NSData *
|
NSData *
|
||||||
MAPIStoreInternalEntryId (struct ldb_context *samCtx, NSString *username)
|
MAPIStoreInternalEntryId (struct mapistore_connection_info *connInfo, NSString *username)
|
||||||
{
|
{
|
||||||
static const uint8_t const providerUid[] = { 0xdc, 0xa7, 0x40, 0xc8,
|
static const uint8_t const providerUid[] = { 0xdc, 0xa7, 0x40, 0xc8,
|
||||||
0xc0, 0x42, 0x10, 0x1a,
|
0xc0, 0x42, 0x10, 0x1a,
|
||||||
|
@ -82,7 +97,7 @@ MAPIStoreInternalEntryId (struct ldb_context *samCtx, NSString *username)
|
||||||
type: 32
|
type: 32
|
||||||
X500DN: variable */
|
X500DN: variable */
|
||||||
|
|
||||||
legacyDN = MAPIStoreSamDBUserAttribute (samCtx, @"sAMAccountName", username,
|
legacyDN = MAPIStoreSamDBUserAttribute (connInfo, @"sAMAccountName", username,
|
||||||
@"legacyExchangeDN");
|
@"legacyExchangeDN");
|
||||||
if (legacyDN)
|
if (legacyDN)
|
||||||
{
|
{
|
||||||
|
|
|
@ -107,11 +107,11 @@
|
||||||
if ([roles containsObject: SOGoRole_ObjectCreator])
|
if ([roles containsObject: SOGoRole_ObjectCreator])
|
||||||
rights |= RightsCreateItems;
|
rights |= RightsCreateItems;
|
||||||
if ([roles containsObject: SOGoRole_ObjectEraser])
|
if ([roles containsObject: SOGoRole_ObjectEraser])
|
||||||
rights |= RightsDeleteAll;
|
rights |= RightsDeleteAll | RightsDeleteOwn;
|
||||||
if ([roles containsObject: SOGoCalendarRole_PublicModifier]
|
if ([roles containsObject: SOGoCalendarRole_PublicModifier]
|
||||||
&& [roles containsObject: SOGoCalendarRole_PrivateModifier]
|
&& [roles containsObject: SOGoCalendarRole_PrivateModifier]
|
||||||
&& [roles containsObject: SOGoCalendarRole_ConfidentialModifier])
|
&& [roles containsObject: SOGoCalendarRole_ConfidentialModifier])
|
||||||
rights |= RightsReadItems | RightsEditAll;
|
rights |= RightsReadItems | RightsEditAll | RightsEditOwn;
|
||||||
else if ([roles containsObject: SOGoCalendarRole_PublicViewer]
|
else if ([roles containsObject: SOGoCalendarRole_PublicViewer]
|
||||||
&& [roles containsObject: SOGoCalendarRole_PrivateViewer]
|
&& [roles containsObject: SOGoCalendarRole_PrivateViewer]
|
||||||
&& [roles containsObject: SOGoCalendarRole_ConfidentialViewer])
|
&& [roles containsObject: SOGoCalendarRole_ConfidentialViewer])
|
||||||
|
|
|
@ -198,7 +198,7 @@ NSObjectFromSPropValue (const struct SPropValue *value)
|
||||||
break;
|
break;
|
||||||
case PT_STRING8:
|
case PT_STRING8:
|
||||||
result = (value->value.lpszA
|
result = (value->value.lpszA
|
||||||
? [NSString stringWithUTF8String: value->value.lpszA]
|
? [NSString stringWithUTF8String: (const char *) value->value.lpszA]
|
||||||
: (id) @"");
|
: (id) @"");
|
||||||
break;
|
break;
|
||||||
case PT_SYSTIME:
|
case PT_SYSTIME:
|
||||||
|
|
|
@ -73,6 +73,8 @@ static NSMapTable *contextsTable = nil;
|
||||||
[userContext autorelease];
|
[userContext autorelease];
|
||||||
[contextsTable setObject: userContext forKey: username];
|
[contextsTable setObject: userContext forKey: username];
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
[userContext activate];
|
||||||
|
|
||||||
return userContext;
|
return userContext;
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,7 +228,7 @@
|
||||||
mvResult = [NSMutableArray arrayWithCapacity: mvString->cValues];
|
mvResult = [NSMutableArray arrayWithCapacity: mvString->cValues];
|
||||||
for (count = 0; count < mvString->cValues; count++)
|
for (count = 0; count < mvString->cValues; count++)
|
||||||
{
|
{
|
||||||
subObject = [NSString stringWithUTF8String: mvString->lppszA[count]];
|
subObject = [NSString stringWithUTF8String: (const char *) mvString->lppszA[count]];
|
||||||
[mvResult addObject: subObject];
|
[mvResult addObject: subObject];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
|
|
||||||
- (BOOL) isNever; /* occurs on 4500-12-31 */
|
- (BOOL) isNever; /* occurs on 4500-12-31 */
|
||||||
|
|
||||||
|
+ (NSCalendarDate *) dateFromSystemTime: (struct SYSTEMTIME) date
|
||||||
|
andRuleYear: (uint16_t) rYear;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NSComparisonResult NSDateCompare (id date1, id date2, void *);
|
NSComparisonResult NSDateCompare (id date1, id date2, void *);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
#import <Foundation/NSTimeZone.h>
|
#import <Foundation/NSTimeZone.h>
|
||||||
|
|
||||||
|
#import "MAPIStoreTypes.h"
|
||||||
#import "NSDate+MAPIStore.h"
|
#import "NSDate+MAPIStore.h"
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
@ -48,7 +49,7 @@ _setupRefDate ()
|
||||||
refDate = [[NSCalendarDate alloc]
|
refDate = [[NSCalendarDate alloc]
|
||||||
initWithYear: 1601 month: 1 day: 1
|
initWithYear: 1601 month: 1 day: 1
|
||||||
hour: 0 minute: 0 second: 0
|
hour: 0 minute: 0 second: 0
|
||||||
timeZone: [NSTimeZone timeZoneWithName: @"UTC"]];
|
timeZone: utcTZ];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSCalendarDate *) dateFromMinutesSince1601: (uint32_t) minutes
|
+ (NSCalendarDate *) dateFromMinutesSince1601: (uint32_t) minutes
|
||||||
|
@ -128,6 +129,64 @@ _setupRefDate ()
|
||||||
return [calDate yearOfCommonEra] == 4500;
|
return [calDate yearOfCommonEra] == 4500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSCalendarDate *) dateFromSystemTime: (struct SYSTEMTIME) date
|
||||||
|
andRuleYear: (uint16_t) rYear
|
||||||
|
{
|
||||||
|
NSCalendarDate *result;
|
||||||
|
NSInteger daysToDate;
|
||||||
|
NSUInteger firstDayOfWeek, year;
|
||||||
|
|
||||||
|
/* ([MS-OXOCAL] 2.2.1.41.1) When we're provided an absolute date (i.e., it
|
||||||
|
happens once), the SYSTEMTIME structure is enough to fill the date.
|
||||||
|
When we're parsing a SYSTEMTIME field from a time zone rule, however, a
|
||||||
|
relative date can be provided for the peroidicity of its periods. In this
|
||||||
|
scenario, the wYear field is empty and we have to use the wYear field in
|
||||||
|
the parent rule */
|
||||||
|
if (date.wYear != 0)
|
||||||
|
year = date.wYear;
|
||||||
|
else
|
||||||
|
year = rYear;
|
||||||
|
|
||||||
|
/* The wDay field indicates the occurrence of the wDayOfWeek within the month.
|
||||||
|
The 5th occurrence means the last one, even if it is the 4th. */
|
||||||
|
if (date.wDay < 5)
|
||||||
|
{
|
||||||
|
result = [[NSCalendarDate alloc] initWithYear: year month: date.wMonth day: 1
|
||||||
|
hour: date.wHour minute: date.wMinute second: date.wSecond
|
||||||
|
timeZone: utcTZ];
|
||||||
|
[result autorelease];
|
||||||
|
|
||||||
|
firstDayOfWeek = [result dayOfWeek];
|
||||||
|
|
||||||
|
daysToDate = 7 * (date.wDay - 1) + date.wDayOfWeek - firstDayOfWeek;
|
||||||
|
if (date.wDayOfWeek < firstDayOfWeek)
|
||||||
|
daysToDate += 7;
|
||||||
|
|
||||||
|
result = [result dateByAddingYears: 0 months: 0 days: daysToDate
|
||||||
|
hours: 0 minutes: 0
|
||||||
|
seconds: 0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = [[NSCalendarDate alloc] initWithYear: year month: date.wMonth + 1 day: 1
|
||||||
|
hour: date.wHour minute: date.wMinute second: date.wSecond
|
||||||
|
timeZone: utcTZ];
|
||||||
|
[result autorelease];
|
||||||
|
|
||||||
|
firstDayOfWeek = [result dayOfWeek];
|
||||||
|
|
||||||
|
daysToDate = date.wDayOfWeek - firstDayOfWeek;
|
||||||
|
if (date.wDayOfWeek >= firstDayOfWeek)
|
||||||
|
daysToDate -= 7;
|
||||||
|
|
||||||
|
result = [result dateByAddingYears: 0 months: 0 days: daysToDate
|
||||||
|
hours: 0 minutes: 0
|
||||||
|
seconds: 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NSComparisonResult
|
NSComparisonResult
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
int font_index;
|
int font_index;
|
||||||
int color_index;
|
int color_index;
|
||||||
int start_pos;
|
int start_pos;
|
||||||
|
const unsigned short *charset;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@
|
||||||
{
|
{
|
||||||
@public
|
@public
|
||||||
NSString *family;
|
NSString *family;
|
||||||
NSString *charset;
|
unsigned char charset;
|
||||||
NSString *name;
|
NSString *name;
|
||||||
unsigned int pitch;
|
unsigned int pitch;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,8 @@
|
||||||
/* dbmsgreader.m - this file is part of SOGo
|
/* dbmsgreader.m - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011-2012 Inverse inc
|
* Copyright (C) 2011-2012 Inverse inc
|
||||||
|
* 2015 Enrique J. Hernandez
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* This file is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -33,21 +33,58 @@
|
||||||
#import <SOGo/SOGoProductLoader.h>
|
#import <SOGo/SOGoProductLoader.h>
|
||||||
#import <SOGo/SOGoSystemDefaults.h>
|
#import <SOGo/SOGoSystemDefaults.h>
|
||||||
|
|
||||||
|
#import <libmapi/libmapi.h>
|
||||||
|
|
||||||
#import "MAPIStoreUserContext.h"
|
#import "MAPIStoreUserContext.h"
|
||||||
#import <SOGo/SOGoCacheGCSObject.h>
|
#import <SOGo/SOGoCacheGCSObject.h>
|
||||||
|
|
||||||
#import <SOGo/BSONCodec.h>
|
#import <SOGo/BSONCodec.h>
|
||||||
#import "NSObject+PropertyList.h"
|
#import "NSObject+PropertyList.h"
|
||||||
|
|
||||||
Class MAPIStoreUserContextK, SOGoCacheGCSObjectK;
|
|
||||||
|
Class MAPIStoreUserContextK, SOGoCacheGCSObjectK, NSStringK;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DumpBSONData(NSData *data)
|
DumpBSONData(NSData *data)
|
||||||
{
|
{
|
||||||
|
id key, value;
|
||||||
|
NSEnumerator *dictEnum;
|
||||||
NSDictionary *dvalue;
|
NSDictionary *dvalue;
|
||||||
|
NSMutableString *outStr;
|
||||||
|
NSUInteger max;
|
||||||
|
|
||||||
dvalue = [data BSONValue];
|
dvalue = [data BSONValue];
|
||||||
[dvalue displayWithIndentation:0];
|
max = [dvalue count];
|
||||||
printf("\n");
|
dictEnum = [dvalue keyEnumerator];
|
||||||
|
NSStringK = [NSString class];
|
||||||
|
outStr = [NSMutableString stringWithFormat: @"{ %d items\n", max];
|
||||||
|
while ((key = [dictEnum nextObject]))
|
||||||
|
{
|
||||||
|
uint32_t proptag = 0;
|
||||||
|
if ([key isKindOfClass: NSStringK] && [(NSString *)key intValue] > 0)
|
||||||
|
proptag = [(NSString *)key intValue];
|
||||||
|
|
||||||
|
if (proptag > 0)
|
||||||
|
{
|
||||||
|
const char *propTagName = get_proptag_name (proptag);
|
||||||
|
NSString *propName;
|
||||||
|
|
||||||
|
if (propTagName)
|
||||||
|
propName = [NSString stringWithCString: propTagName
|
||||||
|
encoding: NSUTF8StringEncoding];
|
||||||
|
else
|
||||||
|
propName = [NSString stringWithFormat: @"0x%.4x", [key unsignedLongValue]];
|
||||||
|
|
||||||
|
[outStr appendFormat: @" %@ = ", propName];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[outStr appendFormat: @" %@ = ", key];
|
||||||
|
|
||||||
|
value = [dvalue objectForKey: key];
|
||||||
|
[outStr appendFormat: @"(%@) %@,\n", NSStringFromClass ([value class]), value];
|
||||||
|
}
|
||||||
|
[outStr appendFormat: @"}\n"];
|
||||||
|
printf ("%s\n", [outStr UTF8String]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -67,7 +104,7 @@ DbDumpObject (NSString *username, NSString *path)
|
||||||
{
|
{
|
||||||
printf("record found: %p\n", record);
|
printf("record found: %p\n", record);
|
||||||
content = [[record objectForKey: @"c_content"] dataByDecodingBase64];
|
content = [[record objectForKey: @"c_content"] dataByDecodingBase64];
|
||||||
DumpBSONData(content);
|
DumpBSONData (content);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
NSLog (@"record not found");
|
NSLog (@"record not found");
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#import <NGCards/iCalDateTime.h>
|
#import <NGCards/iCalDateTime.h>
|
||||||
#import <NGCards/iCalPerson.h>
|
#import <NGCards/iCalPerson.h>
|
||||||
#import <NGCards/iCalTimeZone.h>
|
#import <NGCards/iCalTimeZone.h>
|
||||||
|
#import <NGCards/iCalTimeZonePeriod.h>
|
||||||
#import <NGCards/iCalTrigger.h>
|
#import <NGCards/iCalTrigger.h>
|
||||||
#import <SOGo/SOGoPermissions.h>
|
#import <SOGo/SOGoPermissions.h>
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
|
@ -70,11 +71,12 @@
|
||||||
#include <mapistore/mapistore_nameid.h>
|
#include <mapistore/mapistore_nameid.h>
|
||||||
|
|
||||||
#import "iCalEvent+MAPIStore.h"
|
#import "iCalEvent+MAPIStore.h"
|
||||||
|
#import "iCalTimeZone+MAPIStore.h"
|
||||||
|
|
||||||
@implementation iCalEvent (MAPIStoreProperties)
|
@implementation iCalEvent (MAPIStoreProperties)
|
||||||
|
|
||||||
- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData
|
- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData
|
||||||
inTimeZone: (NSTimeZone *) tz
|
inTimeZone: (iCalTimeZone *) tz
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
struct Binary_r *blob;
|
struct Binary_r *blob;
|
||||||
|
@ -250,10 +252,8 @@
|
||||||
BOOL isAllDay;
|
BOOL isAllDay;
|
||||||
iCalDateTime *start, *end;
|
iCalDateTime *start, *end;
|
||||||
iCalTimeZone *tz;
|
iCalTimeZone *tz;
|
||||||
NSTimeZone *userTimeZone;
|
NSString *priority, *class = nil, *tzDescription = nil;
|
||||||
NSString *priority, *class = nil;
|
|
||||||
NSUInteger responseStatus = 0;
|
NSUInteger responseStatus = 0;
|
||||||
NSInteger tzOffset;
|
|
||||||
SOGoUser *ownerUser;
|
SOGoUser *ownerUser;
|
||||||
id value;
|
id value;
|
||||||
|
|
||||||
|
@ -274,7 +274,31 @@
|
||||||
[self setAccessClass: @"PUBLIC"];
|
[self setAccessClass: @"PUBLIC"];
|
||||||
}
|
}
|
||||||
|
|
||||||
userTimeZone = [userContext timeZone];
|
/* Time zone = PidLidAppointmentTimeZoneDefinitionRecur
|
||||||
|
or PidLidAppointmentTimeZoneDefinition[Start|End]Display */
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionStartDisplay)];
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionEndDisplay)];
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
/* If PidLidtimeZoneStruct, TZID SHOULD come from PidLidTimeZoneDescription,
|
||||||
|
if PidLidAppointmentTimeZoneDefinition[Start|End]Display it MUST be derived from KeyName
|
||||||
|
(MS-OXCICAL] 2.1.3.1.1.19.1) */
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionRecur)];
|
||||||
|
tzDescription = [properties objectForKey: MAPIPropertyKey (PidLidTimeZoneDescription)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
tz = [[iCalTimeZone alloc] iCalTimeZoneFromDefinition: value
|
||||||
|
withDescription: tzDescription
|
||||||
|
inMemCtx: memCtx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* The client is more likely to have the webmail's time zone than any other */
|
||||||
|
tz = [iCalTimeZone timeZoneForName: [[userContext timeZone] name]];
|
||||||
|
[(iCalCalendar *) parent addTimeZone: tz];
|
||||||
|
|
||||||
/* CREATED */
|
/* CREATED */
|
||||||
value = [properties objectForKey: MAPIPropertyKey (PidTagCreationTime)];
|
value = [properties objectForKey: MAPIPropertyKey (PidTagCreationTime)];
|
||||||
|
@ -306,13 +330,6 @@
|
||||||
objectForKey: MAPIPropertyKey (PidLidAppointmentSubType)];
|
objectForKey: MAPIPropertyKey (PidLidAppointmentSubType)];
|
||||||
if (value)
|
if (value)
|
||||||
isAllDay = [value boolValue];
|
isAllDay = [value boolValue];
|
||||||
if (!isAllDay)
|
|
||||||
{
|
|
||||||
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
|
|
||||||
[(iCalCalendar *) parent addTimeZone: tz];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tz = nil;
|
|
||||||
|
|
||||||
// recurrence-id
|
// recurrence-id
|
||||||
value
|
value
|
||||||
|
@ -330,15 +347,7 @@
|
||||||
[start setTimeZone: tz];
|
[start setTimeZone: tz];
|
||||||
if (isAllDay)
|
if (isAllDay)
|
||||||
{
|
{
|
||||||
/* when user TZ is positive (East) all-day events were not
|
/* All-day events are set in floating time ([MS-OXCICAL] 2.1.3.1.1.20.8) */
|
||||||
shown properly in SOGo UI. This day delay fixes it */
|
|
||||||
tzOffset = [userTimeZone secondsFromGMTForDate: value];
|
|
||||||
if (tzOffset > 0)
|
|
||||||
{
|
|
||||||
value = [value dateByAddingYears: 0 months: 0 days: 1
|
|
||||||
hours: 0 minutes: 0
|
|
||||||
seconds: 0];
|
|
||||||
}
|
|
||||||
[start setDate: value];
|
[start setDate: value];
|
||||||
[start setTimeZone: nil];
|
[start setTimeZone: nil];
|
||||||
}
|
}
|
||||||
|
@ -356,15 +365,7 @@
|
||||||
[end setTimeZone: tz];
|
[end setTimeZone: tz];
|
||||||
if (isAllDay)
|
if (isAllDay)
|
||||||
{
|
{
|
||||||
/* when user TZ is positive (East) all-day events were not
|
/* All-day events are set in floating time ([MS-OXCICAL] 2.1.3.1.1.20.8) */
|
||||||
shown properly in SOGo UI. This day delay fixes it */
|
|
||||||
tzOffset = [userTimeZone secondsFromGMTForDate: value];
|
|
||||||
if (tzOffset > 0)
|
|
||||||
{
|
|
||||||
value = [value dateByAddingYears: 0 months: 0 days: 1
|
|
||||||
hours: 0 minutes: 0
|
|
||||||
seconds: 0];
|
|
||||||
}
|
|
||||||
[end setDate: value];
|
[end setDate: value];
|
||||||
[end setTimeZone: nil];
|
[end setTimeZone: nil];
|
||||||
}
|
}
|
||||||
|
@ -467,7 +468,7 @@
|
||||||
value = [properties
|
value = [properties
|
||||||
objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
|
objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
|
||||||
if (value)
|
if (value)
|
||||||
[self _setupEventRecurrence: value inTimeZone: userTimeZone inMemCtx: memCtx];
|
[self _setupEventRecurrence: value inTimeZone: tz inMemCtx: memCtx];
|
||||||
|
|
||||||
/* alarm */
|
/* alarm */
|
||||||
[self _setupEventAlarmFromProperties: properties];
|
[self _setupEventAlarmFromProperties: properties];
|
||||||
|
|
|
@ -30,6 +30,11 @@
|
||||||
- (struct Binary_r *) asTimeZoneStructInMemCtx: (TALLOC_CTX *) memCtx;
|
- (struct Binary_r *) asTimeZoneStructInMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
- (struct Binary_r *) asZoneTimeDefinitionWithFlags: (enum TZRuleFlag) flags
|
- (struct Binary_r *) asZoneTimeDefinitionWithFlags: (enum TZRuleFlag) flags
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
- (iCalTimeZone *) iCalTimeZoneFromDefinition: (NSData *) value
|
||||||
|
withDescription: (NSString *) description
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
- (NSCalendarDate *) shiftedCalendarDateForDate: (NSCalendarDate *) date;
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,15 @@
|
||||||
#import <Foundation/NSArray.h>
|
#import <Foundation/NSArray.h>
|
||||||
#import <Foundation/NSCalendarDate.h>
|
#import <Foundation/NSCalendarDate.h>
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
|
#import <Foundation/NSTimeZone.h>
|
||||||
#import <NGCards/iCalByDayMask.h>
|
#import <NGCards/iCalByDayMask.h>
|
||||||
|
#import <NGCards/iCalDateTime.h>
|
||||||
#import <NGCards/iCalTimeZonePeriod.h>
|
#import <NGCards/iCalTimeZonePeriod.h>
|
||||||
#import <NGCards/iCalRecurrenceRule.h>
|
#import <NGCards/iCalRecurrenceRule.h>
|
||||||
|
|
||||||
#import "NSString+MAPIStore.h"
|
#import "NSString+MAPIStore.h"
|
||||||
|
#import "NSData+MAPIStore.h"
|
||||||
|
#import "NSDate+MAPIStore.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -36,6 +40,7 @@
|
||||||
#include <libmapi/libmapi.h>
|
#include <libmapi/libmapi.h>
|
||||||
|
|
||||||
#import "iCalTimeZone+MAPIStore.h"
|
#import "iCalTimeZone+MAPIStore.h"
|
||||||
|
#import "MAPIStoreTypes.h"
|
||||||
|
|
||||||
@interface iCalTimeZonePeriod (MAPIStorePropertiesPrivate)
|
@interface iCalTimeZonePeriod (MAPIStorePropertiesPrivate)
|
||||||
|
|
||||||
|
@ -103,18 +108,18 @@
|
||||||
{
|
{
|
||||||
iCalTimeZonePeriod *period;
|
iCalTimeZonePeriod *period;
|
||||||
struct TimeZoneStruct tz;
|
struct TimeZoneStruct tz;
|
||||||
int lBias, dlBias;
|
int32_t lBias, dlBias;
|
||||||
|
|
||||||
memset (&tz, 0, sizeof (struct TimeZoneStruct));
|
memset (&tz, 0, sizeof (struct TimeZoneStruct));
|
||||||
period = [self _mostRecentPeriodWithName: @"STANDARD"];
|
period = [self _mostRecentPeriodWithName: @"STANDARD"];
|
||||||
lBias = -[period secondsOffsetFromGMT] / 60;
|
lBias = -[period secondsOffsetFromGMT] / 60;
|
||||||
tz.lBias = (uint32_t) lBias;
|
tz.lBias = lBias;
|
||||||
[period _fillTZDate: &tz.stStandardDate];
|
[period _fillTZDate: &tz.stStandardDate];
|
||||||
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
|
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
|
||||||
if (!period)
|
if (!period)
|
||||||
tz.stStandardDate.wMonth = 0;
|
tz.stStandardDate.wMonth = 0;
|
||||||
dlBias = -([period secondsOffsetFromGMT] / 60) - lBias;
|
dlBias = -([period secondsOffsetFromGMT] / 60) - lBias;
|
||||||
tz.lDaylightBias = (uint32_t) (dlBias);
|
tz.lDaylightBias = dlBias;
|
||||||
[period _fillTZDate: &tz.stDaylightDate];
|
[period _fillTZDate: &tz.stDaylightDate];
|
||||||
tz.wStandardYear = tz.stStandardDate.wYear;
|
tz.wStandardYear = tz.stStandardDate.wYear;
|
||||||
tz.wDaylightYear = tz.stDaylightDate.wYear;
|
tz.wDaylightYear = tz.stDaylightDate.wYear;
|
||||||
|
@ -153,18 +158,220 @@
|
||||||
period = [self _mostRecentPeriodWithName: @"STANDARD"];
|
period = [self _mostRecentPeriodWithName: @"STANDARD"];
|
||||||
rule.wYear = [[period startDate] yearOfCommonEra];
|
rule.wYear = [[period startDate] yearOfCommonEra];
|
||||||
lBias = -[period secondsOffsetFromGMT] / 60;
|
lBias = -[period secondsOffsetFromGMT] / 60;
|
||||||
rule.lBias = (uint32_t) lBias;
|
rule.lBias = lBias;
|
||||||
[period _fillTZDate: &rule.stStandardDate];
|
[period _fillTZDate: &rule.stStandardDate];
|
||||||
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
|
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
|
||||||
if (!period)
|
if (!period)
|
||||||
rule.stStandardDate.wMonth = 0;
|
rule.stStandardDate.wMonth = 0;
|
||||||
dlBias = -([period secondsOffsetFromGMT] / 60) - lBias;
|
dlBias = -([period secondsOffsetFromGMT] / 60) - lBias;
|
||||||
rule.lDaylightBias = (uint32_t) (dlBias);
|
rule.lDaylightBias = dlBias;
|
||||||
[period _fillTZDate: &rule.stDaylightDate];
|
[period _fillTZDate: &rule.stDaylightDate];
|
||||||
|
|
||||||
|
|
||||||
return set_TimeZoneDefinition (memCtx, &definition);
|
return set_TimeZoneDefinition (memCtx, &definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) _offsetStringFromOffset: (NSInteger) offset
|
||||||
|
{
|
||||||
|
NSInteger offsetHours, offsetMins;
|
||||||
|
NSString *offsetSign;
|
||||||
|
|
||||||
|
/* The offset format is, eg, "+0200" for 2 hours 0 minutes ahead */
|
||||||
|
if (offset < 0)
|
||||||
|
offsetSign = @"-";
|
||||||
|
else
|
||||||
|
offsetSign = @"+";
|
||||||
|
offsetHours = abs (offset) / 60;
|
||||||
|
offsetMins = abs (offset) % 60;
|
||||||
|
|
||||||
|
return [NSString stringWithFormat: @"%@%d%d%d%d",
|
||||||
|
offsetSign, offsetHours / 10, offsetHours % 10,
|
||||||
|
offsetMins / 10, offsetMins % 10];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) _rRuleStringFromSystemTime: (struct SYSTEMTIME) date
|
||||||
|
{
|
||||||
|
NSString *result, *byDay;
|
||||||
|
|
||||||
|
/* The conversion tables between the SYSTEMTIME fields and the RRULE ones
|
||||||
|
can be found at [MS-OXCICAL] 2.1.3.2.1 */
|
||||||
|
if (date.wDay == 5)
|
||||||
|
byDay = @"-1";
|
||||||
|
else
|
||||||
|
byDay = [NSString stringWithFormat: @"%d", date.wDay];
|
||||||
|
|
||||||
|
switch (date.wDayOfWeek)
|
||||||
|
{
|
||||||
|
case iCalWeekDaySunday:
|
||||||
|
byDay = [byDay stringByAppendingString: @"SU"];
|
||||||
|
break;
|
||||||
|
case iCalWeekDayMonday:
|
||||||
|
byDay = [byDay stringByAppendingString: @"MO"];
|
||||||
|
break;
|
||||||
|
case iCalWeekDayTuesday:
|
||||||
|
byDay = [byDay stringByAppendingString: @"TU"];
|
||||||
|
break;
|
||||||
|
case iCalWeekDayWednesday:
|
||||||
|
byDay = [byDay stringByAppendingString: @"WE"];
|
||||||
|
break;
|
||||||
|
case iCalWeekDayThursday:
|
||||||
|
byDay = [byDay stringByAppendingString: @"TH"];
|
||||||
|
break;
|
||||||
|
case iCalWeekDayFriday:
|
||||||
|
byDay = [byDay stringByAppendingString: @"FR"];
|
||||||
|
break;
|
||||||
|
case iCalWeekDaySaturday:
|
||||||
|
byDay = [byDay stringByAppendingString: @"SA"];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = [NSString stringWithFormat: @"FREQ=YEARLY;BYDAY=%@;BYMONTH=%d", byDay, date.wMonth];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (iCalTimeZone *) iCalTimeZoneFromDefinition: (NSData *) value
|
||||||
|
withDescription: (NSString *) description
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
BOOL daylightDefined = NO, ruleFound = NO;
|
||||||
|
iCalDateTime *daylightStart, *standardStart;
|
||||||
|
iCalRecurrenceRule *daylightRRule, *standardRRule;
|
||||||
|
iCalTimeZone *tz = nil;
|
||||||
|
iCalTimeZonePeriod *daylight, *standard;
|
||||||
|
NSCalendarDate *dlStartValue, *stStartValue;
|
||||||
|
NSString *strOffsetFrom, *strOffsetTo, *tzID;
|
||||||
|
char *keyName;
|
||||||
|
struct Binary_r *binValue;
|
||||||
|
struct SYSTEMTIME initDate;
|
||||||
|
struct TimeZoneDefinition *definition;
|
||||||
|
struct TZRule rule;
|
||||||
|
uint16_t count;
|
||||||
|
|
||||||
|
binValue = [value asBinaryInMemCtx: memCtx];
|
||||||
|
definition = get_TimeZoneDefinition (memCtx, binValue);
|
||||||
|
|
||||||
|
if (!definition)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
if (!definition->cRules)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
for (count = 0; count < definition->cRules; count++)
|
||||||
|
{
|
||||||
|
/* ([MS-OXCICAL] 2.1.3.1.1.19) The TZRule with the
|
||||||
|
TZRULE_FLAG_EFFECTIVE_TZREG bit set in the TZRule flags field
|
||||||
|
is the one that MUST be exported */
|
||||||
|
if (definition->TZRules[count].flags & TZRULE_FLAG_EFFECTIVE_TZREG)
|
||||||
|
{
|
||||||
|
rule = definition->TZRules[count];
|
||||||
|
ruleFound = YES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ruleFound)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (!description)
|
||||||
|
{
|
||||||
|
/* The cbHeader field contains the size, in bytes of the Reserved (2b),
|
||||||
|
cchKeyName (2b) keyName (variable Unicode string) and cRules (2b)
|
||||||
|
([MS-OXOCAL] 2.2.1.41). The keyName field is a non-NULL-terminated
|
||||||
|
char array. */
|
||||||
|
keyName = talloc_strndup (memCtx, definition->keyName, (definition->cbHeader - 6) / 2);
|
||||||
|
tzID = [NSString stringWithCString: keyName
|
||||||
|
encoding: [NSString defaultCStringEncoding]];
|
||||||
|
talloc_free (keyName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tzID = [NSString stringWithString: description];
|
||||||
|
|
||||||
|
tz = [iCalTimeZone groupWithTag: @"vtimezone"];
|
||||||
|
[tz addChild: [CardElement simpleElementWithTag: @"tzid"
|
||||||
|
value: tzID]];
|
||||||
|
|
||||||
|
if (rule.stStandardDate.wMonth != 0)
|
||||||
|
daylightDefined = YES;
|
||||||
|
|
||||||
|
/* STANDARD TIME ([MS-OXCICAL] 2.1.3.1.1.19.2) */
|
||||||
|
standard = [iCalTimeZonePeriod groupWithTag: @"standard"];
|
||||||
|
|
||||||
|
/* TZOFFSETFROM = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lDaylightBias) */
|
||||||
|
strOffsetFrom = [self _offsetStringFromOffset: -1 * (rule.lBias + rule.lDaylightBias)];
|
||||||
|
[standard addChild: [CardElement simpleElementWithTag: @"tzoffsetfrom"
|
||||||
|
value: strOffsetFrom]];
|
||||||
|
|
||||||
|
/* TZOFFSETTO = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lStandardBias) */
|
||||||
|
strOffsetTo = [self _offsetStringFromOffset: -1 * (rule.lBias + rule.lStandardBias)];
|
||||||
|
[standard addChild: [CardElement simpleElementWithTag: @"tzoffsetto"
|
||||||
|
value: strOffsetTo]];
|
||||||
|
|
||||||
|
/* DTSTART & RRULE are derived from the stStandardDate and wYear properties */
|
||||||
|
standardStart = [iCalDateTime elementWithTag: @"dtstart"];
|
||||||
|
|
||||||
|
initDate = rule.stStandardDate;
|
||||||
|
stStartValue = [NSCalendarDate dateFromSystemTime: initDate
|
||||||
|
andRuleYear: rule.wYear];
|
||||||
|
|
||||||
|
[standardStart setDateTime: stStartValue];
|
||||||
|
[standard addChild: standardStart];
|
||||||
|
|
||||||
|
if (daylightDefined)
|
||||||
|
{
|
||||||
|
standardRRule = [[iCalRecurrenceRule alloc] initWithString: [self _rRuleStringFromSystemTime: initDate]];
|
||||||
|
[standard addChild: standardRRule];
|
||||||
|
|
||||||
|
/* DAYLIGHT SAVING TIME ([MS-OXCICAL] 2.1.3.1.1.19.3) */
|
||||||
|
daylight = [iCalTimeZonePeriod groupWithTag: @"daylight"];
|
||||||
|
/* TZOFFSETFROM = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lStandardBias) */
|
||||||
|
[daylight addChild: [CardElement simpleElementWithTag: @"tzoffsetfrom"
|
||||||
|
value: strOffsetTo]];
|
||||||
|
/* TZOFFSETTO = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lDaylightBias) */
|
||||||
|
[daylight addChild: [CardElement simpleElementWithTag: @"tzoffsetto"
|
||||||
|
value: strOffsetFrom]];
|
||||||
|
|
||||||
|
/* DTSTART & RRULE are derived from the stDaylightDate and wYear properties */
|
||||||
|
daylightStart = [iCalDateTime elementWithTag: @"dtstart"];
|
||||||
|
initDate = rule.stDaylightDate;
|
||||||
|
dlStartValue = [NSCalendarDate dateFromSystemTime: initDate
|
||||||
|
andRuleYear: rule.wYear];
|
||||||
|
|
||||||
|
[daylightStart setDateTime: dlStartValue];
|
||||||
|
[daylight addChild: daylightStart];
|
||||||
|
|
||||||
|
daylightRRule = [[iCalRecurrenceRule alloc] initWithString: [self _rRuleStringFromSystemTime: initDate]];
|
||||||
|
[daylight addChild: daylightRRule];
|
||||||
|
[tz addChild: daylight];
|
||||||
|
}
|
||||||
|
[tz addChild: standard];
|
||||||
|
|
||||||
|
end:
|
||||||
|
|
||||||
|
talloc_free (definition);
|
||||||
|
return tz;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust a date in this vTimeZone to its representation in UTC
|
||||||
|
* Example: Timezone is +0001, the date is 2015-12-15 00:00:00 +0000
|
||||||
|
* it returns 2015-12-14 23:00:00 +0000
|
||||||
|
* @param date the date to adjust to the timezone.
|
||||||
|
* @return a new GMT date adjusted with the offset of the timezone.
|
||||||
|
*/
|
||||||
|
- (NSCalendarDate *) shiftedCalendarDateForDate: (NSCalendarDate *) date
|
||||||
|
{
|
||||||
|
NSCalendarDate *tmpDate;
|
||||||
|
|
||||||
|
tmpDate = [date copy];
|
||||||
|
[tmpDate autorelease];
|
||||||
|
|
||||||
|
[tmpDate setTimeZone: utcTZ];
|
||||||
|
|
||||||
|
return [tmpDate addYear: 0 month: 0 day: 0
|
||||||
|
hour: 0 minute: 0
|
||||||
|
second: -[[self periodForDate: tmpDate] secondsOffsetFromGMT]];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -609,8 +609,16 @@ static Class iCalEventK = nil;
|
||||||
NSNumber *classNumber;
|
NSNumber *classNumber;
|
||||||
unsigned int grantedCount;
|
unsigned int grantedCount;
|
||||||
iCalAccessClass currentClass;
|
iCalAccessClass currentClass;
|
||||||
|
WOContext *localContext;
|
||||||
|
|
||||||
[self initializeQuickTablesAclsInContext: context];
|
/* FIXME: The stored context from initialisation may have changed
|
||||||
|
by setContext by other operations in OpenChange library,
|
||||||
|
so we keep tighly to use the current session one. Without
|
||||||
|
this, the login is set to nil and a NSException is raised
|
||||||
|
at [SOGoAppointmentFolder:roleForComponentsWithAccessClass:forUser]
|
||||||
|
inside [SOGoAppointmentFolder:initializeQuickTablesAclsInContext]. */
|
||||||
|
localContext = [[WOApplication application] context];
|
||||||
|
[self initializeQuickTablesAclsInContext: localContext];
|
||||||
grantedClasses = [NSMutableArray arrayWithCapacity: 3];
|
grantedClasses = [NSMutableArray arrayWithCapacity: 3];
|
||||||
deniedClasses = [NSMutableArray arrayWithCapacity: 3];
|
deniedClasses = [NSMutableArray arrayWithCapacity: 3];
|
||||||
for (currentClass = 0;
|
for (currentClass = 0;
|
||||||
|
|
|
@ -166,9 +166,10 @@
|
||||||
ldifEntry = [childRecords objectForKey: objectName];
|
ldifEntry = [childRecords objectForKey: objectName];
|
||||||
if (!ldifEntry)
|
if (!ldifEntry)
|
||||||
{
|
{
|
||||||
ldifEntry = [source lookupContactEntry: objectName];
|
ldifEntry = [source lookupContactEntry: objectName
|
||||||
if (ldifEntry)
|
inDomain: [[context activeUser] domain]];
|
||||||
[childRecords setObject: ldifEntry forKey: objectName];
|
if (ldifEntry)
|
||||||
|
[childRecords setObject: ldifEntry forKey: objectName];
|
||||||
else if ([self isValidContentName: objectName])
|
else if ([self isValidContentName: objectName])
|
||||||
{
|
{
|
||||||
url = [[[lookupContext request] uri] urlWithoutParameters];
|
url = [[[lookupContext request] uri] urlWithoutParameters];
|
||||||
|
@ -373,7 +374,11 @@
|
||||||
NSDictionary *record;
|
NSDictionary *record;
|
||||||
|
|
||||||
if (aName && [aName length] > 0)
|
if (aName && [aName length] > 0)
|
||||||
record = [self _flattenedRecord: [source lookupContactEntry: aName]];
|
{
|
||||||
|
record = [source lookupContactEntry: aName
|
||||||
|
inDomain: [[context activeUser] domain]];
|
||||||
|
record = [self _flattenedRecord: record];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
record = nil;
|
record = nil;
|
||||||
|
|
||||||
|
@ -611,7 +616,7 @@
|
||||||
toResponse: (WOResponse *) response
|
toResponse: (WOResponse *) response
|
||||||
{
|
{
|
||||||
NSObject <DOMElement> *element;
|
NSObject <DOMElement> *element;
|
||||||
NSString *url, *baseURL, *cname;
|
NSString *url, *baseURL, *cname, *domain;
|
||||||
NSString **propertiesArray;
|
NSString **propertiesArray;
|
||||||
NSMutableString *buffer;
|
NSMutableString *buffer;
|
||||||
NSDictionary *object;
|
NSDictionary *object;
|
||||||
|
@ -628,13 +633,13 @@
|
||||||
|
|
||||||
max = [refs length];
|
max = [refs length];
|
||||||
buffer = [NSMutableString stringWithCapacity: max*512];
|
buffer = [NSMutableString stringWithCapacity: max*512];
|
||||||
|
domain = [[context activeUser] domain];
|
||||||
for (count = 0; count < max; count++)
|
for (count = 0; count < max; count++)
|
||||||
{
|
{
|
||||||
element = [refs objectAtIndex: count];
|
element = [refs objectAtIndex: count];
|
||||||
url = [[[element firstChild] nodeValue] stringByUnescapingURL];
|
url = [[[element firstChild] nodeValue] stringByUnescapingURL];
|
||||||
cname = [self _deduceObjectNameFromURL: url fromBaseURL: baseURL];
|
cname = [self _deduceObjectNameFromURL: url fromBaseURL: baseURL];
|
||||||
object = [source lookupContactEntry: cname];
|
object = [source lookupContactEntry: cname inDomain: domain];
|
||||||
if (object)
|
if (object)
|
||||||
[self appendObject: object
|
[self appendObject: object
|
||||||
properties: propertiesArray
|
properties: propertiesArray
|
||||||
|
|
|
@ -31,13 +31,12 @@
|
||||||
NSDictionary *parameters;
|
NSDictionary *parameters;
|
||||||
NSString *filename;
|
NSString *filename;
|
||||||
|
|
||||||
filename = [[self objectForKey: @"parameterList"]
|
filename = nil;
|
||||||
objectForKey: @"name"];
|
parameters = [[self objectForKey: @"disposition"]
|
||||||
|
objectForKey: @"parameterList"];
|
||||||
|
|
||||||
if (!filename)
|
if (parameters)
|
||||||
{
|
{
|
||||||
parameters = [[self objectForKey: @"disposition"]
|
|
||||||
objectForKey: @"parameterList"];
|
|
||||||
filename = [parameters objectForKey: @"filename"];
|
filename = [parameters objectForKey: @"filename"];
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,29 +44,33 @@
|
||||||
// See RFC2231 for details. If it was folded before, it will
|
// See RFC2231 for details. If it was folded before, it will
|
||||||
// be unfolded when we get here.
|
// be unfolded when we get here.
|
||||||
if (!filename)
|
if (!filename)
|
||||||
{
|
{
|
||||||
filename = [parameters objectForKey: @"filename*"];
|
filename = [parameters objectForKey: @"filename*"];
|
||||||
|
|
||||||
if (filename)
|
if (filename)
|
||||||
{
|
{
|
||||||
NSRange r;
|
NSRange r;
|
||||||
|
|
||||||
filename = [filename stringByUnescapingURL];
|
filename = [filename stringByUnescapingURL];
|
||||||
|
|
||||||
// We skip up to the language
|
// We skip up to the language
|
||||||
r = [filename rangeOfString: @"'"];
|
r = [filename rangeOfString: @"'"];
|
||||||
|
|
||||||
if (r.length)
|
if (r.length)
|
||||||
{
|
{
|
||||||
r = [filename rangeOfString: @"'" options: 0 range: NSMakeRange(r.location+1, [filename length]-r.location-1)];
|
r = [filename rangeOfString: @"'" options: 0 range: NSMakeRange(r.location+1, [filename length]-r.location-1)];
|
||||||
|
|
||||||
if (r.length)
|
if (r.length)
|
||||||
filename = [filename substringFromIndex: r.location+1];
|
filename = [filename substringFromIndex: r.location+1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!filename)
|
||||||
|
filename = [[self objectForKey: @"parameterList"]
|
||||||
|
objectForKey: @"name"];
|
||||||
|
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,12 @@ SOGo_HEADER_FILES = \
|
||||||
SOGoGCSFolder.h \
|
SOGoGCSFolder.h \
|
||||||
SOGoParentFolder.h \
|
SOGoParentFolder.h \
|
||||||
SOGoUserFolder.h \
|
SOGoUserFolder.h \
|
||||||
|
SOGoSource.h \
|
||||||
|
SOGoSystemDefaults.h \
|
||||||
|
SOGoDomainDefaults.h \
|
||||||
|
SOGoLDAPDefaults.h \
|
||||||
|
SOGoDefaultsSource.h \
|
||||||
|
SOGoUserDefaults.h \
|
||||||
\
|
\
|
||||||
SOGoSieveManager.h \
|
SOGoSieveManager.h \
|
||||||
\
|
\
|
||||||
|
|
|
@ -120,8 +120,10 @@ andMultipleBookingsField: (NSString *) newMultipleBookingsField;
|
||||||
- (void) setContactMapping: (NSDictionary *) newMapping
|
- (void) setContactMapping: (NSDictionary *) newMapping
|
||||||
andObjectClasses: (NSArray *) newObjectClasses;
|
andObjectClasses: (NSArray *) newObjectClasses;
|
||||||
|
|
||||||
- (NGLdapEntry *) lookupGroupEntryByUID: (NSString *) theUID;
|
- (NGLdapEntry *) lookupGroupEntryByUID: (NSString *) theUID
|
||||||
- (NGLdapEntry *) lookupGroupEntryByEmail: (NSString *) theEmail;
|
inDomain: (NSString *) domain;
|
||||||
|
- (NGLdapEntry *) lookupGroupEntryByEmail: (NSString *) theEmail
|
||||||
|
inDomain: (NSString *) domain;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,7 @@ static Class NSStringK;
|
||||||
[multipleBookingsField release];
|
[multipleBookingsField release];
|
||||||
[MSExchangeHostname release];
|
[MSExchangeHostname release];
|
||||||
[modifiers release];
|
[modifiers release];
|
||||||
|
[displayName release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1242,6 +1243,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary *) lookupContactEntry: (NSString *) theID
|
- (NSDictionary *) lookupContactEntry: (NSString *) theID
|
||||||
|
inDomain: (NSString *) domain
|
||||||
{
|
{
|
||||||
NGLdapEntry *ldapEntry;
|
NGLdapEntry *ldapEntry;
|
||||||
EOQualifier *qualifier;
|
EOQualifier *qualifier;
|
||||||
|
@ -1339,12 +1341,14 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NGLdapEntry *) lookupGroupEntryByUID: (NSString *) theUID
|
- (NGLdapEntry *) lookupGroupEntryByUID: (NSString *) theUID
|
||||||
|
inDomain: (NSString *) domain
|
||||||
{
|
{
|
||||||
return [self _lookupGroupEntryByAttributes: [NSArray arrayWithObject: UIDField]
|
return [self _lookupGroupEntryByAttributes: [NSArray arrayWithObject: UIDField]
|
||||||
andValue: theUID];
|
andValue: theUID];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NGLdapEntry *) lookupGroupEntryByEmail: (NSString *) theEmail
|
- (NGLdapEntry *) lookupGroupEntryByEmail: (NSString *) theEmail
|
||||||
|
inDomain: (NSString *) domain
|
||||||
{
|
{
|
||||||
return [self _lookupGroupEntryByAttributes: mailFields
|
return [self _lookupGroupEntryByAttributes: mailFields
|
||||||
andValue: theEmail];
|
andValue: theEmail];
|
||||||
|
|
|
@ -50,6 +50,9 @@
|
||||||
andParentSource: systemDefaults];
|
andParentSource: systemDefaults];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!domainDefaults)
|
||||||
|
domainDefaults = [SOGoSystemDefaults sharedSystemDefaults];
|
||||||
|
|
||||||
return domainDefaults;
|
return domainDefaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@
|
||||||
uid = [theID hasPrefix: @"@"] ? [theID substringFromIndex: 1] : theID;
|
uid = [theID hasPrefix: @"@"] ? [theID substringFromIndex: 1] : theID;
|
||||||
|
|
||||||
return [SOGoGroup groupWithValue: uid
|
return [SOGoGroup groupWithValue: uid
|
||||||
andSourceSelector: @selector (lookupGroupEntryByUID:)
|
andSourceSelector: @selector (lookupGroupEntryByUID:inDomain:)
|
||||||
inDomain: domain];
|
inDomain: domain];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
inDomain: (NSString *) domain
|
inDomain: (NSString *) domain
|
||||||
{
|
{
|
||||||
return [SOGoGroup groupWithValue: theEmail
|
return [SOGoGroup groupWithValue: theEmail
|
||||||
andSourceSelector: @selector (lookupGroupEntryByEmail:)
|
andSourceSelector: @selector (lookupGroupEntryByEmail:inDomain:)
|
||||||
inDomain: domain];
|
inDomain: domain];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,9 +158,9 @@
|
||||||
|
|
||||||
// Our different sources might not all implements groups support
|
// Our different sources might not all implements groups support
|
||||||
if ([source respondsToSelector: theSelector])
|
if ([source respondsToSelector: theSelector])
|
||||||
entry = [source performSelector: theSelector
|
entry = [source performSelector: theSelector
|
||||||
withObject: theValue];
|
withObject: theValue
|
||||||
|
withObject: domain];
|
||||||
if (entry)
|
if (entry)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,9 @@
|
||||||
[NSException raise: NSInvalidArgumentException
|
[NSException raise: NSInvalidArgumentException
|
||||||
format: @"'_name' must not be an empty string"];
|
format: @"'_name' must not be an empty string"];
|
||||||
context = [[WOApplication application] context];
|
context = [[WOApplication application] context];
|
||||||
|
if (!context)
|
||||||
|
[self errorWithFormat: @"Error: initializing a SOGoObject (named %@) "
|
||||||
|
@"without wocontext", _name];
|
||||||
nameInContainer = [_name copy];
|
nameInContainer = [_name copy];
|
||||||
container = _container;
|
container = _container;
|
||||||
if ([self doesRetainContainer])
|
if ([self doesRetainContainer])
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#import "SOGoSystemDefaults.h"
|
#import "SOGoSystemDefaults.h"
|
||||||
|
#import "SOGoUserManager.h"
|
||||||
|
|
||||||
@implementation SOGoSession
|
@implementation SOGoSession
|
||||||
|
|
||||||
|
@ -262,7 +263,7 @@
|
||||||
// The domain is probably appended to the username;
|
// The domain is probably appended to the username;
|
||||||
// make sure it is defined as a domain in the configuration.
|
// make sure it is defined as a domain in the configuration.
|
||||||
*theDomain = [*theLogin substringFromIndex: (r.location + r.length)];
|
*theDomain = [*theLogin substringFromIndex: (r.location + r.length)];
|
||||||
if (![[sd domainIds] containsObject: *theDomain])
|
if (![[SOGoUserManager sharedUserManager] isDomainDefined: *theDomain])
|
||||||
*theDomain = nil;
|
*theDomain = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,8 @@
|
||||||
newPassword: (NSString *) newPassword
|
newPassword: (NSString *) newPassword
|
||||||
perr: (SOGoPasswordPolicyError *) perr;
|
perr: (SOGoPasswordPolicyError *) perr;
|
||||||
|
|
||||||
- (NSDictionary *) lookupContactEntry: (NSString *) theID;
|
- (NSDictionary *) lookupContactEntry: (NSString *) theID
|
||||||
|
inDomain: (NSString *) domain;
|
||||||
- (NSDictionary *) lookupContactEntryWithUIDorEmail: (NSString *) entryID
|
- (NSDictionary *) lookupContactEntryWithUIDorEmail: (NSString *) entryID
|
||||||
inDomain: (NSString *) domain;
|
inDomain: (NSString *) domain;
|
||||||
|
|
||||||
|
|
|
@ -261,7 +261,7 @@ _injectConfigurationFromFile (NSMutableDictionary *defaultsDict,
|
||||||
|
|
||||||
- (BOOL) enableDomainBasedUID
|
- (BOOL) enableDomainBasedUID
|
||||||
{
|
{
|
||||||
return ([[self domainIds] count] > 0 && [self boolForKey: @"SOGoEnableDomainBasedUID"]);
|
return [self boolForKey: @"SOGoEnableDomainBasedUID"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) loginDomains
|
- (NSArray *) loginDomains
|
||||||
|
|
|
@ -165,7 +165,7 @@
|
||||||
// The domain is probably appended to the username;
|
// The domain is probably appended to the username;
|
||||||
// make sure it is defined as a domain in the configuration.
|
// make sure it is defined as a domain in the configuration.
|
||||||
domain = [newLogin substringFromIndex: (r.location + r.length)];
|
domain = [newLogin substringFromIndex: (r.location + r.length)];
|
||||||
if ([[sd domainIds] containsObject: domain] &&
|
if ([[SOGoUserManager sharedUserManager] isDomainDefined: domain] &&
|
||||||
![sd enableDomainBasedUID])
|
![sd enableDomainBasedUID])
|
||||||
newLogin = [newLogin substringToIndex: r.location];
|
newLogin = [newLogin substringToIndex: r.location];
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
- (NSArray *) sourceIDsInDomain: (NSString *) domain;
|
- (NSArray *) sourceIDsInDomain: (NSString *) domain;
|
||||||
- (NSArray *) authenticationSourceIDsInDomain: (NSString *) domain;
|
- (NSArray *) authenticationSourceIDsInDomain: (NSString *) domain;
|
||||||
- (NSArray *) addressBookSourceIDsInDomain: (NSString *) domain;
|
- (NSArray *) addressBookSourceIDsInDomain: (NSString *) domain;
|
||||||
|
- (BOOL) isDomainDefined: (NSString *) domain;
|
||||||
|
|
||||||
- (NSObject <SOGoSource> *) sourceWithID: (NSString *) sourceID;
|
- (NSObject <SOGoSource> *) sourceWithID: (NSString *) sourceID;
|
||||||
- (NSDictionary *) metadataForSourceID: (NSString *) sourceID;
|
- (NSDictionary *) metadataForSourceID: (NSString *) sourceID;
|
||||||
|
|
|
@ -67,10 +67,12 @@ static Class NSNullK;
|
||||||
|
|
||||||
if (type)
|
if (type)
|
||||||
{
|
{
|
||||||
if ([type isEqualToString: @"ldap"])
|
if ([type caseInsensitiveCompare: @"ldap"] == NSOrderedSame)
|
||||||
sourceClass = @"LDAPSource";
|
sourceClass = @"LDAPSource";
|
||||||
else if ([type isEqualToString: @"sql"])
|
else if ([type caseInsensitiveCompare: @"sql"] == NSOrderedSame)
|
||||||
sourceClass = @"SQLSource";
|
sourceClass = @"SQLSource";
|
||||||
|
else if (NSClassFromString(type))
|
||||||
|
sourceClass = type;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[NSException raise: @"SOGoUserManagerRegistryException"
|
[NSException raise: @"SOGoUserManagerRegistryException"
|
||||||
|
@ -104,65 +106,58 @@ static Class NSNullK;
|
||||||
NSString *sourceID, *value, *type;
|
NSString *sourceID, *value, *type;
|
||||||
NSMutableDictionary *metadata;
|
NSMutableDictionary *metadata;
|
||||||
NSObject <SOGoSource> *sogoSource;
|
NSObject <SOGoSource> *sogoSource;
|
||||||
BOOL isAddressBook, result;
|
BOOL isAddressBook;
|
||||||
Class c;
|
Class c;
|
||||||
|
|
||||||
result = NO;
|
|
||||||
sourceID = [udSource objectForKey: @"id"];
|
sourceID = [udSource objectForKey: @"id"];
|
||||||
if ([sourceID length] > 0)
|
if (!sourceID || [sourceID length] == 0)
|
||||||
{
|
{
|
||||||
if ([_sourcesMetadata objectForKey: sourceID])
|
[self errorWithFormat: @"attempted to register a contact/user source "
|
||||||
[self errorWithFormat: @"attempted to register a contact/user source"
|
@"without id (skipped)"];
|
||||||
@" with duplicated id (%@)", sourceID];
|
return NO;
|
||||||
else
|
}
|
||||||
{
|
if ([_sourcesMetadata objectForKey: sourceID])
|
||||||
type = [[udSource objectForKey: @"type"] lowercaseString];
|
{
|
||||||
c = NSClassFromString([_registry sourceClassForType: type]);
|
[self errorWithFormat: @"attempted to register a contact/user source "
|
||||||
sogoSource = [c sourceFromUDSource: udSource inDomain: domain];
|
@"with duplicated id (%@)", sourceID];
|
||||||
if (sourceID)
|
return NO;
|
||||||
[_sources setObject: sogoSource forKey: sourceID];
|
}
|
||||||
else
|
|
||||||
[self errorWithFormat: @"id field missing in an user source,"
|
|
||||||
@" check the SOGoUserSources defaults"];
|
|
||||||
metadata = [NSMutableDictionary dictionary];
|
|
||||||
if (domain)
|
|
||||||
[metadata setObject: domain forKey: @"domain"];
|
|
||||||
value = [udSource objectForKey: @"canAuthenticate"];
|
|
||||||
if (value)
|
|
||||||
[metadata setObject: value forKey: @"canAuthenticate"];
|
|
||||||
value = [udSource objectForKey: @"isAddressBook"];
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
[metadata setObject: value forKey: @"isAddressBook"];
|
|
||||||
isAddressBook = [value boolValue];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
isAddressBook = NO;
|
|
||||||
value = [udSource objectForKey: @"displayName"];
|
|
||||||
if (value)
|
|
||||||
[metadata setObject: value forKey: @"displayName"];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (isAddressBook)
|
|
||||||
[self errorWithFormat: @"addressbook source '%@' has"
|
|
||||||
@" no displayname", sourceID];
|
|
||||||
}
|
|
||||||
value = [udSource objectForKey: @"MailFieldNames"];
|
|
||||||
if (value)
|
|
||||||
[metadata setObject: value forKey: @"MailFieldNames"];
|
|
||||||
value = [udSource objectForKey: @"SearchFieldNames"];
|
|
||||||
if (value)
|
|
||||||
[metadata setObject: value forKey: @"SearchFieldNames"];
|
|
||||||
|
|
||||||
[_sourcesMetadata setObject: metadata forKey: sourceID];
|
type = [udSource objectForKey: @"type"];
|
||||||
result = YES;
|
c = NSClassFromString([_registry sourceClassForType: type]);
|
||||||
}
|
sogoSource = [c sourceFromUDSource: udSource inDomain: domain];
|
||||||
|
[_sources setObject: sogoSource forKey: sourceID];
|
||||||
|
|
||||||
|
metadata = [NSMutableDictionary dictionary];
|
||||||
|
if (domain)
|
||||||
|
[metadata setObject: domain forKey: @"domain"];
|
||||||
|
value = [udSource objectForKey: @"canAuthenticate"];
|
||||||
|
if (value)
|
||||||
|
[metadata setObject: value forKey: @"canAuthenticate"];
|
||||||
|
value = [udSource objectForKey: @"isAddressBook"];
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
[metadata setObject: value forKey: @"isAddressBook"];
|
||||||
|
isAddressBook = [value boolValue];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[self errorWithFormat: @"attempted to register a contact/user source"
|
isAddressBook = NO;
|
||||||
@" without id (skipped)"];
|
value = [udSource objectForKey: @"displayName"];
|
||||||
|
if (value)
|
||||||
|
[metadata setObject: value forKey: @"displayName"];
|
||||||
|
else if (isAddressBook)
|
||||||
|
[self errorWithFormat: @"addressbook source '%@' has no displayname", sourceID];
|
||||||
|
|
||||||
return result;
|
value = [udSource objectForKey: @"MailFieldNames"];
|
||||||
|
if (value)
|
||||||
|
[metadata setObject: value forKey: @"MailFieldNames"];
|
||||||
|
value = [udSource objectForKey: @"SearchFieldNames"];
|
||||||
|
if (value)
|
||||||
|
[metadata setObject: value forKey: @"SearchFieldNames"];
|
||||||
|
|
||||||
|
[_sourcesMetadata setObject: metadata forKey: sourceID];
|
||||||
|
|
||||||
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) _registerSourcesInDomain: (NSString *) domain
|
- (int) _registerSourcesInDomain: (NSString *) domain
|
||||||
|
@ -171,11 +166,7 @@ static Class NSNullK;
|
||||||
unsigned int count, max, total;
|
unsigned int count, max, total;
|
||||||
SOGoDomainDefaults *dd;
|
SOGoDomainDefaults *dd;
|
||||||
|
|
||||||
if (domain)
|
dd = [SOGoDomainDefaults defaultsForDomain: domain];
|
||||||
dd = [SOGoDomainDefaults defaultsForDomain: domain];
|
|
||||||
else
|
|
||||||
dd = [SOGoSystemDefaults sharedSystemDefaults];
|
|
||||||
|
|
||||||
userSources = [dd userSources];
|
userSources = [dd userSources];
|
||||||
max = [userSources count];
|
max = [userSources count];
|
||||||
total = 0;
|
total = 0;
|
||||||
|
@ -305,6 +296,35 @@ static Class NSNullK;
|
||||||
return sourceIDs;
|
return sourceIDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) isDomainDefined: (NSString *) domain
|
||||||
|
{
|
||||||
|
NSEnumerator *allIDs;
|
||||||
|
NSArray *ids;
|
||||||
|
NSString *currentID, *sourceDomain;
|
||||||
|
SOGoSystemDefaults *sd;
|
||||||
|
|
||||||
|
if (!domain) return NO;
|
||||||
|
|
||||||
|
ids = [_sources allKeys];
|
||||||
|
if ([ids containsObject: domain])
|
||||||
|
// FIXME check SOGoMailDomain?
|
||||||
|
// Now source id is being considered as the domain
|
||||||
|
return YES;
|
||||||
|
|
||||||
|
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||||
|
if ([sd enableDomainBasedUID])
|
||||||
|
{
|
||||||
|
allIDs = [ids objectEnumerator];
|
||||||
|
while ((currentID = [allIDs nextObject]))
|
||||||
|
{
|
||||||
|
sourceDomain = [[_sources objectForKey: currentID] domain];
|
||||||
|
if (!sourceDomain) // source that can identify any domain
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
- (NSString *) displayNameForSourceWithID: (NSString *) sourceID
|
- (NSString *) displayNameForSourceWithID: (NSString *) sourceID
|
||||||
{
|
{
|
||||||
NSDictionary *metadata;
|
NSDictionary *metadata;
|
||||||
|
@ -328,7 +348,6 @@ static Class NSNullK;
|
||||||
{
|
{
|
||||||
NSDictionary *contactInfos;
|
NSDictionary *contactInfos;
|
||||||
|
|
||||||
// NSLog (@"getEmailForUID: %@", uid);
|
|
||||||
contactInfos = [self contactInfosForUserWithUIDorEmail: uid];
|
contactInfos = [self contactInfosForUserWithUIDorEmail: uid];
|
||||||
|
|
||||||
return [contactInfos objectForKey: @"c_email"];
|
return [contactInfos objectForKey: @"c_email"];
|
||||||
|
@ -345,8 +364,7 @@ static Class NSNullK;
|
||||||
if ([cn length] > 0)
|
if ([cn length] > 0)
|
||||||
{
|
{
|
||||||
if ([email length] > 0)
|
if ([email length] > 0)
|
||||||
fullEmail = [NSString stringWithFormat: @"%@ <%@>",
|
fullEmail = [NSString stringWithFormat: @"%@ <%@>", cn, email];
|
||||||
cn, email];
|
|
||||||
else
|
else
|
||||||
fullEmail = cn;
|
fullEmail = cn;
|
||||||
}
|
}
|
||||||
|
@ -369,11 +387,7 @@ static Class NSNullK;
|
||||||
login = [contactInfos objectForKey: @"c_imaplogin"];
|
login = [contactInfos objectForKey: @"c_imaplogin"];
|
||||||
if (login == nil)
|
if (login == nil)
|
||||||
{
|
{
|
||||||
if ([domain length])
|
dd = [SOGoDomainDefaults defaultsForDomain: domain];
|
||||||
dd = [SOGoDomainDefaults defaultsForDomain: domain];
|
|
||||||
else
|
|
||||||
dd = [SOGoSystemDefaults sharedSystemDefaults];
|
|
||||||
|
|
||||||
if ([dd forceExternalLoginWithEmail])
|
if ([dd forceExternalLoginWithEmail])
|
||||||
{
|
{
|
||||||
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||||
|
@ -415,8 +429,8 @@ static Class NSNullK;
|
||||||
- (BOOL) _sourceChangePasswordForLogin: (NSString *) login
|
- (BOOL) _sourceChangePasswordForLogin: (NSString *) login
|
||||||
inDomain: (NSString *) domain
|
inDomain: (NSString *) domain
|
||||||
oldPassword: (NSString *) oldPassword
|
oldPassword: (NSString *) oldPassword
|
||||||
newPassword: (NSString *) newPassword
|
newPassword: (NSString *) newPassword
|
||||||
perr: (SOGoPasswordPolicyError *) perr
|
perr: (SOGoPasswordPolicyError *) perr
|
||||||
{
|
{
|
||||||
NSObject <SOGoSource> *sogoSource;
|
NSObject <SOGoSource> *sogoSource;
|
||||||
NSEnumerator *authIDs;
|
NSEnumerator *authIDs;
|
||||||
|
@ -465,7 +479,24 @@ static Class NSNullK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkOK && *domain == nil)
|
if (checkOK && *domain == nil)
|
||||||
*domain = [sogoSource domain];
|
{
|
||||||
|
SOGoSystemDefaults *sd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||||
|
BOOL multidomainSource = [sd enableDomainBasedUID] &&
|
||||||
|
[sogoSource domain] == nil;
|
||||||
|
if (multidomainSource)
|
||||||
|
{
|
||||||
|
NSArray *parts = [login componentsSeparatedByString: @"@"];
|
||||||
|
if ([parts count] != 2)
|
||||||
|
{
|
||||||
|
[self errorWithFormat: @"Authenticated with multidomain source "
|
||||||
|
@"but login is not an email (%@).", login];
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
*domain = [parts objectAtIndex: 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*domain = [sogoSource domain];
|
||||||
|
}
|
||||||
|
|
||||||
return checkOK;
|
return checkOK;
|
||||||
}
|
}
|
||||||
|
@ -669,9 +700,9 @@ static Class NSNullK;
|
||||||
//
|
//
|
||||||
- (BOOL) changePasswordForLogin: (NSString *) login
|
- (BOOL) changePasswordForLogin: (NSString *) login
|
||||||
inDomain: (NSString *) domain
|
inDomain: (NSString *) domain
|
||||||
oldPassword: (NSString *) oldPassword
|
oldPassword: (NSString *) oldPassword
|
||||||
newPassword: (NSString *) newPassword
|
newPassword: (NSString *) newPassword
|
||||||
perr: (SOGoPasswordPolicyError *) perr
|
perr: (SOGoPasswordPolicyError *) perr
|
||||||
{
|
{
|
||||||
NSString *jsonUser, *userLogin;
|
NSString *jsonUser, *userLogin;
|
||||||
NSMutableDictionary *currentUser;
|
NSMutableDictionary *currentUser;
|
||||||
|
@ -720,21 +751,19 @@ static Class NSNullK;
|
||||||
SOGoDomainDefaults *dd;
|
SOGoDomainDefaults *dd;
|
||||||
|
|
||||||
domain = [contact objectForKey: @"c_domain"];
|
domain = [contact objectForKey: @"c_domain"];
|
||||||
if ([domain length])
|
dd = [SOGoDomainDefaults defaultsForDomain: domain];
|
||||||
dd = [SOGoDomainDefaults defaultsForDomain: domain];
|
|
||||||
else
|
|
||||||
dd = [SOGoSystemDefaults sharedSystemDefaults];
|
|
||||||
emails = [contact objectForKey: @"emails"];
|
emails = [contact objectForKey: @"emails"];
|
||||||
uid = [contact objectForKey: @"c_uid"];
|
if ([emails count] == 0)
|
||||||
if ([uid rangeOfString: @"@"].location == NSNotFound)
|
{
|
||||||
systemEmail
|
uid = [contact objectForKey: @"c_uid"];
|
||||||
= [NSString stringWithFormat: @"%@@%@", uid, [dd mailDomain]];
|
if ([uid rangeOfString: @"@"].location == NSNotFound)
|
||||||
else
|
systemEmail = [NSString stringWithFormat: @"%@@%@", uid, [dd mailDomain]];
|
||||||
systemEmail = uid;
|
else
|
||||||
|
systemEmail = uid;
|
||||||
// We always add the system email, which will always be returned
|
// We always add the system email, which will always be returned
|
||||||
// by SOGoUser -systemEmail.
|
// by SOGoUser -systemEmail.
|
||||||
[emails addObject: systemEmail];
|
[emails addObject: systemEmail];
|
||||||
|
}
|
||||||
[contact setObject: [emails objectAtIndex: 0] forKey: @"c_email"];
|
[contact setObject: [emails objectAtIndex: 0] forKey: @"c_email"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,7 +933,7 @@ static Class NSNullK;
|
||||||
[user setObject: [NSNumber numberWithBool: YES]
|
[user setObject: [NSNumber numberWithBool: YES]
|
||||||
forKey: @"CalendarAccess"];
|
forKey: @"CalendarAccess"];
|
||||||
[user setObject: [NSNumber numberWithBool: NO]
|
[user setObject: [NSNumber numberWithBool: NO]
|
||||||
forKey: @"MailAccess"];
|
forKey: @"MailAccess"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
|
@ -933,7 +962,7 @@ static Class NSNullK;
|
||||||
// The domain is probably appended to the username;
|
// The domain is probably appended to the username;
|
||||||
// make sure it is a defined domain in the configuration.
|
// make sure it is a defined domain in the configuration.
|
||||||
domain = [uid substringFromIndex: (r.location + r.length)];
|
domain = [uid substringFromIndex: (r.location + r.length)];
|
||||||
if ([[sd domainIds] containsObject: domain])
|
if ([self isDomainDefined: domain])
|
||||||
username = [uid substringToIndex: r.location];
|
username = [uid substringToIndex: r.location];
|
||||||
else
|
else
|
||||||
domain = nil;
|
domain = nil;
|
||||||
|
@ -977,29 +1006,29 @@ static Class NSNullK;
|
||||||
if ([currentUser isKindOfClass: NSNullK])
|
if ([currentUser isKindOfClass: NSNullK])
|
||||||
currentUser = nil;
|
currentUser = nil;
|
||||||
else if (!([currentUser objectForKey: @"emails"]
|
else if (!([currentUser objectForKey: @"emails"]
|
||||||
&& [currentUser objectForKey: @"cn"]))
|
&& [currentUser objectForKey: @"cn"]))
|
||||||
{
|
{
|
||||||
// We make sure that we either have no occurence of a cache entry or
|
// We make sure that we either have no occurence of a cache entry or
|
||||||
// that we have an occurence with only a cached password. In the
|
// that we have an occurence with only a cached password. In the
|
||||||
// latter case, we update the entry with the remaining information
|
// latter case, we update the entry with the remaining information
|
||||||
// and recache the value.
|
// and recache the value.
|
||||||
if (!currentUser ||
|
if (!currentUser ||
|
||||||
([currentUser count] == 1 && [currentUser objectForKey: @"password"]) ||
|
([currentUser count] == 1 && [currentUser objectForKey: @"password"]) ||
|
||||||
([currentUser count] == 2 && [currentUser objectForKey: @"password"] && [currentUser objectForKey: @"DomainLessLogin"]))
|
([currentUser count] == 2 && [currentUser objectForKey: @"password"] && [currentUser objectForKey: @"DomainLessLogin"]))
|
||||||
{
|
{
|
||||||
newUser = YES;
|
newUser = YES;
|
||||||
|
|
||||||
if (!currentUser)
|
if (!currentUser)
|
||||||
currentUser = [NSMutableDictionary dictionary];
|
currentUser = [NSMutableDictionary dictionary];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
newUser = NO;
|
newUser = NO;
|
||||||
[self _fillContactInfosForUser: currentUser
|
[self _fillContactInfosForUser: currentUser
|
||||||
withUIDorEmail: aUID
|
withUIDorEmail: aUID
|
||||||
inDomain: domain];
|
inDomain: domain];
|
||||||
if (newUser)
|
if (newUser)
|
||||||
{
|
{
|
||||||
if ([[currentUser objectForKey: @"c_uid"] length] == 0)
|
if ([[currentUser objectForKey: @"c_uid"] length] == 0)
|
||||||
{
|
{
|
||||||
[self _retainUser: (NSDictionary *) [NSNull null]
|
[self _retainUser: (NSDictionary *) [NSNull null]
|
||||||
withLogin: cacheUid];
|
withLogin: cacheUid];
|
||||||
|
@ -1022,7 +1051,7 @@ static Class NSNullK;
|
||||||
[self _retainUser: currentUser withLogin: cacheUid];
|
[self _retainUser: currentUser withLogin: cacheUid];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
currentUser = nil;
|
currentUser = nil;
|
||||||
|
@ -1048,7 +1077,7 @@ static Class NSNullK;
|
||||||
while ((sourceID = [sources nextObject]))
|
while ((sourceID = [sources nextObject]))
|
||||||
{
|
{
|
||||||
currentSource = [_sources objectForKey: sourceID];
|
currentSource = [_sources objectForKey: sourceID];
|
||||||
contact = [currentSource lookupContactEntry: uid];
|
contact = [currentSource lookupContactEntry: uid inDomain: domain];
|
||||||
if (contact)
|
if (contact)
|
||||||
[contacts addObject: contact];
|
[contacts addObject: contact];
|
||||||
}
|
}
|
||||||
|
@ -1077,30 +1106,30 @@ static Class NSNullK;
|
||||||
{
|
{
|
||||||
uid = [userEntry objectForKey: @"c_uid"];
|
uid = [userEntry objectForKey: @"c_uid"];
|
||||||
if ([uid length])
|
if ([uid length])
|
||||||
{
|
{
|
||||||
returnContact = [compactContacts objectForKey: uid];
|
returnContact = [compactContacts objectForKey: uid];
|
||||||
if (!returnContact)
|
if (!returnContact)
|
||||||
{
|
{
|
||||||
returnContact = [NSMutableDictionary dictionary];
|
returnContact = [NSMutableDictionary dictionary];
|
||||||
[returnContact setObject: uid forKey: @"c_uid"];
|
[returnContact setObject: uid forKey: @"c_uid"];
|
||||||
source = [userEntry objectForKey: @"source"];
|
source = [userEntry objectForKey: @"source"];
|
||||||
if (source)
|
if (source)
|
||||||
[returnContact setObject: source forKey: @"source"];
|
[returnContact setObject: source forKey: @"source"];
|
||||||
[compactContacts setObject: returnContact forKey: uid];
|
[compactContacts setObject: returnContact forKey: uid];
|
||||||
}
|
}
|
||||||
if (![[returnContact objectForKey: @"c_name"] length])
|
if (![[returnContact objectForKey: @"c_name"] length])
|
||||||
[returnContact setObject: [userEntry objectForKey: @"c_name"]
|
[returnContact setObject: [userEntry objectForKey: @"c_name"]
|
||||||
forKey: @"c_name"];
|
forKey: @"c_name"];
|
||||||
if (![[returnContact objectForKey: @"cn"] length])
|
if (![[returnContact objectForKey: @"cn"] length])
|
||||||
[returnContact setObject: [userEntry objectForKey: @"c_cn"]
|
[returnContact setObject: [userEntry objectForKey: @"c_cn"]
|
||||||
forKey: @"cn"];
|
forKey: @"cn"];
|
||||||
emails = [returnContact objectForKey: @"emails"];
|
emails = [returnContact objectForKey: @"emails"];
|
||||||
if (!emails)
|
if (!emails)
|
||||||
{
|
{
|
||||||
emails = [NSMutableArray array];
|
emails = [NSMutableArray array];
|
||||||
[returnContact setObject: emails forKey: @"emails"];
|
[returnContact setObject: emails forKey: @"emails"];
|
||||||
}
|
}
|
||||||
email = [userEntry objectForKey: @"mail"];
|
email = [userEntry objectForKey: @"mail"];
|
||||||
if ([email isKindOfClass: [NSArray class]])
|
if ([email isKindOfClass: [NSArray class]])
|
||||||
{
|
{
|
||||||
allEmails = (NSArray *) email;
|
allEmails = (NSArray *) email;
|
||||||
|
@ -1112,22 +1141,22 @@ static Class NSNullK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (email && ![emails containsObject: email])
|
else if (email && ![emails containsObject: email])
|
||||||
[emails addObject: email];
|
[emails addObject: email];
|
||||||
email = [userEntry objectForKey: @"mozillasecondemail"];
|
email = [userEntry objectForKey: @"mozillasecondemail"];
|
||||||
if (email && ![emails containsObject: email])
|
if (email && ![emails containsObject: email])
|
||||||
[emails addObject: email];
|
[emails addObject: email];
|
||||||
email = [userEntry objectForKey: @"xmozillasecondemail"];
|
email = [userEntry objectForKey: @"xmozillasecondemail"];
|
||||||
if (email && ![emails containsObject: email])
|
if (email && ![emails containsObject: email])
|
||||||
[emails addObject: email];
|
[emails addObject: email];
|
||||||
info = [userEntry objectForKey: @"c_info"];
|
info = [userEntry objectForKey: @"c_info"];
|
||||||
if ([info length] > 0
|
if ([info length] > 0
|
||||||
&& ![[returnContact objectForKey: @"c_info"] length])
|
&& ![[returnContact objectForKey: @"c_info"] length])
|
||||||
[returnContact setObject: info forKey: @"c_info"];
|
[returnContact setObject: info forKey: @"c_info"];
|
||||||
[self _fillContactMailRecords: returnContact];
|
[self _fillContactMailRecords: returnContact];
|
||||||
isGroup = [userEntry objectForKey: @"isGroup"];
|
isGroup = [userEntry objectForKey: @"isGroup"];
|
||||||
if (isGroup)
|
if (isGroup)
|
||||||
[returnContact setObject: isGroup forKey: @"isGroup"];
|
[returnContact setObject: isGroup forKey: @"isGroup"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newContacts = [compactContacts allValues];
|
newContacts = [compactContacts allValues];
|
||||||
|
@ -1136,7 +1165,7 @@ static Class NSNullK;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) _fetchEntriesInSources: (NSArray *) sourcesList
|
- (NSArray *) _fetchEntriesInSources: (NSArray *) sourcesList
|
||||||
matching: (NSString *) filter
|
matching: (NSString *) filter
|
||||||
inDomain: (NSString *) domain
|
inDomain: (NSString *) domain
|
||||||
{
|
{
|
||||||
NSMutableArray *contacts;
|
NSMutableArray *contacts;
|
||||||
|
@ -1150,7 +1179,7 @@ static Class NSNullK;
|
||||||
{
|
{
|
||||||
currentSource = [_sources objectForKey: sourceID];
|
currentSource = [_sources objectForKey: sourceID];
|
||||||
[contacts addObjectsFromArray:
|
[contacts addObjectsFromArray:
|
||||||
[currentSource fetchContactsMatching: filter
|
[currentSource fetchContactsMatching: filter
|
||||||
inDomain: domain]];
|
inDomain: domain]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -620,8 +620,9 @@
|
||||||
|
|
||||||
|
|
||||||
- (NSDictionary *) lookupContactEntry: (NSString *) theID
|
- (NSDictionary *) lookupContactEntry: (NSString *) theID
|
||||||
|
inDomain: (NSString *) domain
|
||||||
{
|
{
|
||||||
return [self _lookupContactEntry: theID considerEmail: NO inDomain: nil];
|
return [self _lookupContactEntry: theID considerEmail: NO inDomain: domain];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary *) lookupContactEntryWithUIDorEmail: (NSString *) entryID
|
- (NSDictionary *) lookupContactEntryWithUIDorEmail: (NSString *) entryID
|
||||||
|
|
|
@ -363,6 +363,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) extractUserLDIFRecord: (NSString *) uid
|
- (BOOL) extractUserLDIFRecord: (NSString *) uid
|
||||||
|
inDomain: (NSString *) domain
|
||||||
intoRecord: (NSMutableDictionary *) userRecord
|
intoRecord: (NSMutableDictionary *) userRecord
|
||||||
{
|
{
|
||||||
NSEnumerator *ldapSources;
|
NSEnumerator *ldapSources;
|
||||||
|
@ -375,11 +376,11 @@
|
||||||
lm = [SOGoUserManager sharedUserManager];
|
lm = [SOGoUserManager sharedUserManager];
|
||||||
|
|
||||||
done = NO;
|
done = NO;
|
||||||
ldapSources = [[lm authenticationSourceIDsInDomain: nil] objectEnumerator];
|
ldapSources = [[lm authenticationSourceIDsInDomain: domain] objectEnumerator];
|
||||||
while (!done && (sourceID = [ldapSources nextObject]))
|
while (!done && (sourceID = [ldapSources nextObject]))
|
||||||
{
|
{
|
||||||
currentSource = [lm sourceWithID: sourceID];
|
currentSource = [lm sourceWithID: sourceID];
|
||||||
userEntry = [currentSource lookupContactEntry: uid];
|
userEntry = [currentSource lookupContactEntry: uid inDomain: domain];
|
||||||
if (userEntry)
|
if (userEntry)
|
||||||
{
|
{
|
||||||
[userRecord setObject: [userEntry ldifRecordAsString]
|
[userRecord setObject: [userEntry ldifRecordAsString]
|
||||||
|
@ -411,7 +412,7 @@
|
||||||
|
|
||||||
- (BOOL) exportUser: (NSDictionary *) theUser
|
- (BOOL) exportUser: (NSDictionary *) theUser
|
||||||
{
|
{
|
||||||
NSString *exportPath, *gcsUID, *ldapUID;
|
NSString *exportPath, *gcsUID, *ldapUID, *domain;
|
||||||
NSMutableDictionary *userRecord;
|
NSMutableDictionary *userRecord;
|
||||||
SOGoSystemDefaults *sd;
|
SOGoSystemDefaults *sd;
|
||||||
|
|
||||||
|
@ -420,7 +421,7 @@
|
||||||
|
|
||||||
ldapUID = [theUser objectForKey: @"c_uid"];
|
ldapUID = [theUser objectForKey: @"c_uid"];
|
||||||
exportPath = [directory stringByAppendingPathComponent: ldapUID];
|
exportPath = [directory stringByAppendingPathComponent: ldapUID];
|
||||||
|
domain = [theUser objectForKey: @"c_domain"];
|
||||||
gcsUID = [theUser objectForKey: @"c_uid"];
|
gcsUID = [theUser objectForKey: @"c_uid"];
|
||||||
|
|
||||||
if ([sd enableDomainBasedUID] && [gcsUID rangeOfString: @"@"].location == NSNotFound)
|
if ([sd enableDomainBasedUID] && [gcsUID rangeOfString: @"@"].location == NSNotFound)
|
||||||
|
@ -430,6 +431,7 @@
|
||||||
return ([self extractUserFolders: gcsUID
|
return ([self extractUserFolders: gcsUID
|
||||||
intoRecord: userRecord]
|
intoRecord: userRecord]
|
||||||
&& [self extractUserLDIFRecord: ldapUID
|
&& [self extractUserLDIFRecord: ldapUID
|
||||||
|
inDomain: domain
|
||||||
intoRecord: userRecord]
|
intoRecord: userRecord]
|
||||||
&& [self extractUserPreferences: gcsUID
|
&& [self extractUserPreferences: gcsUID
|
||||||
intoRecord: userRecord]
|
intoRecord: userRecord]
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 843d63ec5520d313eb327d2d99606e9f6177912e
|
Subproject commit 80a8929f513c508da49a347a2a52bef48c15fb2a
|
Loading…
Reference in New Issue