Compare commits

...
Author SHA1 Message Date
Ludovic Marcotte 5bbe700dcf Changes for the 2.2.17 release 2015-03-24 11:07:12 -04:00
Ludovic Marcotte 15ab383770 now possible to configure objectClass names for LDAP groups using GroupObjectClasses (#1499) 2015-03-24 11:07:12 -04:00
Ludovic Marcotte c46e270f80 Code cleanups 2015-03-24 11:07:12 -04:00
Francis Lachapelle 881d99262d Improve event attendees editor
- Avoid repetitive AJAX queries;
- Improve handling of daylight changes.
2015-03-24 11:07:12 -04:00
Ludovic Marcotte 4d52c9d7e4 improvements to EAS SyncKey handling to avoid missing mails (#3048, #3058) 2015-03-24 11:07:12 -04:00
Ludovic Marcotte 326635d81b enable by default HTML mails support using EAS on Windows and BB phones 2015-03-24 11:07:12 -04:00
Ludovic Marcotte ee28801d9a now favor login@domain as the default email address if multiple mail: fields are specified 2015-03-24 11:07:12 -04:00
Ludovic Marcotte 88f675bbc6 improved GetItemEstimate to count all vasnished/deleted mails too 2015-03-24 11:07:11 -04:00
Ludovic Marcotte d45c22523e prevent potential freebusy lookup crashes during timezone changes with repetitive events 2015-03-24 11:07:11 -04:00
Ludovic Marcotte 5fb8f35951 immediately delete mails from EAS clients when they are marked as deleted on the IMAP server 2015-03-24 11:07:11 -04:00
Ludovic Marcotte e3e716bb54 Fix compilation warning and error 2015-03-24 11:07:11 -04:00
Ludovic Marcotte db20513cf5 properly fallback over EAS to UTF-8 and then Latin1 for messages w/o charset (#3103) 2015-03-24 11:07:11 -04:00
Ludovic Marcotte a64d4bb2cd support for mail prority using EAS 2015-03-24 11:07:11 -04:00
Ludovic Marcotte 8577cc004f Always add DisplayName no matter EAS client version 2015-03-24 11:07:11 -04:00
Francis Lachapelle 4e68ec9d52 Fix Language-Region tags in Web interface
Fixes #3121
2015-03-24 11:07:11 -04:00
Ludovic Marcotte d82f05de75 Documented NGMimeBuildMimeTempDirectory 2015-03-24 11:07:11 -04:00
Ludovic Marcotte baba19711b Fix for bug #3138 2015-03-24 11:07:11 -04:00
Francis Lachapelle 99be2b5a12 Fix issues with freebusy (Web, busyOffHours) 2015-03-24 11:07:11 -04:00
Jens Erat 69962862a3 Remove obsolete archive string from translations 2015-03-24 11:07:11 -04:00
Jens Erat 6df4d2314f Rename "Archive" to "Export" in Webmail, ctd.
Fixes #2758 also for non-Inbox folders
2015-03-24 11:07:11 -04:00
Francis Lachapelle 364e2fdcdf Return a single phone number in JSON contacts list 2015-03-24 11:07:11 -04:00
Francis Lachapelle 42c382d2f7 Fix possible JS exception in Contacts module 2015-03-24 11:07:10 -04:00
Francis Lachapelle 742ace9252 Fix exception in SOGoUserManager 2015-03-24 11:07:10 -04:00
Francis Lachapelle e3a8e17513 Fix contacts lookup by UID
When looking for a specific contact UID, we no longer match a pattern
that could return multiple results. We search for the exact UID only.
2015-03-24 11:07:10 -04:00
Francis Lachapelle 313ed7f4bc Fix some gcc warnings 2015-03-24 11:07:10 -04:00
Ludovic Marcotte 8a35aaf47f use correct mail attachment elements for EAS 2.5 clients - patch from tfu 2015-03-24 11:07:10 -04:00
Ludovic Marcotte 6860ef83ae do not use syncKey from cache when davCollectionTag = -1 - patch from tfu 2015-03-24 11:07:10 -04:00
Ludovic Marcotte 950507626b SmartReply improvements for missing body attributes - patch from tfu 2015-03-24 11:07:10 -04:00
Ludovic Marcotte d2634ba783 use the correct body element for events for EAS 2.5 clients - patch from tfu 2015-03-24 11:07:10 -04:00
Ludovic Marcotte b6144aa29e fixed tasks disappearing issue with RoadSync - patch from tfu 2015-03-24 11:07:10 -04:00
Ludovic Marcotte 5bbf5ba844 use the correct mail body element for EAS 2.5 clients - patch from tfu 2015-03-24 11:07:10 -04:00
Ludovic Marcotte 7980ddaa29 fixed empty sync responses for EAS 2.5 and 12.0 clients - patch from tfu 2015-03-24 11:07:10 -04:00
Ludovic Marcotte 5836785967 multiple collections support for GetItemEstimate - patch from tfu 2015-03-24 11:07:10 -04:00
Ludovic Marcotte f6f64728c0 Fix for bug #3116 2015-03-24 11:07:10 -04:00
Ludovic Marcotte 1cf1088b93 Updated NEWS file regarding previous commit 2015-03-24 11:07:09 -04:00
Jesús García Sáez f2289ec17f Fix change password with DomainBasedUID
When users use full domain to login (SOGoEnableDomainBasedUID) the
user attributes in the cache were not being properly updated because
in this case the key is `uid@domain` instead of just `uid`.
2015-03-24 11:07:09 -04:00
Ludovic Marcotte d16eeb1a89 Merge to 2.2.16 2015-02-12 11:07:36 -05:00
Ludovic Marcotte 3ca94c60d0 Merge to 2.2.15 2015-01-30 11:10:11 -05:00
Ludovic Marcotte 74b27a771a Merge to 2.2.14 2015-01-20 08:35:54 -05:00
Ludovic Marcotte 2ae326c41f Merge to 2.2.13 2014-12-30 08:01:52 -05:00
Ludovic Marcotte 562d3db1a6 Merge to 2.2.12a 2014-12-19 09:04:01 -05:00
Ludovic Marcotte d3914ae8a8 Merge to 2.2.12 2014-12-18 08:57:15 -05:00
Ludovic Marcotte 97135f2afa Merge to 2.2.11a 2014-12-10 15:24:12 -05:00
Ludovic Marcotte 3e14825fe2 Merge to 2.2.11a 2014-12-10 14:25:11 -05:00
Ludovic Marcotte 93d190060e Merge to 2.2.11 2014-12-09 09:09:58 -05:00
Ludovic Marcotte 1f299c7a1a Merge to 2.2.10
Conflicts:
	NEWS
	Version
2014-11-21 09:17:28 -05:00
Ludovic Marcotte 74cfb901fd Updated for the 2.2.9a release 2014-09-29 15:20:22 -04:00
Ludovic Marcotte 065fd5d9b5 Simplified even more -safeString 2014-09-29 15:17:05 -04:00
Ludovic Marcotte bf547dd3fe Fixed sanitization char skipping and #2936 2014-09-29 15:15:30 -04:00
Francis Lachapelle 81e47c59cd Fix URL in documentation 2014-09-29 15:15:23 -04:00
Ludovic Marcotte 7862cda661 Merge to 2.2.9 2014-09-26 14:32:47 -04:00
Ludovic Marcotte 329552030b Merge to 2.2.8 2014-09-10 14:17:14 -04:00
Ludovic Marcotte 04904d8c61 Merge to 2.2.6 2014-07-02 11:41:46 -04:00
Francis Lachapelle f0b4a05c70 Merge to 2.2.5 2014-06-05 13:35:45 -04:00
Francis Lachapelle 95d6911f1a Merge to 2.2.4 2014-05-29 11:17:46 -04:00
Francis Lachapelle 48f98ef34e Merge to 2.2.3 2014-04-03 10:06:08 -04:00
Francis Lachapelle ae0c5eae77 Merge to 2.2.2 2014-03-21 15:39:00 -04:00
Francis Lachapelle 0c2d727057 Merge to 2.2.2 2014-03-21 15:33:55 -04:00
Francis Lachapelle 072f5f5a15 Merge to 2.2.1 2014-03-07 14:03:41 -05:00
Francis Lachapelle 1db85743a0 Merge to 2.2.0 2014-02-24 16:54:11 -05:00
Jean Raby 2cf66e037d Merge to 2.1.1 2013-11-19 14:00:22 -05:00
Francis Lachapelle 449d838dc2 Merge to 2.1.0 2013-11-07 14:43:19 -05:00
Francis Lachapelle c4bc215a47 Merge to 2.0.7 2013-07-23 10:02:39 -04:00
Francis Lachapelle c9936d7ecf Merge to 2.0.7 2013-07-23 08:38:44 -04:00
Francis Lachapelle 885e59a2af Merge to 2.0.7 2013-07-19 13:46:37 -04:00
Jean Raby bf398889bf Merge to 2.0.6b 2013-06-27 11:36:30 -04:00
Ludovic Marcotte e26e3d7307 Revert "Properly escape the foldername to avoid XSS issues"
This reverts commit 045b275b27.
2013-06-27 11:15:41 -04:00
Ludovic Marcotte 045b275b27 Properly escape the foldername to avoid XSS issues 2013-06-27 11:06:07 -04:00
Jean Raby 7ec1973e0f Merge to 2.0.6a 2013-06-25 09:22:35 -04:00
Ludovic Marcotte a79a9c4eff Merge to 2.0.6
Conflicts:
	Documentation/SOGo Installation Guide.odt
2013-06-21 12:44:35 -04:00
Jean Raby f049e2430a Added ldap attribute mapping table 2013-04-22 12:25:22 -04:00
Jean Raby 59b3219f2d Merge to 2.05a 2013-04-16 15:20:19 -04:00
Francis Lachapelle e9eb8bdc86 Merge to 2.0.5 2013-04-11 12:56:34 -04:00
Francis Lachapelle 5e0c7ae4f2 Merge to 2.0.4b 2013-02-04 14:24:46 -05:00
Francis Lachapelle c1c0c1ab44 Merge to 2.0.4a 2013-01-30 08:54:00 -05:00
Francis Lachapelle a59fff785b Merge to 2.0.4 2013-01-25 14:01:10 -05:00
Francis Lachapelle 6a70db80e6 Merge to 2.0.3a 2012-12-07 09:35:03 -05:00
Francis Lachapelle d610630c8d Merge to 2.0.3 (again) 2012-12-06 13:08:47 -05:00
Francis Lachapelle 4dc7790015 Merge to 2.0.3 2012-12-06 10:40:33 -05:00
Francis Lachapelle 9dd000a2ca Merge to 2.0.2
Merge commit '1080bee3ba9749aad0dc28625081fc6a496f7280' into maint

Conflicts:
	OpenChange/MAPIStoreContext.h
	OpenChange/MAPIStoreContext.m
2012-11-15 10:10:48 -05:00
Wolfgang Sourdeau ce4084e528 getNewChangeNumbers: new wrapper for openchangedb_get_new_changeNumbers 2012-10-12 16:55:27 -04:00
44 changed files with 900 additions and 319 deletions

No files matched your search

+25 -22
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2014, Inverse inc.
Copyright (c) 2015, Inverse inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -40,35 +40,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@implementation NGMimeMessage (ActiveSync)
- (NSArray *) allRecipients
- (void) _addRecipients: (NSEnumerator *) enumerator
toArray: (NSMutableArray *) recipients
{
NSEnumerator *enumerator, *addressList;
NSMutableArray *recipients;
NGMailAddressParser *parser;
NSEnumerator *addressList;
NGMailAddress *address;
NSString *s;
while ((s = [enumerator nextObject]))
{
parser = [NGMailAddressParser mailAddressParserWithString: s];
addressList = [[parser parseAddressList] objectEnumerator];
while ((address = [addressList nextObject]))
[recipients addObject: [address address]];
}
}
- (NSArray *) allRecipients
{
NSMutableArray *recipients;
recipients = [NSMutableArray array];
enumerator = [[self headersForKey: @"to"] objectEnumerator];
while ((s = [enumerator nextObject]))
{
parser = [NGMailAddressParser mailAddressParserWithString: s];
addressList = [[parser parseAddressList] objectEnumerator];
while ((address = [addressList nextObject]))
[recipients addObject: [address address]];
}
[self _addRecipients: [[self headersForKey: @"to"] objectEnumerator]
toArray: recipients];
enumerator = [[self headersForKey: @"cc"] objectEnumerator];
while ((s = [enumerator nextObject]))
{
parser = [NGMailAddressParser mailAddressParserWithString: s];
addressList = [[parser parseAddressList] objectEnumerator];
while ((address = [addressList nextObject]))
[recipients addObject: [address address]];
}
[self _addRecipients: [[self headersForKey: @"cc"] objectEnumerator]
toArray: recipients];
[self _addRecipients: [[self headersForKey: @"bcc"] objectEnumerator]
toArray: recipients];
return recipients;
}
+2
View File
@@ -49,6 +49,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- (NSString *) deviceType;
- (NSString *) attachmentName;
- (NSString *) command;
- (NSString *) collectionid;
- (NSString *) itemid;
- (NSData *) convertHexStringToBytes;
@end
+25
View File
@@ -298,6 +298,31 @@ static NSArray *easCommandParameters = nil;
return s;
}
- (NSString *) itemid
{
NSString *s;
s = [self _valueForParameter: @"ITEMID="];
if (!s)
s = @"Unknown";
return s;
}
- (NSString *) collectionid
{
NSString *s;
s = [self _valueForParameter: @"COLLECTIONID="];
if (!s)
s = @"Unknown";
return s;
}
//
// FIXME: combine with our OpenChange code.
//
+9 -5
View File
@@ -540,6 +540,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
NSMutableDictionary *folderMetadata, *dateCache, *syncCache;
NSString *davCollectionTagToStore;
NSAutoreleasePool *pool;
NSMutableString *s;
@@ -618,6 +619,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
more_available = NO;
davCollectionTagToStore = [theCollection davCollectionTag];
switch (theFolderType)
{
// Handle all the GCS components
@@ -788,7 +791,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
else
{
[folderMetadata removeObjectForKey: @"MoreAvailable"];
[folderMetadata setObject: [theCollection davCollectionTag] forKey: @"SyncKey"];
[folderMetadata setObject: davCollectionTagToStore forKey: @"SyncKey"];
}
[self _setFolderMetadata: folderMetadata
@@ -963,7 +966,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
else
{
[folderMetadata removeObjectForKey: @"MoreAvailable"];
[folderMetadata setObject: [theCollection davCollectionTag] forKey: @"SyncKey"];
[folderMetadata setObject: davCollectionTagToStore forKey: @"SyncKey"];
}
[self _setFolderMetadata: folderMetadata forKey: [self _getNameInCache: theCollection withType: theFolderType]];
@@ -1211,7 +1214,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
// Make sure that client is updated with the right syncKey. - This keeps vtodo's and vevent's syncKey in sync.
syncKeyInCache = [folderMetadata objectForKey: @"SyncKey"];
if (syncKeyInCache && !([davCollectionTag isEqualToString:syncKeyInCache]))
if (syncKeyInCache && !([davCollectionTag isEqualToString:syncKeyInCache]) && ![davCollectionTag isEqualToString: @"-1"])
{
davCollectionTag = syncKeyInCache;
*changeDetected = YES;
@@ -1431,8 +1434,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
}
// Only send a response if there are changes otherwise send an empty response.
if (changeDetected)
// Only send a response if there are changes or MS-ASProtocolVersion is either 2.5 or 12.0 oterwise send an empty response.
if (changeDetected || [[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"] || [[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"12.0"])
{
// We always return the last generated response.
// If we only return <Sync><Collections/></Sync>,
+86 -59
View File
@@ -1127,6 +1127,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
id currentCollection;
NSMutableString *s;
NSData *d;
NSArray *allCollections;
int j;
SOGoMicrosoftActiveSyncFolderType folderType;
int status, count;
@@ -1135,66 +1137,72 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
status = 1;
count = 0;
collectionId = [[(id)[theDocumentElement getElementsByTagName: @"CollectionId"] lastObject] textValue];
realCollectionId = [collectionId realCollectionIdWithFolderType: &folderType];
if (folderType == ActiveSyncMailFolder)
nameInCache = [NSString stringWithFormat: @"folder%@", realCollectionId];
else
nameInCache = collectionId;
realCollectionId = [self globallyUniqueIDToIMAPFolderName: realCollectionId type: folderType];
currentCollection = [self collectionFromId: realCollectionId type: folderType];
//
// For IMAP, we simply build a request like this:
//
// . UID SORT (SUBJECT) UTF-8 SINCE 1-Jan-2014 NOT DELETED
// * SORT 124576 124577 124579 124578
// . OK Completed (4 msgs in 0.000 secs)
//
if (folderType == ActiveSyncMailFolder)
{
EOQualifier *notDeletedQualifier, *sinceDateQualifier;
EOAndQualifier *qualifier;
NSCalendarDate *filter;
NSArray *uids;
filter = [NSCalendarDate dateFromFilterType: [[(id)[theDocumentElement getElementsByTagName: @"FilterType"] lastObject] textValue]];
notDeletedQualifier = [EOQualifier qualifierWithQualifierFormat:
@"(not (flags = %@))",
@"deleted"];
sinceDateQualifier = [EOQualifier qualifierWithQualifierFormat:
@"(DATE >= %@)", filter];
qualifier = [[EOAndQualifier alloc] initWithQualifiers: notDeletedQualifier, sinceDateQualifier,
nil];
AUTORELEASE(qualifier);
uids = [currentCollection fetchUIDsMatchingQualifier: qualifier
sortOrdering: @"REVERSE ARRIVAL"
threaded: NO];
count = [uids count];
// Add the number of UIDs expected to "soft delete"
count += [self _softDeleteCountWithFilter: filter collectionId: nameInCache];
}
else
{
count = [[currentCollection toOneRelationshipKeys] count];
}
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
[s appendFormat: @"<GetItemEstimate xmlns=\"GetItemEstimate:\"><Response><Status>%d</Status><Collection>", status];
[s appendString: @"<GetItemEstimate xmlns=\"GetItemEstimate:\">"];
allCollections = (id)[theDocumentElement getElementsByTagName: @"Collection"];
for (j = 0; j < [allCollections count]; j++)
{
collectionId = [[(id)[[allCollections objectAtIndex: j] getElementsByTagName: @"CollectionId"] lastObject] textValue];
realCollectionId = [collectionId realCollectionIdWithFolderType: &folderType];
if (folderType == ActiveSyncMailFolder)
nameInCache = [NSString stringWithFormat: @"folder%@", realCollectionId];
else
nameInCache = collectionId;
realCollectionId = [self globallyUniqueIDToIMAPFolderName: realCollectionId type: folderType];
currentCollection = [self collectionFromId: realCollectionId type: folderType];
[s appendFormat: @"<CollectionId>%@</CollectionId>", collectionId];
[s appendFormat: @"<Estimate>%d</Estimate>", count];
//
// For IMAP, we simply build a request like this:
//
// . UID SORT (SUBJECT) UTF-8 SINCE 1-Jan-2014 NOT DELETED
// * SORT 124576 124577 124579 124578
// . OK Completed (4 msgs in 0.000 secs)
//
if (folderType == ActiveSyncMailFolder)
{
NSCalendarDate *filter;
NSString *syncKey;
NSArray *allMessages;
filter = [NSCalendarDate dateFromFilterType: [[(id)[[allCollections objectAtIndex: j] getElementsByTagName: @"FilterType"] lastObject] textValue]];
syncKey = [[(id)[[allCollections objectAtIndex: j] getElementsByTagName: @"SyncKey"] lastObject] textValue];
allMessages = [currentCollection syncTokenFieldsWithProperties: nil matchingSyncToken: syncKey fromDate: filter];
count = [allMessages count];
// Add the number of UIDs expected to "soft delete"
count += [self _softDeleteCountWithFilter: filter collectionId: nameInCache];
}
else
{
count = [[currentCollection toOneRelationshipKeys] count];
}
[s appendString: @"<Response>"];
[s appendFormat: @"<Status>%d</Status><Collection>", status];
if (folderType == ActiveSyncMailFolder)
[s appendString: @"<Class>Email</Class>"];
else if (folderType == ActiveSyncContactFolder)
[s appendString: @"<Class>Contacts</Class>"];
else if (folderType == ActiveSyncEventFolder)
[s appendString: @"<Class>Calendar</Class>"];
else if (folderType == ActiveSyncTaskFolder)
[s appendString: @"<Class>Tasks</Class>"];
[s appendFormat: @"<CollectionId>%@</CollectionId>",collectionId];
[s appendFormat: @"<Estimate>%d</Estimate></Collection></Response>", count];
}
[s appendString: @"</Collection></Response></GetItemEstimate>"];
[s appendString: @"</GetItemEstimate>"];
d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
@@ -1929,6 +1937,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
[s appendString: @"<Provision xmlns=\"Provision:\">"];
[s appendString: @"<AllowHTMLEmail>1</AllowHTMLEmail>"];
[s appendString: @"</Provision>"];
d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
@@ -2254,7 +2263,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
error = [self _sendMail: data
recipients: [message allRecipients]
saveInSentItems: ([(id)[theDocumentElement getElementsByTagName: @"SaveInSentItems"] count] ? YES : NO)];
saveInSentItems: ([(id)[theDocumentElement getElementsByTagName: @"SaveInSentItems"] count] ? YES : NO)];
if (error)
{
@@ -2345,7 +2354,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
id value;
folderId = [[(id)[theDocumentElement getElementsByTagName: @"FolderId"] lastObject] textValue];
// if folderId is not there try to get it from URL
if (!folderId)
{
folderId = [[[context request] uri] collectionid];
}
itemId = [[(id)[theDocumentElement getElementsByTagName: @"ItemId"] lastObject] textValue];
// if itemId is not there try to get it from URL
if (!itemId)
{
itemId = [[[context request] uri] itemid];
}
realCollectionId = [folderId realCollectionIdWithFolderType: &folderType];
realCollectionId = [self globallyUniqueIDToIMAPFolderName: realCollectionId type: folderType];
@@ -2543,7 +2566,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// If the MS-ASProtocolVersion header is set to "12.1", the body of the SendMail request is
// is a "message/rfc822" payload - otherwise, it's a WBXML blob.
//
if ([cmdName caseInsensitiveCompare: @"SendMail"] == NSOrderedSame &&
if (([cmdName caseInsensitiveCompare: @"SendMail"] == NSOrderedSame ||
[cmdName caseInsensitiveCompare: @"SmartReply"] == NSOrderedSame ||
[cmdName caseInsensitiveCompare: @"SmartForward"] == NSOrderedSame) &&
[[theRequest headerForKey: @"content-type"] caseInsensitiveCompare: @"message/rfc822"] == NSOrderedSame)
{
NSString *s, *xml;
@@ -2561,7 +2586,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
s = [theRequest contentAsString];
}
xml = [NSString stringWithFormat: @"<?xml version=\"1.0\"?><!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\"><SendMail xmlns=\"ComposeMail:\"><SaveInSentItems/><MIME>%@</MIME></SendMail>", [s stringByEncodingBase64]];
xml = [NSString stringWithFormat: @"<?xml version=\"1.0\"?><!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\"><%@ xmlns=\"ComposeMail:\"><SaveInSentItems/><MIME>%@</MIME></%@>", cmdName, [s stringByEncodingBase64], cmdName];
d = [xml dataUsingEncoding: NSASCIIStringEncoding];
}
+87 -31
View File
@@ -272,10 +272,14 @@ struct GlobalObjectId {
charset = [[[self lookupInfoForBodyPart: key] objectForKey: @"parameterList"] objectForKey: @"charset"];
if (![charset length])
charset = @"us-ascii";
charset = @"utf-8";
s = [NSString stringWithData: d usingEncodingNamed: charset];
// We fallback to ISO-8859-1 string encoding
if (!s)
s = [[[NSString alloc] initWithData: d encoding: NSISOLatin1StringEncoding] autorelease];
if (theType == 1 && *theNativeTypeFound == 2)
s = [s htmlToText];
@@ -323,7 +327,7 @@ struct GlobalObjectId {
[[[thePart contentType] type] isEqualToString: @"text"] &&
([[[thePart contentType] subType] isEqualToString: @"plain"] || [[[thePart contentType] subType] isEqualToString: @"html"]))
{
// We make sure everything is encoded in UTF-8
// We make sure everything is encoded in UTF-8.
NGMimeType *mimeType;
NSString *s;
@@ -334,9 +338,13 @@ struct GlobalObjectId {
charset = [[thePart contentType] valueOfParameter: @"charset"];
if (![charset length])
charset = @"us-ascii";
charset = @"utf-8";
s = [NSString stringWithData: body usingEncodingNamed: charset];
s = [NSString stringWithData: body usingEncodingNamed: charset];
// We fallback to ISO-8859-1 string encoding. We avoid #3103.
if (!s)
s = [[[NSString alloc] initWithData: body encoding: NSISOLatin1StringEncoding] autorelease];
}
else
{
@@ -439,7 +447,7 @@ struct GlobalObjectId {
charset = [[[self lookupInfoForBodyPart: @""] objectForKey: @"parameterList"] objectForKey: @"charset"];
if (![charset length])
charset = @"us-ascii";
charset = @"utf-8";
d = [[self fetchPlainTextParts] objectForKey: @""];
@@ -453,6 +461,10 @@ struct GlobalObjectId {
d = [d dataByDecodingQuotedPrintableTransferEncoding];
s = [NSString stringWithData: d usingEncodingNamed: charset];
// We fallback to ISO-8859-1 string encoding. We avoid #3103.
if (!s)
s = [[[NSString alloc] initWithData: d encoding: NSISOLatin1StringEncoding] autorelease];
// Check if we must convert html->plain
if (theType == 1 && [subtype isEqualToString: @"html"])
@@ -469,9 +481,10 @@ struct GlobalObjectId {
}
else if (theType == 4)
{
// We sanitize the content *ONLY* for Outlook clients. Outlook has strange issues
// We sanitize the content *ONLY* for Outlook clients and if the content-transfer-encoding is 8bit. Outlook has strange issues
// with quoted-printable/base64 encoded text parts. It just doesn't decode them.
if ([[context objectForKey: @"DeviceType"] isEqualToString: @"WindowsOutlook15"])
encoding = [[self lookupInfoForBodyPart: @""] objectForKey: @"encoding"];
if ([[context objectForKey: @"DeviceType"] isEqualToString: @"WindowsOutlook15"] || ([encoding caseInsensitiveCompare: @"8bit"] == NSOrderedSame))
d = [self _sanitizedMIMEMessage];
else
d = [self content];
@@ -537,6 +550,10 @@ struct GlobalObjectId {
NSData *d, *globalObjId;
NSArray *attachmentKeys;
NSMutableString *s;
uint32_t v;
NSString *p;
id value;
iCalCalendar *calendar;
@@ -577,8 +594,25 @@ struct GlobalObjectId {
if (value)
[s appendFormat: @"<Cc xmlns=\"Email:\">%@</Cc>", [value activeSyncRepresentationInContext: context]];
// Importance - FIXME
[s appendFormat: @"<Importance xmlns=\"Email:\">%@</Importance>", @"1"];
// Importance
v = 0x1;
p = [[self mailHeaders] objectForKey: @"x-priority"];
if (p)
{
if ([p hasPrefix: @"1"]) v = 0x2;
else if ([p hasPrefix: @"2"]) v = 0x2;
else if ([p hasPrefix: @"4"]) v = 0x0;
else if ([p hasPrefix: @"5"]) v = 0x0;
}
else
{
p = [[self mailHeaders] objectForKey: @"importance"];
if ([p hasPrefix: @"High"]) v = 0x2;
else if ([p hasPrefix: @"Low"]) v = 0x0;
}
[s appendFormat: @"<Importance xmlns=\"Email:\">%d</Importance>", v];
// Read
[s appendFormat: @"<Read xmlns=\"Email:\">%d</Read>", ([self read] ? 1 : 0)];
@@ -753,23 +787,31 @@ struct GlobalObjectId {
len = [content length];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
// Set the correct type if client requested text/html but we got text/plain
if (preferredBodyType == 2 && nativeBodyType == 1)
[s appendString: @"<Type>1</Type>"];
else
[s appendFormat: @"<Type>%d</Type>", preferredBodyType];
[s appendFormat: @"<Truncated>%d</Truncated>", truncated];
[s appendFormat: @"<Preview></Preview>"];
if (!truncated)
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<Data>%@</Data>", content];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", len];
[s appendFormat: @"<Body xmlns=\"Email:\">%@</Body>", content];
[s appendFormat: @"<BodyTruncated xmlns=\"Email:\">%d</BodyTruncated>", truncated];
}
[s appendString: @"</Body>"];
else
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
// Set the correct type if client requested text/html but we got text/plain
if (preferredBodyType == 2 && nativeBodyType == 1)
[s appendString: @"<Type>1</Type>"];
else
[s appendFormat: @"<Type>%d</Type>", preferredBodyType];
[s appendFormat: @"<Truncated>%d</Truncated>", truncated];
[s appendFormat: @"<Preview></Preview>"];
if (!truncated)
{
[s appendFormat: @"<Data>%@</Data>", content];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", len];
}
[s appendString: @"</Body>"];
}
}
// Attachments -namespace 16
@@ -777,9 +819,12 @@ struct GlobalObjectId {
if ([attachmentKeys count])
{
int i;
[s appendString: @"<Attachments xmlns=\"AirSyncBase:\">"];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
[s appendString: @"<Attachments xmlns=\"Email:\">"];
else
[s appendString: @"<Attachments xmlns=\"AirSyncBase:\">"];
for (i = 0; i < [attachmentKeys count]; i++)
{
value = [attachmentKeys objectAtIndex: i];
@@ -790,11 +835,22 @@ struct GlobalObjectId {
// FileReference must be a unique identifier across the whole store. We use the following structure:
// mail/<foldername>/<message UID/<pathofpart>
// mail/INBOX/2
[s appendFormat: @"<FileReference>mail/%@/%@/%@</FileReference>", [[[self container] relativeImap4Name] stringByEscapingURL], [self nameInContainer], [value objectForKey: @"path"]];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
[s appendFormat: @"<AttName>mail/%@/%@/%@</AttName>", [[[self container] relativeImap4Name] stringByEscapingURL], [self nameInContainer], [value objectForKey: @"path"]];
else
[s appendFormat: @"<FileReference>mail/%@/%@/%@</FileReference>", [[[self container] relativeImap4Name] stringByEscapingURL], [self nameInContainer], [value objectForKey: @"path"]];
[s appendFormat: @"<Method>%d</Method>", 1]; // See: http://msdn.microsoft.com/en-us/library/ee160322(v=exchg.80).aspx
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [[value objectForKey: @"size"] intValue]];
//[s appendFormat: @"<IsInline>%d</IsInline>", 1];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<AttMethod>%d</AttMethod>", 1];
[s appendFormat: @"<AttSize>%d</AttSize>", [[value objectForKey: @"size"] intValue]];
}
else
{
[s appendFormat: @"<Method>%d</Method>", 1]; // See: http://msdn.microsoft.com/en-us/library/ee160322(v=exchg.80).aspx
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [[value objectForKey: @"size"] intValue]];
//[s appendFormat: @"<IsInline>%d</IsInline>", 1];
}
[s appendString: @"</Attachment>"];
}
+26 -8
View File
@@ -40,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <NGExtensions/NSString+misc.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WORequest.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalDateTime.h>
@@ -274,11 +275,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// It is very important here to NOT set <Truncated>0</Truncated> in the response,
// otherwise it'll prevent WP8 phones from sync'ing. See #3028 for details.
o = [o activeSyncRepresentationInContext: context];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<Body xmlns=\"Calendar:\">%@</Body>", o];
[s appendString: @"<BodyTruncated xmlns=\"Calendar:\">0</BodyTruncated>"];
}
else
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
}
[s appendFormat: @"<NativeBodyType xmlns=\"AirSyncBase:\">%d</NativeBodyType>", 1];
@@ -394,9 +404,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
// FIXME: merge with iCalToDo
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
[self setComment: o];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
if ((o = [theValues objectForKey: @"Body"]))
[self setComment: o];
}
else
{
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
[self setComment: o];
}
if ((o = [theValues objectForKey: @"Location"]))
[self setLocation: o];
+46 -11
View File
@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import <NGExtensions/NSString+misc.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WORequest.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
@@ -49,6 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "NSDate+ActiveSync.h"
#include "NSString+ActiveSync.h"
@implementation iCalToDo (ActiveSync)
- (NSString *) activeSyncRepresentationInContext: (WOContext *) context
@@ -62,11 +64,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
s = [NSMutableString string];
// Complete
o = [self completed];
[s appendFormat: @"<Complete xmlns=\"Tasks:\">%d</Complete>", (o ? 1 : 0)];
[s appendFormat: @"<Complete xmlns=\"Tasks:\">%d</Complete>", [[self status] isEqualToString: @"COMPLETED"] ? 1 : 0];
// DateCompleted
if (o)
if ((o = [self completed]))
[s appendFormat: @"<DateCompleted xmlns=\"Tasks:\">%@</DateCompleted>", [o activeSyncRepresentationInContext: context]];
// Start date
@@ -97,6 +98,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Reminder - FIXME
[s appendFormat: @"<ReminderSet xmlns=\"Tasks:\">%d</ReminderSet>", 0];
// Sensitivity
if ([[self accessClass] isEqualToString: @"PRIVATE"])
v = 2;
else if ([[self accessClass] isEqualToString: @"CONFIDENTIAL"])
@@ -104,6 +106,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
else
v = 0;
[s appendFormat: @"<Sensitivity xmlns=\"Tasks:\">%d</Sensitivity>", v];
categories = [self categories];
if ([categories count])
@@ -126,11 +130,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// It is very important here to NOT set <Truncated>0</Truncated> in the response,
// otherwise it'll prevent WP8 phones from sync'ing. See #3028 for details.
o = [o activeSyncRepresentationInContext: context];
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
[s appendFormat: @"<Body xmlns=\"Tasks:\">%@</Body>", o];
[s appendString: @"<BodyTruncated xmlns=\"Tasks:\">0</BodyTruncated>"];
}
else
{
[s appendString: @"<Body xmlns=\"AirSyncBase:\">"];
[s appendFormat: @"<Type>%d</Type>", 1];
[s appendFormat: @"<EstimatedDataSize>%d</EstimatedDataSize>", [o length]];
[s appendFormat: @"<Data>%@</Data>", o];
[s appendString: @"</Body>"];
}
}
return s;
@@ -152,9 +165,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[self setSummary: o];
// FIXME: merge with iCalEvent
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
[self setComment: o];
if ([[[context request] headerForKey: @"MS-ASProtocolVersion"] isEqualToString: @"2.5"])
{
if ((o = [theValues objectForKey: @"Body"]))
[self setComment: o];
}
else
{
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
[self setComment: o];
}
if ([[theValues objectForKey: @"Complete"] intValue] &&
((o = [theValues objectForKey: @"DateCompleted"])) )
@@ -166,6 +186,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[completed setDate: o];
[self setStatus: @"COMPLETED"];
}
else
{
[self setStatus: @"IN-PROCESS"];
[self setCompleted: nil];
}
if ((o = [theValues objectForKey: @"DueDate"]))
{
@@ -177,6 +202,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[due setDateTime: o];
}
if ((o = [theValues objectForKey: @"StartDate"]))
{
iCalDateTime *due;
o = [o calendarDate];
due = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"];
[due setTimeZone: tz];
[due setDateTime: o];
}
// 2 == high, 1 == normal, 0 == low
if ((o = [theValues objectForKey: @"Importance"]))
{
+350
View File
@@ -1,3 +1,353 @@
commit 097d5c2333515092f03ace5e64fc6824682ba974
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Mar 24 08:40:13 2015 -0400
now possible to configure objectClass names for LDAP groups using GroupObjectClasses (#1499)
M Documentation/SOGoInstallationGuide.asciidoc
M NEWS
M SoObjects/SOGo/LDAPSource.h
M SoObjects/SOGo/LDAPSource.m
M SoObjects/SOGo/SOGoGroup.m
M SoObjects/SOGo/SOGoSource.h
commit d75fb0722a0ced5bb937e5b754e95cd0261df7a7
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Mar 24 08:34:29 2015 -0400
Code cleanups
M UI/Scheduler/UIxAttendeesEditor.h
M UI/Scheduler/UIxAttendeesEditor.m
M UI/Scheduler/UIxComponentEditor.h
M UI/Scheduler/UIxComponentEditor.m
commit 26d876e67a32e6c2dc36a3a92449aa0b6638ec41
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Mon Mar 23 16:28:32 2015 -0400
Improve event attendees editor
- Avoid repetitive AJAX queries;
- Improve handling of daylight changes.
M UI/WebServerResources/JavascriptAPIExtensions.js
M UI/WebServerResources/UIxAttendeesEditor.js
commit cc3652b59b40bcb420d806412277509ac247d85d
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Mar 23 17:23:29 2015 -0400
improvements to EAS SyncKey handling to avoid missing mails (#3048, #3058)
M ActiveSync/SOGoActiveSyncDispatcher+Sync.m
M NEWS
commit 9d7bbbc312cbe8ccb535e24308be111a3a2eb710
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Mar 23 14:55:14 2015 -0400
enable by default HTML mails support using EAS on Windows and BB phones
M ActiveSync/SOGoActiveSyncDispatcher.m
M NEWS
commit d2915add6d69a8fd05d15bb8c2ed979fe6ad9026
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Mar 23 14:08:31 2015 -0400
now favor login@domain as the default email address if multiple mail: fields are specified
M NEWS
M SoObjects/SOGo/SOGoUser.h
M SoObjects/SOGo/SOGoUser.m
commit 67139ce3e3f69160a683d8c11bee439be202a84e
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Mar 23 11:35:45 2015 -0400
improved GetItemEstimate to count all vasnished/deleted mails too
M ActiveSync/SOGoActiveSyncDispatcher.m
M NEWS
commit 9eb138b867ebd0a51b9a649891422bac70406510
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Mar 23 10:54:36 2015 -0400
prevent potential freebusy lookup crashes during timezone changes with repetitive events
M NEWS
M UI/MainUI/SOGoUserHomePage.m
commit baf3d1f986d48d4fa37a076ccf555d75f4d5dbda
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Fri Mar 20 09:10:49 2015 -0400
immediately delete mails from EAS clients when they are marked as deleted on the IMAP server
M NEWS
M SoObjects/Mailer/SOGoMailFolder.m
commit ecd336fa5c6513ee8533dae05e5a328c81527a38
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Fri Mar 20 08:51:35 2015 -0400
Fix compilation warning and error
M ActiveSync/NGMimeMessage+ActiveSync.m
M ActiveSync/SOGoMailObject+ActiveSync.m
commit afd73289d1ebb13c643f7a8290eac7da43b69330
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Fri Mar 20 08:45:42 2015 -0400
properly fallback over EAS to UTF-8 and then Latin1 for messages w/o charset (#3103)
M ActiveSync/SOGoMailObject+ActiveSync.m
M NEWS
commit bff21ab1ff136ada7d93cc529a87da9dd254fa60
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Mar 19 16:08:33 2015 -0400
support for mail prority using EAS
M ActiveSync/SOGoMailObject+ActiveSync.m
M NEWS
commit 6d99226b1390d2dce1f7dfc6a3bab5143aad6364
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Mar 19 14:53:01 2015 -0400
Always add DisplayName no matter EAS client version
M ActiveSync/SOGoMailObject+ActiveSync.m
commit 69974807b5740f245376f8e19f71559997bcae44
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Thu Mar 19 08:32:37 2015 -0400
Fix Language-Region tags in Web interface
Fixes #3121
M NEWS
M UI/MailerUI/UIxMailEditor.m
M UI/Scheduler/UIxCalMainView.m
commit cdb766e2eff3b6e420da48b3f396814edff96b4f
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Mar 18 10:15:33 2015 -0400
Documented NGMimeBuildMimeTempDirectory
M Documentation/SOGoInstallationGuide.asciidoc
commit e25a7e3d8d0a5f11a65a6fa337a637b3e1f44432
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Mar 18 09:36:35 2015 -0400
Fix for bug #3138
M ActiveSync/NGMimeMessage+ActiveSync.m
M ActiveSync/SOGoActiveSyncDispatcher.m
M NEWS
commit 1d5ae27c996f63488653d3a8638b33320540741c
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Tue Mar 17 15:31:35 2015 -0400
Fix issues with freebusy (Web, busyOffHours)
M NEWS
M SoObjects/Appointments/SOGoFreeBusyObject.m
M UI/WebServerResources/UIxAttendeesEditor.js
commit 1bdd5dfc9085e1f08f839b8179a7ccb37b038e5c
Author: Jens Erat <email@jenserat.de>
Date: Fri Mar 13 14:06:58 2015 +0100
Remove obsolete archive string from translations
M UI/MailerUI/Arabic.lproj/Localizable.strings
M UI/MailerUI/Danish.lproj/Localizable.strings
M UI/MailerUI/Icelandic.lproj/Localizable.strings
M UI/MailerUI/Italian.lproj/Localizable.strings
M UI/MailerUI/NorwegianNynorsk.lproj/Localizable.strings
M UI/MailerUI/Swedish.lproj/Localizable.strings
M UI/MailerUI/Ukrainian.lproj/Localizable.strings
M UI/MailerUI/Welsh.lproj/Localizable.strings
commit 37fbd75d552873575f11853e4478d6dce9640201
Author: Jens Erat <email@jenserat.de>
Date: Fri Mar 13 11:41:07 2015 +0100
Rename "Archive" to "Export" in Webmail, ctd.
Fixes #2758 also for non-Inbox folders
M UI/Templates/MailerUI/UIxMailMainFrame.wox
commit f1fda8bd0617d5e6b924bb1ae57fb7840bbcc13f
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Tue Mar 10 13:27:17 2015 -0400
Return a single phone number in JSON contacts list
M SoObjects/Contacts/SOGoContactSourceFolder.m
commit 517f4b0f49e2545f930408b922dabc1a4a9006eb
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Mon Mar 9 14:04:21 2015 -0400
Fix possible JS exception in Contacts module
M NEWS
commit cbba0719bb58229d9be8d3bb5af5fba23da3ae14
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Wed Mar 4 10:05:12 2015 -0500
Fix exception in SOGoUserManager
M SoObjects/SOGo/SOGoUserManager.m
commit 8e0849029ea93bfc9e1f9e2cb4ff2e0e5b6a4308
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Tue Mar 3 21:18:46 2015 -0500
Fix contacts lookup by UID
When looking for a specific contact UID, we no longer match a pattern
that could return multiple results. We search for the exact UID only.
M NEWS
M SoObjects/Appointments/SOGoFreeBusyObject.m
M SoObjects/SOGo/SOGoUserManager.h
M SoObjects/SOGo/SOGoUserManager.m
commit 61923225136db72ceb89294d504b65a7f62e7a7f
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Tue Mar 3 20:59:32 2015 -0500
Fix some gcc warnings
M SoObjects/SOGo/SOGoCASSession.m
M SoObjects/SOGo/SOGoUser.m
M SoObjects/SOGo/SOGoUserManager.m
commit df59b73a221467523c18c56493c13c86003d7271
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 26 17:56:42 2015 -0500
use correct mail attachment elements for EAS 2.5 clients - patch from tfu
M ActiveSync/SOGoMailObject+ActiveSync.m
M NEWS
commit a5672fda5210e6149bd893683c7ee4338f0c3cf9
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 26 17:55:36 2015 -0500
do not use syncKey from cache when davCollectionTag = -1 - patch from tfu
M ActiveSync/SOGoActiveSyncDispatcher+Sync.m
M NEWS
commit b593ddc6436e0d4aff2ef24e6ff9b3cda0c0c396
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 26 17:53:58 2015 -0500
SmartReply improvements for missing body attributes - patch from tfu
M ActiveSync/NSString+ActiveSync.h
M ActiveSync/NSString+ActiveSync.m
M ActiveSync/SOGoActiveSyncDispatcher.m
M NEWS
commit 38d61f720f0c9352619fa2cb214e81734ed05868
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 26 17:52:37 2015 -0500
use the correct body element for events for EAS 2.5 clients - patch from tfu
M ActiveSync/iCalEvent+ActiveSync.m
M NEWS
commit 733e334726824be7ab3a41ca7d4b885550a18f9a
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 26 17:51:02 2015 -0500
fixed tasks disappearing issue with RoadSync - patch from tfu
M ActiveSync/iCalToDo+ActiveSync.m
M NEWS
commit 22888ba5ac2cdc8d52d4c8eba9a94936376b7520
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 26 17:49:26 2015 -0500
use the correct mail body element for EAS 2.5 clients - patch from tfu
M ActiveSync/SOGoMailObject+ActiveSync.m
M NEWS
commit 33c485d2f6d58443c0c67297b87d8cc3d67d1398
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 26 17:48:06 2015 -0500
fixed empty sync responses for EAS 2.5 and 12.0 clients - patch from tfu
M ActiveSync/SOGoActiveSyncDispatcher+Sync.m
M NEWS
commit 9160e34134c1c24f5f51cd6c9081723f0963e7c5
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 26 17:46:34 2015 -0500
multiple collections support for GetItemEstimate - patch from tfu
M ActiveSync/SOGoActiveSyncDispatcher.m
M NEWS
commit 5ceddc213ec08ccb5b44b07aae47921a19b36fd8
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 26 16:00:03 2015 -0500
Fix for bug #3116
M ActiveSync/SOGoMailObject+ActiveSync.m
M NEWS
commit b97002565e3d21b417f99b704641abee1052642c
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Feb 25 08:42:18 2015 -0500
Updated NEWS file regarding previous commit
M NEWS
commit 8d21bc3e36014d63db0e37bf7121d81c8200b5e1
Author: Jesús García Sáez <jgarcia@zentyal.com>
Date: Wed Feb 25 12:01:31 2015 +0100
Fix change password with DomainBasedUID
When users use full domain to login (SOGoEnableDomainBasedUID) the
user attributes in the cache were not being properly updated because
in this case the key is `uid@domain` instead of just `uid`.
M SoObjects/SOGo/SOGoUserManager.m
commit b26ea30b1b794e983ea272b5de713b0205fda0d8
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 12 11:06:57 2015 -0500
Update ChangeLog
M ChangeLog
commit 72b210cd2ebccc8e9cdc13c23abb76b7f455b780
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 12 10:29:46 2015 -0500
@@ -1048,6 +1048,11 @@ of supported attributes.
user addressbooks (see _abOU_ below), this list of object classes will
be applied to new records as they are created.
|GroupObjectClasses
|A list (array) of names identifying groups within the LDAP source. If not
set, SOGo will use `group`, `groupofnames`, `groupofuniquenames`
and `posixgroup`.
|modifiers
|A list (array) of usernames that are authorized to perform
modifications to the address book defined by this LDAP source.
@@ -1689,6 +1694,13 @@ cronjob `sogo-tmpwatch`.
Defaults to `/var/spool/sogo`.
|S |NGMimeBuildMimeTempDirectory
|Parameter used to set the path where temporary files will be stored
by SOPE when dealing with MIME messages.
Defaults to `/tmp`.
|S |NGImap4DisableIMAP4Pooling
|Disables IMAP pooling when set to `YES`. Enable pooling by setting to
`NO` or using a caching proxy like imapproxy.
+3 -3
View File
@@ -1,7 +1,7 @@
<!-- TODO have the build system take care of this -->
<releaseinfo>Version 2.2.16 - February 2015</releaseinfo>
<subtitle>for version 2.2.16</subtitle>
<date>2015-02-12</date>
<releaseinfo>Version 2.2.17 - March 2015</releaseinfo>
<subtitle>for version 2.2.17</subtitle>
<date>2015-03-24</date>
<legalnotice>
<para>Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".</para>
@@ -13,6 +13,6 @@
// TODO have the build system take care of this
:release_version: 2.2.16
:release_version: 2.2.17
// vim: set syntax=asciidoc tabstop=2 shiftwidth=2 expandtab:
+32
View File
@@ -1,3 +1,35 @@
2.2.17 (2015-03-24)
-------------------
Enhancements
- support for mail prority using EAS
- immediately delete mails from EAS clients when they are marked as deleted on the IMAP server
- now favor login@domain as the default email address if multiple mail: fields are specified
- enable by default HTML mails support using EAS on Windows and BB phones
- now possible to configure objectClass names for LDAP groups using GroupObjectClasses (#1499)
Bug fixes
- fixed login issue after password change (#2601)
- fixed potential encoding issue using EAS and 8-bit mails (#3116)
- multiple collections support for GetItemEstimate using EAS
- fixed empty sync responses for EAS 2.5 and 12.0 clients
- use the correct mail body element for EAS 2.5 clients
- fixed tasks disappearing issue with RoadSync
- use the correct body element for events for EAS 2.5 clients
- SmartReply improvements for missing body attributes
- do not use syncKey from cache when davCollectionTag = -1
- use correct mail attachment elements for EAS 2.5 clients
- fixed contacts lookup by UID in freebusy
- reduced telephone number to a single value in JSON response of contacts list
- fixed freebusy data when 'busy off hours' is enabled and period starts during the weekend
- fixed fetching of freebusy data from the Web interface
- fixed EAS handling of Bcc in emails (#3138)
- fixed Language-Region tags in Web interface (#3121)
- properly fallback over EAS to UTF-8 and then Latin1 for messages w/o charset (#3103)
- prevent potential freebusy lookup crashes during timezone changes with repetitive events
- improved GetItemEstimate to count all vasnished/deleted mails too
- improvements to EAS SyncKey handling to avoid missing mails (#3048, #3058)
2.2.16 (2015-02-12)
-------------------
+5 -11
View File
@@ -62,17 +62,14 @@
SOGoUserManager *um;
NSString *domain;
NSDictionary *contactInfos;
NSArray *contacts;
um = [SOGoUserManager sharedUserManager];
contactInfos = [um contactInfosForUserWithUIDorEmail: uid];
if (contactInfos == nil)
{
// Search among global addressbooks
domain = [[context activeUser] domain];
[um fetchContactsMatching: uid inDomain: domain];
contacts = [um fetchContactsMatching: uid inDomain: domain];
if ([contacts count] == 1)
contactInfos = [contacts lastObject];
contactInfos = [um fetchContactWithUID: uid inDomain: domain];
}
/* iCal.app compatibility:
@@ -279,7 +276,6 @@
if ([uid length])
{
SOGoUserManager *um;
NSArray *contacts;
NSString *domain, *email;
NSDictionary *contact;
MSExchangeFreeBusy *exchangeFreeBusy;
@@ -287,10 +283,9 @@
um = [SOGoUserManager sharedUserManager];
domain = [[context activeUser] domain];
contacts = [um fetchContactsMatching: uid inDomain: domain];
if ([contacts count] == 1)
contact = [um fetchContactWithUID: uid inDomain: domain];
if (contact)
{
contact = [contacts lastObject];
email = [contact valueForKey: @"c_email"];
source = [contact objectForKey: @"source"];
if ([email length]
@@ -386,8 +381,7 @@
([currentStartDate compare: startDate] == NSOrderedAscending)? startDate : currentStartDate, @"startDate",
currentEndDate, @"endDate", nil]];
if (!firstRange
&& currentEndDate != endDate
if (currentEndDate != endDate
&& ([currentEndDate dayOfWeek] == 6 || [currentEndDate dayOfWeek] == 0))
{
// Fill weekend days
@@ -267,6 +267,13 @@
data = [oldRecord objectForKey: @"homephone"];
if (![data length])
data = @"";
else if ([data isKindOfClass: [NSArray class]])
{
if ([data count] > 0)
data = [data objectAtIndex: 0];
else
data = @"";
}
[newRecord setObject: data forKey: @"c_telephonenumber"];
// Custom attribute for group-lookups. See LDAPSource.m where
+5 -5
View File
@@ -2129,13 +2129,13 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
value: nextModseq];
searchQualifier = [[EOAndQualifier alloc]
initWithQualifiers:
kvQualifier, [self _nonDeletedQualifier], nil];
kvQualifier, nil];
[kvQualifier release];
[searchQualifier autorelease];
}
else
{
searchQualifier = [self _nonDeletedQualifier];
searchQualifier = nil;
}
if (theStartDate)
@@ -2144,7 +2144,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
sinceDateQualifier = [EOQualifier qualifierWithQualifierFormat:
@"(DATE >= %@)", theStartDate];
searchQualifier = [[EOAndQualifier alloc] initWithQualifiers: searchQualifier, sinceDateQualifier,
searchQualifier = [[EOAndQualifier alloc] initWithQualifiers: sinceDateQualifier, searchQualifier,
nil];
[searchQualifier autorelease];
}
@@ -2155,7 +2155,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
sortOrdering: nil];
fetchResults = [(NSDictionary *)[self fetchUIDs: uids
parts: [NSArray arrayWithObject: @"modseq"]]
parts: [NSArray arrayWithObjects: @"modseq", @"flags", nil]]
objectForKey: @"fetch"];
/* NOTE: we sort items manually because Cyrus does not properly sort
@@ -2166,7 +2166,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
for (i = 0; i < [fetchResults count]; i++)
{
d = [NSDictionary dictionaryWithObject: [[fetchResults objectAtIndex: i] objectForKey: @"modseq"]
d = [NSDictionary dictionaryWithObject: ([[[fetchResults objectAtIndex: i] objectForKey: @"flags"] containsObject: @"deleted"]) ? [NSNull null] : [[fetchResults objectAtIndex: i] objectForKey: @"modseq"]
forKey: [[[fetchResults objectAtIndex: i] objectForKey: @"uid"] stringValue]];
[allTokens addObject: d];
}
+2
View File
@@ -72,6 +72,7 @@
NSDictionary *contactMapping;
NSArray *contactObjectClasses;
NSArray *groupObjectClasses;
NSDictionary *modulesConstraints;
@@ -106,6 +107,7 @@
UIDField: (NSString *) newUIDField
mailFields: (NSArray *) newMailFields
searchFields: (NSArray *) newSearchFields
groupObjectClasses: (NSArray *) newGroupObjectClasses
IMAPHostField: (NSString *) newIMAPHostField
IMAPLoginField: (NSString *) newIMAPLoginField
SieveHostField: (NSString *) newSieveHostField
+29 -11
View File
@@ -101,6 +101,8 @@ static Class NSStringK;
contactMapping = nil;
searchFields = [NSArray arrayWithObjects: @"sn", @"displayname", @"telephonenumber", nil];
[searchFields retain];
groupObjectClasses = [NSArray arrayWithObjects: @"group", @"groupofnames", @"groupofuniquenames", @"posixgroup", nil];
[groupObjectClasses retain];
IMAPHostField = nil;
IMAPLoginField = nil;
SieveHostField = nil;
@@ -144,6 +146,7 @@ static Class NSStringK;
[contactMapping release];
[mailFields release];
[searchFields release];
[groupObjectClasses release];
[IMAPHostField release];
[IMAPLoginField release];
[SieveHostField release];
@@ -189,6 +192,7 @@ static Class NSStringK;
UIDField: [udSource objectForKey: @"UIDFieldName"]
mailFields: [udSource objectForKey: @"MailFieldNames"]
searchFields: [udSource objectForKey: @"SearchFieldNames"]
groupObjectClasses: [udSource objectForKey: @"GroupObjectClasses"]
IMAPHostField: [udSource objectForKey: @"IMAPHostFieldName"]
IMAPLoginField: [udSource objectForKey: @"IMAPLoginFieldName"]
SieveHostField: [udSource objectForKey: @"SieveHostFieldName"]
@@ -310,6 +314,7 @@ static Class NSStringK;
UIDField: (NSString *) newUIDField
mailFields: (NSArray *) newMailFields
searchFields: (NSArray *) newSearchFields
groupObjectClasses: (NSArray *) newGroupObjectClasses
IMAPHostField: (NSString *) newIMAPHostField
IMAPLoginField: (NSString *) newIMAPLoginField
SieveHostField: (NSString *) newSieveHostField
@@ -334,6 +339,8 @@ static Class NSStringK;
ASSIGN(mailFields, newMailFields);
if (newSearchFields)
ASSIGN(searchFields, newSearchFields);
if (newGroupObjectClasses)
ASSIGN(groupObjectClasses, newGroupObjectClasses);
if (newBindFields)
{
// Before SOGo v1.2.0, bindFields was a comma-separated list
@@ -1031,6 +1038,8 @@ static Class NSStringK;
NSString *value;
static NSArray *resourceKinds = nil;
NSMutableArray *classes;
NSEnumerator *gclasses;
NSString *gclass;
id o;
if (!resourceKinds)
@@ -1059,24 +1068,27 @@ static Class NSStringK;
if (classes)
{
// We check if our entry is a group. If so, we set the
// 'isGroup' custom attribute.
if ([classes containsObject: @"group"] ||
[classes containsObject: @"groupofnames"] ||
[classes containsObject: @"groupofuniquenames"] ||
[classes containsObject: @"posixgroup"])
{
[ldifRecord setObject: [NSNumber numberWithInt: 1]
forKey: @"isGroup"];
}
// We check if our entry is a resource. We also support
// determining resources based on the KindFieldName attribute
// value - see below.
else if ([classes containsObject: @"calendarresource"])
if ([classes containsObject: @"calendarresource"])
{
[ldifRecord setObject: [NSNumber numberWithInt: 1]
forKey: @"isResource"];
}
else
{
// We check if our entry is a group. If so, we set the
// 'isGroup' custom attribute.
gclasses = [groupObjectClasses objectEnumerator];
while (gclass = [gclasses nextObject])
if ([classes containsObject: [gclass lowercaseString]])
{
[ldifRecord setObject: [NSNumber numberWithInt: 1]
forKey: @"isGroup"];
break;
}
}
}
// We check if that entry corresponds to a resource. For this,
@@ -1368,6 +1380,11 @@ static Class NSStringK;
return modifiers;
}
- (NSArray *) groupObjectClasses
{
return groupObjectClasses;
}
static NSArray *
_convertRecordToLDAPAttributes (LDAPSourceSchema *schema, NSDictionary *ldifRecord)
{
@@ -1683,6 +1700,7 @@ _makeLDAPChanges (NGLdapConnection *ldapConnection,
UIDField: @"cn"
mailFields: nil
searchFields: nil
groupObjectClasses: nil
IMAPHostField: nil
IMAPLoginField: nil
SieveHostField: nil
-1
View File
@@ -113,7 +113,6 @@
+ (void) handleLogoutRequest: (NSString *) logoutRequest
{
CASLogoutRequest *rq;
SOGoCache *cache;
NSBundle *bundle;
NSString *mapFile, *sessionIndex;
+7 -6
View File
@@ -137,6 +137,8 @@
NGLdapEntry *entry;
NSObject <SOGoSource> *source;
id o;
NSEnumerator *gclasses;
NSString *gclass;
int i;
@@ -194,12 +196,11 @@
}
}
// Found a group, let's return it.
if ([classes containsObject: @"group"] ||
[classes containsObject: @"groupofnames"] ||
[classes containsObject: @"groupofuniquenames"] ||
[classes containsObject: @"posixgroup"])
{
gclasses = [[source groupObjectClasses] objectEnumerator];
while (gclass = [gclasses nextObject])
if ([classes containsObject: gclass])
{
// Found a group, let's return it.
o = [[self alloc] initWithIdentifier: theValue
domain: domain
source: source
+1
View File
@@ -110,6 +110,7 @@
- (NSString *) baseDN;
- (NSString *) MSExchangeHostname;
- (NSArray *) groupObjectClasses;
@end
#endif /* SOGOSOURCE_H */
+1 -1
View File
@@ -1,5 +1,5 @@
/*
Copyright (C) 2006-2013 Inverse inc.
Copyright (C) 2006-2015 Inverse inc.
Copyright (C) 2005 SKYRIX Software AG
This file is part of SOGo.
+16 -7
View File
@@ -37,6 +37,7 @@
#import <NGExtensions/NSObject+Logs.h>
#import <Appointments/SOGoAppointmentFolders.h>
#import <Contacts/SOGoContactFolders.h>
#import "NSArray+Utilities.h"
#import "SOGoCache.h"
@@ -234,7 +235,6 @@
[currentPassword release];
[cn release];
[loginInDomain release];
//[language release];
[super dealloc];
}
@@ -577,13 +577,13 @@
- (void) _appendSystemMailAccount
{
NSString *fullName, *replyTo, *imapLogin, *imapServer, *cImapServer, *signature,
*encryption, *scheme, *action, *query, *customEmail, *sieveServer;
*encryption, *scheme, *action, *query, *customEmail, *defaultEmail, *sieveServer;
NSMutableDictionary *mailAccount, *identity, *mailboxes, *receipts;
NSNumber *port;
NSMutableArray *identities;
NSArray *mails;
NSURL *url, *cUrl;
unsigned int count, max;
unsigned int count, max, default_identity;
NSInteger defaultPort;
[self userDefaults];
@@ -661,8 +661,9 @@
[mailAccount setObject: sieveServer forKey: @"sieveServerName"];
}
/* identities */
// Identities
defaultEmail = [NSString stringWithFormat: @"%@@%@", [self loginInDomain], [self domain]];
default_identity = 0;
identities = [NSMutableArray new];
mails = [self allEmails];
[mailAccount setObject: [mails objectAtIndex: 0] forKey: @"name"];
@@ -702,6 +703,10 @@
if (signature)
[identity setObject: signature forKey: @"signature"];
[identities addObject: identity];
if ([[identity objectForKey: @"email"] caseInsensitiveCompare: defaultEmail] == NSOrderedSame)
default_identity = [identities count]-1;
[identity release];
}
}
@@ -723,10 +728,14 @@
if (signature)
[identity setObject: signature forKey: @"signature"];
[identities addObject: identity];
if ([[identity objectForKey: @"email"] caseInsensitiveCompare: defaultEmail] == NSOrderedSame)
default_identity = [identities count]-1;
[identity release];
}
[[identities objectAtIndex: 0] setObject: [NSNumber numberWithBool: YES]
forKey: @"isDefault"];
[[identities objectAtIndex: default_identity] setObject: [NSNumber numberWithBool: YES]
forKey: @"isDefault"];
[mailAccount setObject: identities forKey: @"identities"];
[identities release];
+3
View File
@@ -65,10 +65,13 @@
- (NSDictionary *) contactInfosForUserWithUIDorEmail: (NSString *) uid;
- (NSDictionary *) contactInfosForUserWithUIDorEmail: (NSString *) uid
inDomain: (NSString *) domain;
- (NSDictionary *) fetchContactWithUID: (NSString *) uid
inDomain: (NSString *) domain;
- (NSArray *) fetchContactsMatching: (NSString *) match
inDomain: (NSString *) domain;
- (NSArray *) fetchUsersMatching: (NSString *) filter
inDomain: (NSString *) domain;
- (NSArray *) _compactAndCompleteContacts: (NSEnumerator *) contacts;
- (NSString *) getCNForUID: (NSString *) uid;
- (NSString *) getEmailForUID: (NSString *) uid;
+43 -8
View File
@@ -18,6 +18,7 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSException.h>
@@ -595,10 +596,11 @@ static Class NSNullK;
newPassword: (NSString *) newPassword
perr: (SOGoPasswordPolicyError *) perr
{
NSString *jsonUser;
NSString *jsonUser, *userLogin;
NSMutableDictionary *currentUser;
BOOL didChange;
SOGoSystemDefaults *sd;
jsonUser = [[SOGoCache sharedCache] userAttributesForLogin: login];
currentUser = [jsonUser objectFromJSONString];
@@ -611,9 +613,7 @@ static Class NSNullK;
didChange = YES;
if (!currentUser)
{
currentUser = [NSMutableDictionary dictionary];
}
currentUser = [NSMutableDictionary dictionary];
// It's important to cache the password here as we might have cached the
// user's entry in -contactInfosForUserWithUIDorEmail: and if we don't
@@ -621,9 +621,13 @@ static Class NSNullK;
// cached for the user unless its entry expires from memcached's
// internal cache.
[currentUser setObject: [newPassword asSHA1String] forKey: @"password"];
[[SOGoCache sharedCache]
setUserAttributes: [currentUser jsonRepresentation]
forLogin: login];
sd = [SOGoSystemDefaults sharedSystemDefaults];
if ([sd enableDomainBasedUID])
userLogin = [NSString stringWithFormat: @"%@@%@", login, domain];
else
userLogin = login;
[[SOGoCache sharedCache] setUserAttributes: [currentUser jsonRepresentation]
forLogin: userLogin];
}
else
didChange = NO;
@@ -911,6 +915,37 @@ static Class NSNullK;
return currentUser;
}
/**
* Fetch the contact information identified by the specified UID in the global addressbooks.
*/
- (NSDictionary *) fetchContactWithUID: (NSString *) uid
inDomain: (NSString *) domain
{
NSDictionary *contact;
NSMutableArray *contacts;
NSEnumerator *sources;
NSString *sourceID;
id currentSource;
contacts = [NSMutableArray array];
contact = nil;
sources = [[self addressBookSourceIDsInDomain: domain] objectEnumerator];
while ((sourceID = [sources nextObject]))
{
currentSource = [_sources objectForKey: sourceID];
contact = [currentSource lookupContactEntry: uid];
if (contact)
[contacts addObject: contact];
}
if ([contacts count])
contact = [[self _compactAndCompleteContacts: [contacts objectEnumerator]] lastObject];
else
contact = nil;
return contact;
}
- (NSArray *) _compactAndCompleteContacts: (NSEnumerator *) contacts
{
NSMutableDictionary *compactContacts, *returnContact;
@@ -79,7 +79,6 @@
"Remove this folder" = "مسح المجلد";
"Erase mails from this folder" = "مسح الرسائل من هذا المجلد";
"Expunge this folder" = "محو هذا المجلد";
"Archive This Folder" = "أرشفة هذا المجلد";
"Modify the acl of this folder" = "تعديل قائمة الصلاحيات لهذا المجلد";
"Saved Messages.zip" = "حفظ Messages.zip";
@@ -79,7 +79,6 @@
"Remove this folder" = "Fjern denne mappe";
"Erase mails from this folder" = "Slet beskeder fra denne mappe";
"Expunge this folder" = "Slet denne mappe";
"Archive This Folder" = "Gem denne mappe";
"Modify the acl of this folder" = "Rediger ACL i denne mappe";
"Saved Messages.zip" = "Gemte beskeder.zip";
@@ -76,7 +76,6 @@
"Remove this folder" = "Fjarlægja þessa möppu";
"Erase mails from this folder" = "Eyða bréfum úr þessari möppu";
"Expunge this folder" = "Afmá allt í þessari möppu";
"Archive This Folder" = "Setja þessa möppu í geymslu";
"Modify the acl of this folder" = "Breyta aðgangsstýringum fyrir þessa möppu";
"Saved Messages.zip" = "vistud_skilabod.zip";
@@ -79,7 +79,6 @@
"Remove this folder" = "Rimuovi questa cartella";
"Erase mails from this folder" = "Elimina emails da questa cartella";
"Expunge this folder" = "Pulisci questa cartella";
"Archive This Folder" = "Archivia questa cartella";
"Modify the acl of this folder" = "Modifica i permessi per questa cartella";
"Saved Messages.zip" = "Salvato Messages.zip";
@@ -76,7 +76,6 @@
"Remove this folder" = "Ta bort mappen";
"Erase mails from this folder" = "Slett meldinger fra mappen";
"Expunge this folder" = "Fjern mappen";
"Archive This Folder" = "Arkiver denne mappen";
"Modify the acl of this folder" = "Endre adgangsrettigheter til mappen";
"Saved Messages.zip" = "Lagrete Meldinger.zip";
@@ -76,7 +76,6 @@
"Remove this folder" = "Ta bort mappen";
"Erase mails from this folder" = "Radera meddelanden från mappen";
"Expunge this folder" = "Radera mappen";
"Archive This Folder" = "Arkivera mappen";
"Modify the acl of this folder" = "Ändra åtkomsträttigheter på mappen";
"Saved Messages.zip" = "Sparat Messages.zip";
+3 -1
View File
@@ -230,7 +230,9 @@ static NSArray *infoKeys = nil;
- (NSString *) localeCode
{
// WARNING : NSLocaleCode is not defined in <Foundation/NSUserDefaults.h>
return [locale objectForKey: @"NSLocaleCode"];
// Region subtag must be separated by a dash
NSString *s = [locale objectForKey: @"NSLocaleCode"];
return [s stringByReplacingOccurrencesOfString: @"_" withString: @"-"];
}
- (void) setFrom: (NSString *) newFrom
@@ -79,7 +79,6 @@
"Remove this folder" = "Вилучати цю теку";
"Erase mails from this folder" = "Вилучати повідомлення з цієї теки";
"Expunge this folder" = "Позначати листи як вилучені";
"Archive This Folder" = "Архівувати цю теку";
"Modify the acl of this folder" = "Керувати правами доступу до цієї теки";
"Saved Messages.zip" = "Збережено Messages.zip";
@@ -76,7 +76,6 @@
"Remove this folder" = "Dileu'r ffolder hwn";
"Erase mails from this folder" = "Dileu ebost o'r ffolder hwn";
"Expunge this folder" = "Dileu'r ffolder hwn";
"Archive This Folder" = "Archive This Folder";
"Modify the acl of this folder" = "Newid acl y ffolder";
"Saved Messages.zip" = "Saved Messages.zip";
+5 -2
View File
@@ -155,6 +155,7 @@
delta = [[currentDate timeZoneDetail] timeZoneSecondsFromGMT] - [[startDate timeZoneDetail] timeZoneSecondsFromGMT];
startInterval += (delta/60/15);
startInterval = (startInterval < -4 ? -4 : startInterval);
currentDate = [record objectForKey: @"endDate"];
if ([currentDate earlierDate: endDate] == endDate)
@@ -165,6 +166,8 @@
delta = [[currentDate timeZoneDetail] timeZoneSecondsFromGMT] - [[startDate timeZoneDetail] timeZoneSecondsFromGMT];
endInterval += (delta/60/15);
endInterval = (endInterval < 0 ? 0 : endInterval);
endInterval = (endInterval > itemCount+4 ? itemCount+4 : endInterval);
// Update bit string representation
// If the user is a resource with restristed amount of bookings, keep the sum of overlapping events
@@ -230,7 +233,7 @@
intervals = interval / intervalSeconds + 8;
// Build a bit string representation of the freebusy data for the period
freeBusyItems = NSZoneCalloc (NULL, intervals, sizeof (int));
freeBusyItems = calloc(intervals, sizeof (unsigned int));
[self _fillFreeBusyItems: (freeBusyItems+4)
count: (intervals-4)
withRecords: [fb fetchFreeBusyInfosFrom: start to: end forContact: uid]
@@ -243,7 +246,7 @@
{
[freeBusy addObject: [NSString stringWithFormat: @"%d", *(freeBusyItems + count)]];
}
NSZoneFree (NULL, freeBusyItems);
free(freeBusyItems);
// Return a NSString representation
return [freeBusy componentsJoinedByString: @","];
+1 -3
View File
@@ -1,8 +1,6 @@
/* UIxAttendeesEditor.h - this file is part of SOGo
*
* Copyright (C) 2007-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2007-2015 Inverse inc.
*
* 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
+1 -3
View File
@@ -1,8 +1,6 @@
/* UIxAttendeesEditor.m - this file is part of SOGo
*
* Copyright (C) 2007-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2007-2015 Inverse inc.
*
* 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
+3 -1
View File
@@ -82,7 +82,9 @@
- (NSString *) localeCode
{
// WARNING : NSLocaleCode is not defined in <Foundation/NSUserDefaults.h>
return [locale objectForKey: @"NSLocaleCode"];
// Region subtag must be separated by a dash
NSString *s = [locale objectForKey: @"NSLocaleCode"];
return [s stringByReplacingOccurrencesOfString: @"_" withString: @"-"];
}
- (NSArray *) monthMenuItems
+1 -1
View File
@@ -1,6 +1,6 @@
/* UIxComponentEditor.h - this file is part of SOGo
*
* Copyright (C) 2006-2014 Inverse inc.
* Copyright (C) 2006-2015 Inverse inc.
*
* 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
+7 -74
View File
@@ -176,7 +176,6 @@ iRANGE(2);
[self setIsCycleEndNever];
componentOwner = @"";
organizer = nil;
//organizerIdentity = nil;
organizerProfile = nil;
ownerAsAttendee = nil;
attendee = nil;
@@ -213,7 +212,6 @@ iRANGE(2);
[title release];
[location release];
[organizer release];
//[organizerIdentity release];
[organizerProfile release];
[ownerAsAttendee release];
[comment release];
@@ -820,25 +818,27 @@ iRANGE(2);
uid = email;
[profile setObject: name
forKey: @"name"];
forKey: @"name"];
[profile setObject: email
forKey: @"email"];
forKey: @"email"];
if (partstat == nil || ![partstat length])
partstat = @"accepted";
[profile setObject: partstat
forKey: @"partstat"];
forKey: @"partstat"];
if (role == nil || ![role length])
role = @"chair";
[profile setObject: role
forKey: @"role"];
forKey: @"role"];
organizerProfile = [NSDictionary dictionaryWithObject: profile forKey: uid];
[organizerProfile retain];
}
return organizerProfile;
}
@@ -897,30 +897,6 @@ iRANGE(2);
return [[[[self organizerProfile] allValues] lastObject] jsonRepresentation];
}
// - (BOOL) canBeOrganizer
// {
// NSString *owner;
// SOGoObject <SOGoComponentOccurence> *co;
// SOGoUser *currentUser;
// BOOL hasOrganizer;
// SoSecurityManager *sm;
// co = [self clientObject];
// owner = [co ownerInContext: context];
// currentUser = [context activeUser];
// hasOrganizer = ([[organizer value: 0] length] > 0);
// sm = [SoSecurityManager sharedSecurityManager];
// return ([co isNew]
// || (([owner isEqualToString: [currentUser login]]
// || ![sm validatePermission: SOGoCalendarPerm_ModifyComponent
// onObject: co
// inContext: context])
// && (!hasOrganizer || [component userIsOrganizer: currentUser])));
// }
- (BOOL) hasOrganizer
{
// We check if there's an organizer and if it's not ourself
@@ -948,51 +924,8 @@ iRANGE(2);
}
return NO;
//return ([[organizer value: 0] length] && ![self canBeOrganizer]);
}
//- (void) setOrganizerIdentity: (NSDictionary *) newOrganizerIdentity
//{
// ASSIGN (organizerIdentity, newOrganizerIdentity);
//}
// - (NSDictionary *) organizerIdentity
// {
// NSArray *allIdentities;
// NSEnumerator *identities;
// NSDictionary *currentIdentity;
// NSString *orgEmail;
// orgEmail = [organizer rfc822Email];
// if (!organizerIdentity)
// {
// if ([orgEmail length])
// {
// allIdentities = [[context activeUser] allIdentities];
// identities = [allIdentities objectEnumerator];
// while (!organizerIdentity
// && ((currentIdentity = [identities nextObject])))
// if ([[currentIdentity objectForKey: @"email"]
// caseInsensitiveCompare: orgEmail]
// == NSOrderedSame)
// ASSIGN (organizerIdentity, currentIdentity);
// }
// }
// return organizerIdentity;
// }
//- (NSArray *) organizerList
//{
// return [[context activeUser] allIdentities];
//}
//- (NSString *) itemOrganizerText
//{
// return [item keysWithFormat: @"%{fullName} <%{email}>"];
//}
- (BOOL) hasAttendees
{
return ([[component attendees] count] > 0);
+2 -2
View File
@@ -85,7 +85,7 @@
<li><var:string label:value="Mark Folder Read" /></li>
<li><var:string label:value="New Subfolder..." /></li>
<li><var:string label:value="Compact This Folder" /></li>
<li><var:string label:value="Archive This Folder" /></li>
<li><var:string label:value="Export This Folder" /></li>
<li><var:string label:value="Empty Trash" /></li>
<li><!-- separator --></li>
<li><var:string label:value="Search Messages..." /></li>
@@ -103,7 +103,7 @@
<li><var:string label:value="New Subfolder..." /></li>
<li><var:string label:value="Rename Folder..." /></li>
<li><var:string label:value="Compact This Folder" /></li>
<li><var:string label:value="Archive This Folder" /></li>
<li><var:string label:value="Export This Folder" /></li>
<li><var:string label:value="Delete Folder" /></li>
<li><var:string label:value="Use This Folder For" /></li>
<li><!-- separator --></li>
@@ -218,7 +218,7 @@ Date.prototype.stringWithSeparator = function(separator) {
Date.prototype.addDays = function(nbrDays) {
var milliSeconds = this.getTime();
milliSeconds += 86400000 * nbrDays;
milliSeconds += 86400000 * Math.round(nbrDays);
this.setTime(milliSeconds);
};
+52 -32
View File
@@ -896,9 +896,8 @@ _freeBusyCacheEntry.prototype = {
if (this.entries.length > offset) {
var adjustedEd = ed.beginOfDay();
var nbrDays = adjustedSd.deltaDays(adjustedEd) + 1;
var nbrQu = nbrDays * 96;
var offsetEnd = offset + nbrQu;
if (this.entries.length >= offsetEnd) {
var offsetEnd = offset + (nbrDays * 96);
if (Math.round(this.entries.length/96) >= nbrDays) {
entries = this.entries.slice(offset, offsetEnd);
}
}
@@ -912,15 +911,19 @@ _freeBusyCacheEntry.prototype = {
var adjustedSd = sd.beginOfDay();
var adjustedEd = ed.beginOfDay();
var nbrDays = adjustedSd.deltaDays(adjustedEd) + 1;
var start = adjustedSd.clone();
start.addDays(-7);
var end = adjustedEd.clone();
end.addDays(7);
if (this.startDate) {
fetchDates = [];
if (adjustedSd.getTime() < this.startDate.getTime()) {
var start = adjustedSd.clone();
start.addDays(-7);
var end = this.startDate.beginOfDay();
end.addDays(-1);
// Period extends to before current start
if (end.getTime() >= this.startDate.getTime()) {
end = this.startDate.beginOfDay();
end.addDays(-1);
}
fetchDates.push({ start: start, end: end });
}
@@ -928,16 +931,16 @@ _freeBusyCacheEntry.prototype = {
var nextDate = this.startDate.clone();
nextDate.addDays(currentNbrDays);
if (adjustedEd.getTime() >= nextDate.getTime()) {
var end = nextDate.clone();
end.addDays(7);
fetchDates.push({ start: nextDate, end: end });
// Period extends to after current end
if (start.getTime() <= nextDate.getTime()) {
start = nextDate.beginOfDay();
start.addDays(1);
}
fetchDates.push({ start: start, end: end });
}
}
else {
var start = adjustedSd.clone();
start.addDays(-7);
var end = adjustedEd.clone();
end.addDays(7);
// Initial range
fetchDates = [ { start: start, end: end } ];
}
@@ -945,18 +948,27 @@ _freeBusyCacheEntry.prototype = {
},
integrateEntries: function fBCE_integrateEntries(entries, start, end) {
var days, merged = false;
if (this.startDate) {
if (start.getTime() < this.startDate) {
var days = start.deltaDays(this.startDate);
days = start.deltaDays(this.startDate);
if (entries.length == (days * 96)) {
// New period is just before previous period
this.startDate = start;
this.entries = entries.concat(this.entries);
merged = true;
}
}
else {
this.entries = this.entries.concat(entries);
days = this.startDate.deltaDays(start);
if (Math.round(this.entries.length/96) == days) {
// New period is just after previous period
this.entries = this.entries.concat(entries);
merged = true;
}
}
} else {
}
if (!merged) {
this.startDate = start;
this.entries = entries;
}
@@ -1193,7 +1205,7 @@ function drawFbData(input, slots) {
else {
log("inconsistency between freebusy results and"
+ " the number of cells");
log(" expecting: " + tds.length + " received: " + slots.length);
log(" expecting: " + (tds.length * 4) + " received: " + slots.length);
}
}
@@ -1674,10 +1686,10 @@ function initTimeWidgets(widgets) {
function onAdjustTime(event) {
var endDate = window.getEndDate();
var startDate = window.getStartDate();
var delta = 0;
if (this.id.startsWith("start")) {
// Start date was changed
var delta = window.getShadowStartDate().valueOf() -
startDate.valueOf();
delta = window.getShadowStartDate().valueOf() - startDate.valueOf();
var newEndDate = new Date(endDate.valueOf() - delta);
window.setEndDate(newEndDate);
window.timeWidgets['end']['date'].updateShadowValue();
@@ -1687,20 +1699,27 @@ function onAdjustTime(event) {
}
else {
// End date was changed
var delta = endDate.valueOf() - startDate.valueOf();
if (delta < 0) {
showAlertDialog(labels.validate_endbeforestart);
var oldEndDate = window.getShadowEndDate();
window.setEndDate(oldEndDate);
window.timeWidgets['end']['date'].updateShadowValue();
window.timeWidgets['end']['time'].updateShadowValue();
window.timeWidgets['end']['time'].onChange(); // method from SOGoTimePicker
delta = window.getShadowEndDate().valueOf() - endDate.valueOf();
if (delta != 0) {
var startEndDelta = endDate.valueOf() - startDate.valueOf();
if (startEndDelta < 0) {
showAlertDialog(labels.validate_endbeforestart);
var oldEndDate = window.getShadowEndDate();
window.setEndDate(oldEndDate);
window.timeWidgets['end']['date'].updateShadowValue();
window.timeWidgets['end']['time'].updateShadowValue();
window.timeWidgets['end']['time'].onChange(); // method from SOGoTimePicker
}
else {
window.timeWidgets['end']['date'].updateShadowValue();
window.timeWidgets['end']['time'].updateShadowValue();
}
}
}
// Specific function for the attendees editor
onTimeDateWidgetChange();
if ($("freeBusyHeader").getElementsByTagName("th").length == 0 || delta != 0)
// Update freebusy data
onTimeDateWidgetChange();
}
function _getDate(which) {
@@ -1739,6 +1758,7 @@ function getShadowEndDate() {
function _setDate(which, newDate) {
window.timeWidgets[which]['date'].setInputAsDate(newDate);
jQuery(window.timeWidgets[which]['date']).closest('.date').datepicker('update');
if (!isAllDay) {
window.timeWidgets[which]['time'].value = newDate.getDisplayHoursString();
if (window.timeWidgets[which]['time'].onChange) window.timeWidgets[which]['time'].onChange(); // method from SOGoTimePicker
+1 -1
View File
@@ -4,4 +4,4 @@
MAJOR_VERSION=2
MINOR_VERSION=2
SUBMINOR_VERSION=16
SUBMINOR_VERSION=17