mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-06-03 17:39:45 +00:00
Merge to 2.2.10
Conflicts: NEWS Version
This commit is contained in:
@@ -222,7 +222,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[self setNote: o];
|
||||
|
||||
// Categories
|
||||
if ((o = [theValues objectForKey: @"Categories"]))
|
||||
if ((o = [theValues objectForKey: @"Categories"]) && [o length])
|
||||
[self setCategories: o];
|
||||
|
||||
// Birthday
|
||||
|
||||
@@ -35,9 +35,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <Foundation/NSDate.h>
|
||||
|
||||
#include <SOGo/NSString+Utilities.h>
|
||||
#include <SOGo/NSData+Crypto.h>
|
||||
|
||||
#include <NGExtensions/NGBase64Coding.h>
|
||||
#include <NGExtensions/NSString+misc.h>
|
||||
|
||||
static NSArray *easCommandCodes = nil;
|
||||
static NSArray *easCommandParameters = nil;
|
||||
|
||||
@implementation NSString (ActiveSync)
|
||||
|
||||
- (NSString *) sanitizedServerIdWithType: (SOGoMicrosoftActiveSyncFolderType) folderType
|
||||
@@ -61,9 +66,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
s = [self stringByEscapingHTMLString];
|
||||
s = [self safeString];
|
||||
|
||||
return [s safeString];
|
||||
return [s stringByEscapingHTMLString];
|
||||
}
|
||||
|
||||
- (int) activeSyncFolderType
|
||||
@@ -134,11 +139,78 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
- (NSString *) _valueForParameter: (NSString *) theParameter
|
||||
{
|
||||
NSArray *components;
|
||||
NSMutableArray *components;
|
||||
NSString *s;
|
||||
int i;
|
||||
|
||||
components = [[[self componentsSeparatedByString: @"?"] lastObject] componentsSeparatedByString: @"&"];
|
||||
components = [NSMutableArray arrayWithArray: [[[self componentsSeparatedByString: @"?"] lastObject] componentsSeparatedByString: @"&"]];
|
||||
|
||||
// We handle BASE64 encoded queryStrings. See http://msdn.microsoft.com/en-us/library/ee160227%28v=exchg.80%29.aspx for details.
|
||||
if ([components count] == 1)
|
||||
{
|
||||
NSString *deviceType, *parameterValue;
|
||||
NSData *queryString;
|
||||
|
||||
int cmd_code, deviceid_length, policy_length, devicetype_length, parameter_code, parameter_length, i;
|
||||
const char* qs_bytes;
|
||||
|
||||
queryString = [[components objectAtIndex: 0] dataByDecodingBase64];
|
||||
qs_bytes = (const char*)[queryString bytes];
|
||||
|
||||
if (!easCommandCodes)
|
||||
{
|
||||
easCommandCodes = [NSArray arrayWithObjects:@"Sync", @"SendMail", @"SmartForward", @"SmartReply", @"GetAttachment", @"na", @"na", @"na", @"na",
|
||||
@"FolderSync", @"FolderCreate", @"FolderDelete", @"FolderUpdate", @"MoveItems", @"GetItemEstimate", @"MeetingResponse",
|
||||
@"Search", @"Settings", @"Ping", @"ItemOperations", @"Provision", @"ResolveRecipients", @"ValidateCert", nil];
|
||||
RETAIN(easCommandCodes);
|
||||
}
|
||||
|
||||
if (!easCommandParameters)
|
||||
{
|
||||
easCommandParameters = [NSArray arrayWithObjects:@"AttachmentName", @"CollectionId", @"na", @"ItemId", @"LongId", @"na", @"Occurrence", @"Options", @"User", nil];
|
||||
RETAIN(easCommandParameters);
|
||||
}
|
||||
|
||||
// Command code, 1 byte, ie.: cmd=
|
||||
cmd_code = qs_bytes[1];
|
||||
[components addObject: [NSString stringWithFormat: @"cmd=%@", [easCommandCodes objectAtIndex: cmd_code]]];
|
||||
|
||||
// Device ID length and Device ID (variable)
|
||||
deviceid_length = qs_bytes[4];
|
||||
[components addObject: [NSString stringWithFormat: @"deviceId=%@", [[NSData encodeDataAsHexString: [queryString subdataWithRange: NSMakeRange(5, deviceid_length)]] uppercaseString]]];
|
||||
|
||||
// Device type length and type (variable)
|
||||
policy_length = qs_bytes[5+deviceid_length];
|
||||
devicetype_length = qs_bytes[5+deviceid_length+1+policy_length];
|
||||
deviceType = [[NSString alloc] initWithData: [queryString subdataWithRange: NSMakeRange(5+deviceid_length+1+policy_length+1, devicetype_length)]
|
||||
encoding: NSASCIIStringEncoding];
|
||||
AUTORELEASE(deviceType);
|
||||
|
||||
[components addObject: [NSString stringWithFormat: @"deviceType=%@", deviceType]];
|
||||
|
||||
// Command Parameters
|
||||
i = 5+deviceid_length+1+policy_length+1+devicetype_length;
|
||||
|
||||
while (i < [queryString length])
|
||||
{
|
||||
parameter_code = qs_bytes[i];
|
||||
parameter_length = qs_bytes[i+1];
|
||||
parameterValue = [[NSString alloc] initWithData: [queryString subdataWithRange: NSMakeRange(i+1+1, parameter_length)]
|
||||
encoding: NSASCIIStringEncoding];
|
||||
|
||||
AUTORELEASE(parameterValue);
|
||||
|
||||
// parameter_code 7 == Options
|
||||
// http://msdn.microsoft.com/en-us/library/ee237789(v=exchg.80).aspx
|
||||
if (parameter_code == 7)
|
||||
[components addObject: [NSString stringWithFormat: @"%@=%@", [easCommandParameters objectAtIndex: parameter_code],
|
||||
([parameterValue isEqualToString: @"\001"]) ? @"SaveInSent" : @"AcceptMultiPart"]];
|
||||
else
|
||||
[components addObject: [NSString stringWithFormat: @"%@=%@", [easCommandParameters objectAtIndex: parameter_code], parameterValue]];
|
||||
|
||||
i = i + 1 + 1 + parameter_length;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < [components count]; i++)
|
||||
{
|
||||
|
||||
@@ -29,11 +29,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#import "SOGoActiveSyncDispatcher+Sync.h"
|
||||
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSNull.h>
|
||||
#import <Foundation/NSProcessInfo.h>
|
||||
#import <Foundation/NSSortDescriptor.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
#import <Foundation/NSURL.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
@@ -122,7 +122,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[o setObjectType: ActiveSyncFolderCacheObject];
|
||||
[o setTableUrl: [self folderTableURL]];
|
||||
[o reloadIfNeeded];
|
||||
|
||||
|
||||
[[o properties] removeObjectForKey: @"SyncKey"];
|
||||
[[o properties] removeObjectForKey: @"SyncCache"];
|
||||
[[o properties] removeObjectForKey: @"DateCache"];
|
||||
@@ -147,6 +147,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
return [o properties];
|
||||
}
|
||||
|
||||
- (NSString *) _getNameInCache: (id) theCollection withType: (SOGoMicrosoftActiveSyncFolderType) theFolderType
|
||||
{
|
||||
NSString *nameInCache;
|
||||
|
||||
if (theFolderType == ActiveSyncMailFolder)
|
||||
nameInCache= [[[theCollection mailAccountFolder] imapFolderGUIDs] objectForKey: [theCollection nameInContainer]];
|
||||
else
|
||||
{
|
||||
NSString *component_name;
|
||||
if (theFolderType == ActiveSyncContactFolder)
|
||||
component_name = @"vcard";
|
||||
else if (theFolderType == ActiveSyncEventFolder)
|
||||
component_name = @"vevent";
|
||||
else
|
||||
component_name = @"vtodo";
|
||||
|
||||
nameInCache= [NSString stringWithFormat: @"%@/%@", component_name, [theCollection nameInContainer]];
|
||||
}
|
||||
|
||||
return nameInCache;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// <?xml version="1.0"?>
|
||||
@@ -190,7 +213,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
withType: (SOGoMicrosoftActiveSyncFolderType) theFolderType
|
||||
inBuffer: (NSMutableString *) theBuffer
|
||||
{
|
||||
NSMutableDictionary *allValues;
|
||||
NSMutableDictionary *folderMetadata, *dateCache, *syncCache, *allValues;
|
||||
NSString *clientId, *serverId;
|
||||
NSArray *additions;
|
||||
|
||||
@@ -276,6 +299,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[theBuffer appendFormat: @"<ServerId>%@</ServerId>", serverId];
|
||||
[theBuffer appendFormat: @"<Status>%d</Status>", 1];
|
||||
[theBuffer appendString: @"</Add>"];
|
||||
|
||||
// Update syncCache
|
||||
folderMetadata = [self _folderMetadataForKey: [self _getNameInCache: theCollection withType: theFolderType]];
|
||||
|
||||
syncCache = [folderMetadata objectForKey: @"SyncCache"];
|
||||
dateCache = [folderMetadata objectForKey: @"DateCache"];
|
||||
|
||||
[syncCache setObject: [folderMetadata objectForKey: @"SyncKey"] forKey: serverId];
|
||||
[dateCache setObject: [NSCalendarDate date] forKey: serverId];
|
||||
|
||||
[self _setFolderMetadata: folderMetadata forKey: [self _getNameInCache: theCollection withType: theFolderType]];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -375,6 +409,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
}
|
||||
}
|
||||
|
||||
[theBuffer appendString: @"<Change>"];
|
||||
[theBuffer appendFormat: @"<ServerId>%@</ServerId>", serverId];
|
||||
[theBuffer appendFormat: @"<Status>%d</Status>", 1];
|
||||
[theBuffer appendString: @"</Change>"];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -431,6 +469,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
if (![sogoObject isKindOfClass: [NSException class]])
|
||||
[sogoObject delete];
|
||||
|
||||
[theBuffer appendString: @"<Delete>"];
|
||||
[theBuffer appendFormat: @"<ServerId>%@</ServerId>", serverId];
|
||||
[theBuffer appendFormat: @"<Status>%d</Status>", 1];
|
||||
[theBuffer appendString: @"</Delete>"];
|
||||
|
||||
// update syncCache
|
||||
NSMutableDictionary *folderMetadata, *dateCache, *syncCache;
|
||||
folderMetadata = [self _folderMetadataForKey: [self _getNameInCache: theCollection withType: theFolderType]];
|
||||
|
||||
syncCache = [folderMetadata objectForKey: @"SyncCache"];
|
||||
dateCache = [folderMetadata objectForKey: @"DateCache"];
|
||||
|
||||
[syncCache removeObjectForKey: serverId];
|
||||
[dateCache removeObjectForKey: serverId];
|
||||
|
||||
[self _setFolderMetadata: folderMetadata forKey: [self _getNameInCache: theCollection withType: theFolderType]];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -488,18 +543,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
more_available = NO;
|
||||
|
||||
if (theFolderType == ActiveSyncMailFolder && !([theSyncKey isEqualToString: @"-1"]) && theFilterType)
|
||||
folderMetadata = [self _folderMetadataForKey: [self _getNameInCache: theCollection withType: theFolderType]];
|
||||
|
||||
// If this is a new sync operation, DateCache and SyncCache needs to be deleted
|
||||
if ([theSyncKey isEqualToString: @"-1"])
|
||||
{
|
||||
[folderMetadata setObject: [NSMutableDictionary dictionary] forKey: @"SyncCache"];
|
||||
[folderMetadata setObject: [NSMutableDictionary dictionary] forKey: @"DateCache"];
|
||||
}
|
||||
|
||||
syncCache = [folderMetadata objectForKey: @"SyncCache"];
|
||||
dateCache = [folderMetadata objectForKey: @"DateCache"];
|
||||
|
||||
if ((theFolderType == ActiveSyncMailFolder || theFolderType == ActiveSyncEventFolder || theFolderType == ActiveSyncTaskFolder) &&
|
||||
!([folderMetadata objectForKey: @"MoreAvailable"]) && // previous sync operation reached the windowSize
|
||||
!([theSyncKey isEqualToString: @"-1"]) && // new sync operation
|
||||
theFilterType)
|
||||
{
|
||||
NSArray *allKeys;
|
||||
NSString *key;
|
||||
|
||||
int softdelete_count;
|
||||
|
||||
softdelete_count = 0;
|
||||
|
||||
folderMetadata = [self _folderMetadataForKey: [theCollection nameInContainer]];
|
||||
dateCache = [folderMetadata objectForKey: @"DateCache"];
|
||||
syncCache = [folderMetadata objectForKey: @"SyncCache"];
|
||||
|
||||
allKeys = [dateCache allKeys];
|
||||
for (i = 0; i < [allKeys count]; i++)
|
||||
{
|
||||
@@ -510,7 +577,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[s appendString: @"<SoftDelete xmlns=\"AirSync:\">"];
|
||||
[s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", key];
|
||||
[s appendString: @"</SoftDelete>"];
|
||||
|
||||
|
||||
[syncCache removeObjectForKey: key];
|
||||
[dateCache removeObjectForKey: key];
|
||||
|
||||
@@ -520,7 +587,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
if (softdelete_count >= theWindowSize)
|
||||
{
|
||||
[folderMetadata setObject: [NSNumber numberWithBool: YES] forKey: @"MoreAvailable"];
|
||||
[self _setFolderMetadata: folderMetadata forKey: [theCollection nameInContainer]];
|
||||
[self _setFolderMetadata: folderMetadata forKey: [self _getNameInCache: theCollection withType: theFolderType]];
|
||||
|
||||
more_available = YES;
|
||||
*theLastServerKey = theSyncKey;
|
||||
@@ -532,7 +599,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
}
|
||||
|
||||
[folderMetadata removeObjectForKey: @"MoreAvailable"];
|
||||
[self _setFolderMetadata: folderMetadata forKey: [theCollection nameInContainer]];
|
||||
[self _setFolderMetadata: folderMetadata forKey: [self _getNameInCache: theCollection withType: theFolderType]];
|
||||
}
|
||||
|
||||
//
|
||||
@@ -557,7 +624,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
NSArray *allComponents;
|
||||
|
||||
BOOL updated;
|
||||
int deleted;
|
||||
int deleted, return_count;
|
||||
|
||||
if (theFolderType == ActiveSyncContactFolder)
|
||||
component_name = @"vcard";
|
||||
@@ -567,19 +634,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
component_name = @"vtodo";
|
||||
|
||||
allComponents = [theCollection syncTokenFieldsWithProperties: nil matchingSyncToken: theSyncKey fromDate: theFilterType];
|
||||
allComponents = [allComponents sortedArrayUsingDescriptors: [NSArray arrayWithObjects: [[NSSortDescriptor alloc] initWithKey: @"c_lastmodified" ascending:YES], nil]];
|
||||
|
||||
// Check for the WindowSize
|
||||
max = [allComponents count];
|
||||
|
||||
// Disabled for now for GCS folders.
|
||||
// if (max > theWindowSize)
|
||||
// {
|
||||
// max = theWindowSize;
|
||||
// more_available = YES;
|
||||
// }
|
||||
|
||||
return_count = 0;
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
// Check for the WindowSize and slice accordingly
|
||||
if (return_count >= theWindowSize)
|
||||
{
|
||||
more_available = YES;
|
||||
|
||||
// -1 to make sure that we miss no event in case there are more with the same c_lastmodified
|
||||
*theLastServerKey = [NSString stringWithFormat: @"%d", [[component objectForKey: @"c_lastmodified"] intValue] - 1];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
component = [allComponents objectAtIndex: i];
|
||||
deleted = [[component objectForKey: @"c_deleted"] intValue];
|
||||
|
||||
@@ -590,17 +664,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
if (deleted)
|
||||
{
|
||||
[s appendString: @"<Delete xmlns=\"AirSync:\">"];
|
||||
[s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", uid];
|
||||
[s appendString: @"</Delete>"];
|
||||
if ([syncCache objectForKey: uid])
|
||||
{
|
||||
[s appendString: @"<Delete xmlns=\"AirSync:\">"];
|
||||
[s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", uid];
|
||||
[s appendString: @"</Delete>"];
|
||||
|
||||
[syncCache removeObjectForKey: uid];
|
||||
[dateCache removeObjectForKey: uid];
|
||||
return_count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
updated = YES;
|
||||
|
||||
if ([[component objectForKey: @"c_creationdate"] intValue] > [theSyncKey intValue])
|
||||
if (![syncCache objectForKey: uid])
|
||||
updated = NO;
|
||||
else if ([[component objectForKey: @"c_lastmodified"] intValue] == [[syncCache objectForKey: uid] intValue])
|
||||
continue;
|
||||
|
||||
return_count++;
|
||||
|
||||
sogoObject = [theCollection lookupName: [uid sanitizedServerIdWithType: theFolderType]
|
||||
inContext: context
|
||||
acquire: 0];
|
||||
@@ -635,11 +720,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
[syncCache setObject: [component objectForKey: @"c_lastmodified"] forKey: uid];
|
||||
|
||||
if (updated)
|
||||
[s appendString: @"<Change xmlns=\"AirSync:\">"];
|
||||
else
|
||||
{
|
||||
// no need to set dateCache for Contacts
|
||||
if ((theFolderType == ActiveSyncEventFolder || theFolderType == ActiveSyncTaskFolder))
|
||||
[dateCache setObject: [componentObject startDate] ? [componentObject startDate] : [NSCalendarDate date] forKey: uid]; // FIXME: need to set proper date for recurring events - softDelete
|
||||
|
||||
[s appendString: @"<Add xmlns=\"AirSync:\">"];
|
||||
}
|
||||
|
||||
[s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", uid];
|
||||
[s appendString: @"<ApplicationData xmlns=\"AirSync:\">"];
|
||||
@@ -652,11 +745,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[s appendString: @"</Change>"];
|
||||
else
|
||||
[s appendString: @"</Add>"];
|
||||
|
||||
return_count++;
|
||||
}
|
||||
} // for ...
|
||||
|
||||
folderMetadata = [NSDictionary dictionaryWithObject: [theCollection davCollectionTag]
|
||||
forKey: @"SyncKey"];
|
||||
if (more_available)
|
||||
{
|
||||
[folderMetadata setObject: [NSNumber numberWithBool: YES] forKey: @"MoreAvailable"];
|
||||
[folderMetadata setObject: *theLastServerKey forKey: @"SyncKey"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[folderMetadata removeObjectForKey: @"MoreAvailable"];
|
||||
[folderMetadata setObject: [theCollection davCollectionTag] forKey: @"SyncKey"];
|
||||
}
|
||||
|
||||
[self _setFolderMetadata: folderMetadata
|
||||
forKey: [NSString stringWithFormat: @"%@/%@", component_name, [theCollection nameInContainer]]];
|
||||
}
|
||||
@@ -685,27 +789,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
sequence: [[[allMessages objectAtIndex: i] allValues] lastObject]]];
|
||||
}
|
||||
|
||||
// If it's a new Sync operation, DateCache and SyncCache need to be deleted
|
||||
// but GUID stored by folderSync shouldn't be touched
|
||||
folderMetadata = [self _folderMetadataForKey: [theCollection nameInContainer]];
|
||||
if ([theSyncKey isEqualToString: @"-1"])
|
||||
{
|
||||
[folderMetadata setObject: [NSMutableDictionary dictionary] forKey: @"SyncCache"];
|
||||
[folderMetadata setObject: [NSMutableDictionary dictionary] forKey: @"DateCache"];
|
||||
}
|
||||
|
||||
// Check whether GUID in cache is equal to the GUID from imap - this is to avoid cache corruptions if a folder has been renamed and a new folder
|
||||
// with the same name has been created but folderSync has not yet updated the cache
|
||||
if (!([[theCollection nameInContainer] isEqualToString:
|
||||
[NSString stringWithFormat: @"folder%@", [self globallyUniqueIDToIMAPFolderName: [folderMetadata objectForKey: @"GUID"] type: theFolderType]]]))
|
||||
{
|
||||
NSLog(@"GUID mismatch don't sync now!");
|
||||
return;
|
||||
}
|
||||
|
||||
syncCache = [folderMetadata objectForKey: @"SyncCache"];
|
||||
dateCache = [folderMetadata objectForKey: @"DateCache"];
|
||||
|
||||
sortedBySequence = [[NSMutableArray alloc] initWithDictionary: syncCache];
|
||||
[sortedBySequence sortUsingSelector: @selector(compareSequence:)];
|
||||
[sortedBySequence autorelease];
|
||||
@@ -849,8 +932,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[folderMetadata setObject: [theCollection davCollectionTag] forKey: @"SyncKey"];
|
||||
}
|
||||
|
||||
[self _setFolderMetadata: folderMetadata
|
||||
forKey: [theCollection nameInContainer]];
|
||||
[self _setFolderMetadata: folderMetadata forKey: [self _getNameInCache: theCollection withType: theFolderType]];
|
||||
} // default:
|
||||
break;
|
||||
} // switch (folderType) ...
|
||||
@@ -862,9 +944,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[theBuffer appendString: @"<Commands>"];
|
||||
[theBuffer appendString: s];
|
||||
[theBuffer appendString: @"</Commands>"];
|
||||
|
||||
if (more_available)
|
||||
[theBuffer appendString: @"<MoreAvailable/>"];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -926,6 +1005,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
inCollection: theCollection
|
||||
withType: theFolderType
|
||||
inBuffer: theBuffer];
|
||||
*processed = YES;
|
||||
}
|
||||
else if ([[element tagName] isEqualToString: @"Fetch"])
|
||||
{
|
||||
@@ -954,7 +1034,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
NSMutableString *changeBuffer, *commandsBuffer;
|
||||
BOOL getChanges, first_sync;
|
||||
unsigned int windowSize, v;
|
||||
unsigned int windowSize, v, status;
|
||||
|
||||
changeBuffer = [NSMutableString string];
|
||||
commandsBuffer = [NSMutableString string];
|
||||
@@ -965,6 +1045,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
collection = [self collectionFromId: realCollectionId type: folderType];
|
||||
|
||||
syncKey = davCollectionTag = [[(id)[theDocumentElement getElementsByTagName: @"SyncKey"] lastObject] textValue];
|
||||
|
||||
if (collection == nil)
|
||||
{
|
||||
// Collection not found - next folderSync will do the cleanup
|
||||
//NSLog(@"Sync Collection not found %@ %@", collectionId, realCollectionId);
|
||||
[theBuffer appendString: @"<Collection>"];
|
||||
[theBuffer appendFormat: @"<SyncKey>%@</SyncKey>", syncKey];
|
||||
[theBuffer appendFormat: @"<CollectionId>%@</CollectionId>", collectionId];
|
||||
[theBuffer appendFormat: @"<Status>%d</Status>", 8];
|
||||
[theBuffer appendString: @"</Collection>"];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We check for a window size, default to 100 if not specfied or out of bounds
|
||||
windowSize = [[[(id)[theDocumentElement getElementsByTagName: @"WindowSize"] lastObject] textValue] intValue];
|
||||
@@ -978,6 +1071,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
windowSize = v;
|
||||
|
||||
lastServerKey = nil;
|
||||
status = 1;
|
||||
|
||||
// From the documention, if GetChanges is missing, we must assume it's a YES.
|
||||
// See http://msdn.microsoft.com/en-us/library/gg675447(v=exchg.80).aspx for all details.
|
||||
@@ -995,6 +1089,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
first_sync = YES;
|
||||
*changeDetected = YES;
|
||||
}
|
||||
else if ((![syncKey isEqualToString: @"-1"]) && !([[self _folderMetadataForKey: [self _getNameInCache: collection withType: folderType]] objectForKey: @"SyncCache"]))
|
||||
{
|
||||
//NSLog(@"Reset folder: %@", [collection nameInContainer]);
|
||||
davCollectionTag = @"0";
|
||||
first_sync = YES;
|
||||
*changeDetected = YES;
|
||||
|
||||
if (!([[self _folderMetadataForKey: [self _getNameInCache: collection withType: folderType]] objectForKey: @"displayName"]))
|
||||
status = 13; // need folderSync
|
||||
else
|
||||
status = 3; // do a complete resync
|
||||
}
|
||||
|
||||
// We check our sync preferences and we stash them
|
||||
bodyPreferenceType = [[(id)[[(id)[theDocumentElement getElementsByTagName: @"BodyPreference"] lastObject] getElementsByTagName: @"Type"] lastObject] textValue];
|
||||
@@ -1004,7 +1110,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
[context setObject: bodyPreferenceType forKey: @"BodyPreferenceType"];
|
||||
|
||||
|
||||
// We generate the commands, if any, for the response. We might also have
|
||||
// generated some in processSyncCommand:inResponse: as we could have
|
||||
// received a Fetch command
|
||||
@@ -1013,9 +1118,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[self processSyncGetChanges: theDocumentElement
|
||||
inCollection: collection
|
||||
withWindowSize: windowSize
|
||||
//withWindowSize: 5
|
||||
withSyncKey: syncKey
|
||||
withFolderType: folderType
|
||||
withFilterType: [NSCalendarDate dateFromFilterType: [[(id)[theDocumentElement getElementsByTagName: @"FilterType"] lastObject] textValue]]
|
||||
//withFilterType: [NSCalendarDate dateFromFilterType: @"7"]
|
||||
inBuffer: changeBuffer
|
||||
lastServerKey: &lastServerKey];
|
||||
}
|
||||
@@ -1037,10 +1144,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
inBuffer: s
|
||||
processed: &processed];
|
||||
|
||||
if (processed)
|
||||
// Windows phons don't empty Responses tags - such as: <Responses></Responses>.
|
||||
// We onnly generate this tag when the command has generated a response.
|
||||
if (processed && [s length])
|
||||
[commandsBuffer appendFormat: @"<Responses>%@</Responses>", s];
|
||||
else
|
||||
[commandsBuffer appendString: s];
|
||||
}
|
||||
|
||||
// If we got any changes or if we have applied any commands
|
||||
@@ -1049,9 +1156,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{
|
||||
if (lastServerKey)
|
||||
davCollectionTag = lastServerKey;
|
||||
else if (![[self _folderMetadataForKey: [collection nameInContainer]] objectForKey: @"MoreAvailable"])
|
||||
davCollectionTag = [collection davCollectionTag];
|
||||
|
||||
else
|
||||
{
|
||||
// Use the SyncKey saved by processSyncGetChanges - if processSyncGetChanges is not called (because of getChanges=false)
|
||||
// SyncKey has the value of the previous sync operation.
|
||||
davCollectionTag = [[self _folderMetadataForKey: [self _getNameInCache: collection withType: folderType]] objectForKey: @"SyncKey"];
|
||||
|
||||
if (!davCollectionTag)
|
||||
davCollectionTag = [collection davCollectionTag];
|
||||
}
|
||||
|
||||
*changeDetected = YES;
|
||||
}
|
||||
else
|
||||
@@ -1074,10 +1188,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
[theBuffer appendFormat: @"<SyncKey>%@</SyncKey>", davCollectionTag];
|
||||
[theBuffer appendFormat: @"<CollectionId>%@</CollectionId>", collectionId];
|
||||
[theBuffer appendFormat: @"<Status>%d</Status>", 1];
|
||||
[theBuffer appendFormat: @"<Status>%d</Status>", status];
|
||||
|
||||
// MoreAvailable breaks Windows Mobile devices if not between <Status> and <Commands>
|
||||
// https://social.msdn.microsoft.com/Forums/en-US/040b254e-f47e-4cc1-a397-6d8393cdb819/airsyncmoreavailable-breaks-windows-mobile-devices-what-am-i-doing-wrong?forum=os_exchangeprotocols
|
||||
if ([[self _folderMetadataForKey: [self _getNameInCache: collection withType: folderType]] objectForKey: @"MoreAvailable"])
|
||||
[theBuffer appendString: @"<MoreAvailable/>"];
|
||||
|
||||
[theBuffer appendString: changeBuffer];
|
||||
[theBuffer appendString: commandsBuffer];
|
||||
[theBuffer appendString: changeBuffer];
|
||||
|
||||
[theBuffer appendString: @"</Collection>"];
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -67,8 +67,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <Appointments/iCalPerson+SOGo.h>
|
||||
#include <Mailer/NSString+Mail.h>
|
||||
#include <Mailer/SOGoMailBodyPart.h>
|
||||
|
||||
#include <SOGo/SOGoUser.h>
|
||||
#include <SOGo/NSString+Utilities.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t dwLowDateTime;
|
||||
@@ -323,6 +323,11 @@ struct GlobalObjectId {
|
||||
|
||||
if (s)
|
||||
{
|
||||
// We sanitize the content immediately, in case we have non-UNICODE safe
|
||||
// characters that would be re-encoded later in HTML entities and thus,
|
||||
// ignore afterwards.
|
||||
s = [s safeString];
|
||||
|
||||
body = [s dataUsingEncoding: NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,11 @@ ADDITIONAL_INCLUDE_DIRS += \
|
||||
-I../../SOPE
|
||||
|
||||
ADDITIONAL_LIB_DIRS += \
|
||||
-L../SoObjects/SOGo/SOGo.framework/ \
|
||||
-L../SoObjects/SOGo/SOGo.framework/Versions/Current/sogo \
|
||||
-L../SoObjects/SOGo/$(GNUSTEP_OBJ_DIR)/ \
|
||||
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \
|
||||
-L/usr/local/lib
|
||||
-L/usr/local/lib \
|
||||
-Wl,-rpath,$(GNUSTEP_SYSTEM_LIBRARIES)/sogo
|
||||
|
||||
BUNDLE_LIBS += \
|
||||
-lSOGo \
|
||||
|
||||
@@ -127,7 +127,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
tz = [(iCalDateTime *)[self firstChildWithTag: @"dtstart"] timeZone];
|
||||
|
||||
if (!tz)
|
||||
tz = [iCalTimeZone timeZoneForName: @"Europe/London"];
|
||||
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
|
||||
|
||||
[s appendFormat: @"<TimeZone xmlns=\"Calendar:\">%@</TimeZone>", [tz activeSyncRepresentationInContext: context]];
|
||||
|
||||
@@ -334,14 +334,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[o intValue];
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
if ((o = [theValues objectForKey: @"MeetingStatus"]))
|
||||
{
|
||||
[o intValue];
|
||||
}
|
||||
|
||||
//
|
||||
// 0- normal, 1- personal, 2- private and 3-confidential
|
||||
//
|
||||
@@ -361,14 +353,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[self setAccessClass: @"PUBLIC"];
|
||||
}
|
||||
}
|
||||
|
||||
if ((o = [theValues objectForKey: @"TimeZone"]))
|
||||
{
|
||||
// Ugh, we ignore it for now.
|
||||
userTimeZone = [[[context activeUser] userDefaults] timeZone];
|
||||
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
|
||||
[(iCalCalendar *) parent addTimeZone: tz];
|
||||
}
|
||||
|
||||
// We ignore TimeZone sent by mobile devices for now.
|
||||
// Some Windows devices don't send during event updates.
|
||||
//if ((o = [theValues objectForKey: @"TimeZone"]))
|
||||
// {
|
||||
userTimeZone = [[[context activeUser] userDefaults] timeZone];
|
||||
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
|
||||
[(iCalCalendar *) parent addTimeZone: tz];
|
||||
//}
|
||||
|
||||
// FIXME: merge with iCalToDo
|
||||
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
|
||||
@@ -481,11 +474,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
[self setOrganizer: person];
|
||||
}
|
||||
|
||||
//
|
||||
// iOS is plain stupid here. It seends event invitations with no Organizer.
|
||||
// We check this corner-case and if MeetingStatus == 1 (see http://msdn.microsoft.com/en-us/library/ee219342(v=exchg.80).aspx or details)
|
||||
// and there's no organizer, we fake one.
|
||||
//
|
||||
if ((o = [theValues objectForKey: @"MeetingStatus"]))
|
||||
{
|
||||
if ([o intValue] == 1 && ![theValues objectForKey: @"Organizer_Email"])
|
||||
{
|
||||
iCalPerson *person;
|
||||
|
||||
person = [iCalPerson elementWithTag: @"organizer"];
|
||||
[person setEmail: [[[context activeUser] primaryIdentity] objectForKey: @"email"]];
|
||||
[person setCn: [[context activeUser] cn]];
|
||||
[person setPartStat: @"ACCEPTED"];
|
||||
[self setOrganizer: person];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Attendees - we don't touch the values if we're an attendee. This is gonna
|
||||
// be done automatically by the ActiveSync client when invoking MeetingResponse.
|
||||
if (![self userIsAttendee: [context activeUser]])
|
||||
{
|
||||
if ((o = [theValues objectForKey: @"Attendees"]))
|
||||
// Windows phones sens sometimes an empty Attendees tag.
|
||||
// We check it's an array before processing it.
|
||||
if ((o = [theValues objectForKey: @"Attendees"])&& [o isKindOfClass: [NSArray class]])
|
||||
{
|
||||
NSMutableArray *attendees;
|
||||
NSDictionary *attendee;
|
||||
|
||||
@@ -76,15 +76,17 @@ struct SYSTEMTIME {
|
||||
byMonth = [rrule byMonth];
|
||||
if ([byMonth count] > 0)
|
||||
{
|
||||
tzData->wYear = 0;
|
||||
tzData->wMonth = [[byMonth objectAtIndex: 0] intValue];
|
||||
mask = [rrule byDayMask];
|
||||
tzData->wDayOfWeek = [mask firstDay];
|
||||
tzData->wDay = [mask firstOccurrence];
|
||||
tzData->wDay = ([mask firstOccurrence] == -1) ? 5 : [mask firstOccurrence];
|
||||
|
||||
dateValue = [self startDate];
|
||||
tzData->wHour = [dateValue hourOfDay];
|
||||
tzData->wMinute = [dateValue minuteOfHour];
|
||||
tzData->wSecond = [dateValue secondOfMinute];
|
||||
tzData->wMilliseconds = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
all: $(patsubst %.asciidoc,%.pdf,$(wildcard *.asciidoc))
|
||||
|
||||
%.pdf : %.asciidoc
|
||||
asciidoc -a docinfo1 -b docbook -d book -d book -o $<.docbook $<
|
||||
asciidoc -a docinfo1 -b docbook -d book -o $<.docbook $<
|
||||
fop -c fonts/fop-config.xml -xsl docbook/xsl/sogo-fo.xsl -xml $<.docbook -pdf $@
|
||||
|
||||
clean:
|
||||
|
||||
@@ -193,7 +193,7 @@ installation for a Red Hat or CentOS distribution.
|
||||
Software Downloads
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
SOGo can be installed using the+yum+utility. To do so, first create
|
||||
SOGo can be installed using the `yum` utility. To do so, first create
|
||||
the `/etc/yum.repos.d/inverse.repo` configuration file with the following
|
||||
content:
|
||||
|
||||
@@ -258,13 +258,13 @@ In SOGo, the user's applications settings are stored
|
||||
in `/etc/sogo/sogo.conf`. You can use your favourite text editor to
|
||||
modify the file.
|
||||
|
||||
The +sogo.conf+ file is a serialized _property list_. This simple format
|
||||
The `sogo.conf` file is a serialized _property list_. This simple format
|
||||
encapsulates four basic data types: arrays, dictionaries (or hashes),
|
||||
strings and numbers. Numbers are represented as-is, except for booleans
|
||||
which can take the unquoted values `YES` and `NO`. Strings are not
|
||||
mandatorily quoted, but doing so will avoid you many problems. A
|
||||
dictionary is a sequence of key and value pairs separated in their
|
||||
middle with a `=` sign. It starts with a `\{` and ends with a
|
||||
middle with a `=` sign. It starts with a `{` and ends with a
|
||||
corresponding `}`. Each value definition in a dictionary ends with a
|
||||
semicolon. An array is a chain of values starting with `(` and ending
|
||||
with `)`, where the values are separated with a `,`. Also, the file
|
||||
@@ -1167,7 +1167,7 @@ keytool -import -keystore /etc/ssl/certs/java/cacerts \
|
||||
|
||||
*The certificate used by the CAS server must also be trusted by SOGo.*
|
||||
In case of a self-signed certificate, this means exporting tomcat's
|
||||
certificate using the +keytool+utility, converting it to PEM format and
|
||||
certificate using the `keytool` utility, converting it to PEM format and
|
||||
appending it to the `ca-certificates.crt` file (the name and location of
|
||||
that file differs between distributions). Basically:
|
||||
|
||||
@@ -1581,8 +1581,8 @@ Note that TLS is supported but SSL is not.
|
||||
|
||||
|D |SOGoSieveFolderEncoding
|
||||
|Parameter used to specify which encoding is used for IMAP folder names
|
||||
in Sieve filters. Defaults to "UTF-7". The other possible value is
|
||||
"UTF-8".
|
||||
in Sieve filters. Defaults to `UTF-7`. The other possible value is
|
||||
`UTF-8`.
|
||||
|
||||
|U |SOGoMailShowSubscribedFoldersOnly
|
||||
|Parameter used to specify if the Web interface should only show
|
||||
@@ -1632,6 +1632,12 @@ cronjob `sogo-tmpwatch`.
|
||||
|
||||
Defaults to `/var/spool/sogo`.
|
||||
|
||||
|S |NGImap4DisableIMAP4Pooling
|
||||
|Disables IMAP pooling when set to `YES`. Enable pooling by setting to
|
||||
`NO` or using a caching proxy like imapproxy.
|
||||
|
||||
The default value is `YES`.
|
||||
|
||||
|S |NGImap4ConnectionStringSeparator
|
||||
|Parameter used to set the IMAP mailbox separator. Setting this will
|
||||
also have an impact on the mailbox separator used by Sieve filters.
|
||||
@@ -1644,7 +1650,7 @@ SASL mechanism. Please note that feature might be limited at this time.
|
||||
|
||||
|D |NGImap4ConnectionGroupIdPrefix
|
||||
|Prefix to prepend to names in IMAP ACL transactions, to indicate the
|
||||
name is a group name not a user name.
|
||||
name is a group name, not a user name.
|
||||
|
||||
RFC4314 gives examples where group names are prefixed with `$`. Dovecot,
|
||||
for one, follows this scheme, and will, for example, apply permissions
|
||||
@@ -1993,7 +1999,7 @@ Defaults to `NO` when unset.
|
||||
SOGo Configuration Summary
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The complete SOGo configuration file+/etc/sogo/sogo.conf+should look
|
||||
The complete SOGo configuration file `/etc/sogo/sogo.conf` should look
|
||||
like this:
|
||||
|
||||
----
|
||||
@@ -2325,7 +2331,7 @@ ActiveSync:
|
||||
|Parameter used to set the maximum amount of time, in seconds, SOGo will
|
||||
wait before replying to a Ping command.
|
||||
|
||||
If not set, it defaults to `5` seconds.
|
||||
If not set, it defaults to `10` seconds.
|
||||
|
||||
|S |SOGoMaximumSyncInterval
|
||||
|Parameter used to set the maximum amount of time, in seconds, SOGo will
|
||||
@@ -2336,7 +2342,8 @@ If not set, it defaults to `30` seconds.
|
||||
|S |SOGoInternalSyncInterval
|
||||
|Parameter used to set the maximum amount of time, in seconds, SOGo will
|
||||
wait before doing an internal check for data changes (add, delete, and
|
||||
update). This parameter must be lower than _SOGoMaximumSyncInterval_.
|
||||
update). This parameter must be lower than _SOGoMaximumSyncInterval_ and
|
||||
_SOGoMaximumPingInterval_.
|
||||
|
||||
If not set, it defaults to `10` seconds.
|
||||
|
||||
@@ -2379,6 +2386,10 @@ see http://support.microsoft.com/kb/291621 for configuration
|
||||
instructions. On the SOGo side, _SOGoEnablePublicAccess_ must be set to
|
||||
`YES` and the URL to use must be of the following format:
|
||||
`http://<hostname>/SOGo/dav/public/%NAME%/freebusy.ifb`
|
||||
* If you have very large mail folders (thousands of messages), you will
|
||||
need to adjust the word size of your IMAP server. In Dovecot, the parameter
|
||||
to increase is "imap_max_line_length" while under Cyrus IMAP Server, the
|
||||
parameter is "maxword". We suggest a buffer of 2MB.
|
||||
|
||||
In order to use the SOGo ActiveSync support code in production
|
||||
environments, you need to get a proper usage license from Microsoft.
|
||||
|
||||
@@ -233,13 +233,12 @@ Installation
|
||||
This section will guide you through the installation of the native
|
||||
Microsoft Outlook compatibility layer SOGo offers.
|
||||
|
||||
Red Hat Enterprise Linux v5 and v6
|
||||
Red Hat Enterprise Linux v6 x86_64
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you are using Red Hat Enterprise Linux (or CentOS) version 5 or
|
||||
version 6, packages for Samba 4, OpenChange and SOGo and the SOGo
|
||||
OpenChange backend are available from SOGo's web site. Please follow the
|
||||
instructions from
|
||||
If you are using Red Hat Enterprise Linux version 6 x86_64, packages
|
||||
for Samba 4, OpenChange and SOGo and the SOGo OpenChange backend are
|
||||
available from SOGo's web site. Please follow the instructions from
|
||||
http://www.sogo.nu/english/downloads/backend_nightly.html.
|
||||
|
||||
In order to satisfy certain dependencies, you should also add the EPEL
|
||||
@@ -253,53 +252,48 @@ installation:
|
||||
|
||||
----
|
||||
yum clean all && yum makecache
|
||||
yum install samba4 \
|
||||
yum install samba \
|
||||
openchange \
|
||||
sogo-openchange-backend \
|
||||
openchange-ocsmanager \
|
||||
openchange-rpcproxy
|
||||
openchange-rpcproxy \
|
||||
mysql-server \
|
||||
MySQL-python
|
||||
----
|
||||
|
||||
Once the packages are installed, refer to the _Configuration_ chapter
|
||||
from this guide.
|
||||
|
||||
Debian 6.0 (Squeeze) and Ubuntu 12.04 (Precise Pangolin)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
[NOTE]
|
||||
Samba4/OpenChange are not available for now on CentOS 5 i386/x86_64,
|
||||
CentOS 6 i386 and CentOS 7.
|
||||
|
||||
Samba 4, OpenChange, SOGo and the SOGo OpenChange backend are now
|
||||
Debian 7.0 (Wheezy) and Ubuntu 12.04 (Precise Pangolin)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
SOGo, OpenChange and the SOGo OpenChange backend are now
|
||||
available from SOGo's web site. Please follow the instructions from
|
||||
http://www.sogo.nu/english/downloads/backend_nightly.html to setup your
|
||||
http://www.sogo.nu/english/downloads/backend.html to setup your
|
||||
apt sources.
|
||||
|
||||
Debian Squeeze ships an older version of some libraries required by
|
||||
Samba 4. In order to workaround this, users of this distribution will
|
||||
have to use the _squeeze-backports_ repository. To do so, create
|
||||
For Samba 4, you need to use the _wheezy-backports_ repository. To do so, create
|
||||
`/etc/apt/sources.list.d/backports.list`:
|
||||
|
||||
deb http://backports.debian.org/debian-backports squeeze-backports main
|
||||
deb http://http.debian.net/debian wheezy-backports main
|
||||
|
||||
Then install the dependencies on Debian Squeeze, do:
|
||||
On Ubuntu 12.04, you will also have to add the Wheezy sources:
|
||||
|
||||
----
|
||||
apt-get update
|
||||
apt-get install -t squeeze-backports libwbclient-dev samba-common smbclient libsmbclient libsmbclient-dev
|
||||
----
|
||||
deb http://ftp.us.debian.org/debian wheezy main
|
||||
deb http://security.debian.org/ wheezy/updates main
|
||||
|
||||
Once ready, install the `samba4` package on top of an existing SOGo
|
||||
Then install Samba 4 on top of an existing SOGo
|
||||
installation:
|
||||
|
||||
----
|
||||
apt-get update
|
||||
apt-get install samba4
|
||||
apt-get -t wheezy-backports install samba samba-dev
|
||||
----
|
||||
|
||||
The current post installation script shipped with the Samba 4 package is
|
||||
far from perfect and might fail even on a fresh install. The following
|
||||
command is needed to let dpkg know that everything is fine about Samba 4
|
||||
if the post install script fails.
|
||||
|
||||
sed --in-place 'N; s/Package: samba4\nStatus: install ok half-configured/Package: samba4\nStatus: install ok installed/;' /var/lib/dpkg/status
|
||||
|
||||
Once completed, install the packages related to OpenChange and the SOGo
|
||||
provider:
|
||||
|
||||
@@ -307,13 +301,53 @@ provider:
|
||||
apt-get install openchangeserver \
|
||||
sogo-openchange \
|
||||
openchangeproxy \
|
||||
openchange-ocsmanager \
|
||||
openchange-rpcproxy
|
||||
python-ocsmanager \
|
||||
mysql-server \
|
||||
python-mysqldb
|
||||
----
|
||||
|
||||
Once the packages are installed, refer to the _Configuration_ chapter
|
||||
from this guide.
|
||||
|
||||
[NOTE]
|
||||
On Ubuntu 12.04, the Samba init scripts need to be modified to
|
||||
disable the upstart check. For more details, refer to:
|
||||
https://wiki.samba.org/index.php/Samba4/InitScript
|
||||
|
||||
|
||||
Ubuntu 14.04 (Trusty Tahr)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For Ubuntu 14.04, you must not use the Debian Wheezy backports.
|
||||
|
||||
Please follow the instructions from
|
||||
http://www.sogo.nu/english/downloads/backend.html to setup your
|
||||
apt sources.
|
||||
|
||||
Then install Samba 4 on top of an existing SOGo
|
||||
installation:
|
||||
|
||||
----
|
||||
apt-get update
|
||||
apt-get install samba samba-dev
|
||||
----
|
||||
|
||||
Once completed, install the packages related to OpenChange and the SOGo
|
||||
provider:
|
||||
|
||||
----
|
||||
apt-get install openchangeserver \
|
||||
sogo-openchange \
|
||||
openchangeproxy \
|
||||
python-ocsmanager \
|
||||
mysql-server \
|
||||
python-mysqldb
|
||||
----
|
||||
|
||||
Once the packages are installed, refer to the _Configuration_ chapter
|
||||
from this guide.
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
@@ -349,16 +383,14 @@ You might consider changing the realm and domain used, to suit your
|
||||
enviroment.
|
||||
|
||||
You might also have to
|
||||
remove `/etc/samba4/smb.conf` (or `/etc/samba/smb.conf` on Debian-based
|
||||
distributions) prior running this command.
|
||||
remove `/etc/samba/smb.conf` prior running this command.
|
||||
|
||||
Add the following parameters to the `[global]` section of the
|
||||
`/etc/samba4/smb.conf` (`/samba/smb.conf` if you use a Debian-based
|
||||
distribution) configuration file:
|
||||
`/etc/samba/smb.conf` configuration file:
|
||||
|
||||
----
|
||||
### Configuration required by OpenChange server ###
|
||||
dcerpc endpoint servers = +epmapper, +mapiproxy
|
||||
dcerpc endpoint servers = epmapper, mapiproxy, dnsserver
|
||||
dcerpc_mapiproxy:server = true
|
||||
dcerpc_mapiproxy:interfaces = exchange_emsmdb, exchange_nsp, exchange_ds_rfr
|
||||
### Configuration required by OpenChange server ###
|
||||
@@ -392,11 +424,22 @@ Your Samba 4 configuration file should look like this:
|
||||
OpenChange Configuration
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
OpenChange 2.2 stores its metadata in MySQL so you need to have it installed.
|
||||
|
||||
First, create the OpenChange MySQL user:
|
||||
|
||||
----
|
||||
$ mysql -u root -p
|
||||
mysql> CREATE USER 'openchange-user'@'localhost' IDENTIFIED BY 'openchange$123';
|
||||
mysql> GRANT ALL PRIVILEGES ON `openchange`.* TO 'openchange-user'@'localhost' WITH GRANT OPTION;
|
||||
mysql> FLUSH PRIVILEGES;
|
||||
----
|
||||
|
||||
The Samba AD schema needs to be filled with additional object
|
||||
definitions by running the following commands:
|
||||
|
||||
----
|
||||
openchange_provision
|
||||
openchange_provision --standalone
|
||||
|
||||
NOTE: This operation can take several minutes
|
||||
[+] Step 1: Register Exchange OIDs
|
||||
@@ -410,38 +453,59 @@ NOTE: This operation can take several minutes
|
||||
[+] Step 9: Add Exchange classes to Samba schema
|
||||
[+] Step 10: Add possSuperior attributes to Exchange classes
|
||||
[+] Step 11: Extend existing Samba classes and attributes
|
||||
[+] Step 12: Exchange Samba with Exchange configuration objects
|
||||
[+] Step 12: Generic Exchange configuration objects
|
||||
[+] Step 13: Finalize generic Exchange configuration objects
|
||||
[SUCCESS] Done!
|
||||
[+] Step 1: Exchange Samba registration
|
||||
[SUCCESS] Done!
|
||||
[+] Step 1: Register Exchange Samba as the main server
|
||||
[SUCCESS] Done!
|
||||
----
|
||||
|
||||
You can safely ignore the "`ERROR: no subClassOf 'serviceAdministrationPoint' for 'rRASAdministrationConnectionPoint'`" message when running the `openchange_provision` command.
|
||||
|
||||
Provision the OpenChange database:
|
||||
Create the OpenChange database:
|
||||
|
||||
----
|
||||
openchange_provision --openchangedb
|
||||
openchange_provision --openchangedb --openchangedb-uri 'mysql://openchange-user:openchange$123@localhost/openchange'
|
||||
|
||||
Setting up openchange db
|
||||
[+] Public Folders
|
||||
===================
|
||||
* Public Folder Root 0x0100000000000001
|
||||
* IPM_SUBTREE 0x0200000000000001
|
||||
* NON_IPM_SUBTREE 0x0300000000000001
|
||||
* EFORMS REGISTRY 0x0400000000000001
|
||||
* OFFLINE ADDRESS BOOK 0x0500000000000001
|
||||
* /o=First Organization/cn=addrlists/cn=oabs/cn=Default Offline Address Book 0x0600000000000001
|
||||
* SCHEDULE+ FREE BUSY 0x0700000000000001
|
||||
* EX:/o=First Organization/ou=Exchange Administrative Group (UBUNTU-OC) 0x0800000000000001
|
||||
* Events Root 0x0900000000000001
|
||||
* Public Folder Root : 0x0100000000000001 (72057594037927937)
|
||||
* IPM_SUBTREE : 0x0200000000000001 (144115188075855873)
|
||||
* NON_IPM_SUBTREE : 0x0300000000000001 (216172782113783809)
|
||||
* EFORMS REGISTRY : 0x0400000000000001 (288230376151711745)
|
||||
* OFFLINE ADDRESS BOOK : 0x0500000000000001 (360287970189639681)
|
||||
* /o=First Organization/cn=addrlists/cn=oabs/cn=Default Offline Address Book: 0x0600000000000001 (432345564227567617)
|
||||
* SCHEDULE+ FREE BUSY : 0x0700000000000001 (504403158265495553)
|
||||
* EX:/o=first organization/ou=first administrative group: 0x0800000000000001 (576460752303423489)
|
||||
* Events Root : 0x0900000000000001 (648518346341351425)
|
||||
----
|
||||
|
||||
Finally, modify `/etc/samba/smb.conf` to specify OpenChange connection information
|
||||
for its indexing database. Add the following at the end of the `[global]` section:
|
||||
|
||||
----
|
||||
mapistore:namedproperties = mysql
|
||||
namedproperties:mysql_user = openchange-user
|
||||
namedproperties:mysql_pass = openchange$123
|
||||
namedproperties:mysql_host = localhost
|
||||
namedproperties:mysql_db = openchange
|
||||
|
||||
mapistore:indexing_backend = mysql://openchange-user:openchange$123@localhost/openchange
|
||||
mapiproxy:openchangedb = mysql://openchange-user:openchange$123@localhost/openchange
|
||||
----
|
||||
|
||||
On RHEL, make sure SELinux is disabled:
|
||||
|
||||
setenforce 0
|
||||
|
||||
Next, you can start Samba using the usual command :
|
||||
Next, you can start Samba using the usual command:
|
||||
|
||||
/etc/init.d/samba4 start
|
||||
/etc/init.d/samba start
|
||||
|
||||
On upstart-based distributions, use:
|
||||
|
||||
start samba-ad-dc
|
||||
|
||||
You can also launch the OpenChange web services:
|
||||
|
||||
@@ -503,6 +567,10 @@ On Debian-based distributions, do:
|
||||
|
||||
update-rc.d apache2 defaults && /etc/init.d/apache2 restart
|
||||
|
||||
[NOTE]
|
||||
Debian-based distributions are not supported anymore for
|
||||
OCSManager/rpcproxy. Support will soon resume.
|
||||
|
||||
Name Service Configuration for Web Services
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -540,14 +608,13 @@ samba-tool domain passwordsettings set --complexity=off
|
||||
samba-tool domain passwordsettings set --min-pwd-length=1
|
||||
samba-tool user add <username>
|
||||
samba-tool user setexpiry <username> --noexpiry
|
||||
# create user in openchange+ +openchange_newuser --create <username>
|
||||
# create user in openchange
|
||||
openchange_newuser --create <username>
|
||||
----
|
||||
|
||||
If you don't have a trust between your IMAP server and SOGo, you must at
|
||||
this point set the cleartext password of the newly created user in
|
||||
`/var/lib/samba4/private/mapistore/<username/password` (or
|
||||
`/var/lib/samba/private/mapistore/<username/password` on Debian-based
|
||||
distributions).
|
||||
`/var/lib/samba/private/mapistore/<username/password`.
|
||||
|
||||
This per-user file contains the cleartext password of the user as a
|
||||
UTF-8 string, on a single line. This password will be used to
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||
version="1.0">
|
||||
|
||||
<!-- ********************************************************************
|
||||
|
||||
SOGo Documentation Docbook FO Parameters
|
||||
|
||||
This file is part of the SOGo project.
|
||||
Authors:
|
||||
- Inverse inc. <info@inverse.ca>
|
||||
|
||||
Copyright (C) 2011-2014 Inverse inc.
|
||||
License: GFDL 1.2 or later. http://www.gnu.org/licenses/fdl.html
|
||||
|
||||
******************************************************************** -->
|
||||
|
||||
<!--
|
||||
Global Tasks
|
||||
|
||||
TODO prettier revhistory
|
||||
TODO prettier Table of Contents
|
||||
TODO generate PDF table of contents (like OSX's Preview shows on the right hand side)
|
||||
TODO title 2
|
||||
- align with text?
|
||||
- more above whitespace
|
||||
TODO change the bullet for a prettier one
|
||||
TODO title 3 and 4
|
||||
- align with text?
|
||||
- should be easier to differentiate (check network guide)
|
||||
TODO icon on line wrap in monospace boxes
|
||||
TODO caution, notes, warnings, etc.
|
||||
- box around it
|
||||
- sexy icon
|
||||
TODO -> is converted into an arrow but it's not pretty (is it font or docbook-thingy?)
|
||||
|
||||
-->
|
||||
|
||||
<!--
|
||||
Load default values
|
||||
|
||||
Real upstream schema is at:
|
||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"/>
|
||||
|
||||
but we decided to load all sensible local xsd since it only produce a warning on missing imports.
|
||||
-->
|
||||
<!-- CentOS / RHEL -->
|
||||
<xsl:import href="/usr/share/sgml/docbook/xsl-stylesheets/fo/docbook.xsl"/>
|
||||
<!-- Debian / Ubuntu -->
|
||||
<xsl:import href="/usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl"/>
|
||||
<!-- OSX through mac ports -->
|
||||
<xsl:import href="/opt/local/share/xsl/docbook-xsl/fo/docbook.xsl"/>
|
||||
|
||||
<!-- title page extra styling -->
|
||||
<xsl:import href="titlepage-fo.xsl"/>
|
||||
|
||||
<!-- header / footer extra styling -->
|
||||
<xsl:import href="headerfooter-fo.xsl"/>
|
||||
|
||||
<!-- attaching an image to the verso legalnotice component -->
|
||||
<xsl:template match="legalnotice" mode="book.titlepage.verso.mode">
|
||||
<xsl:apply-templates mode="titlepage.mode"/>
|
||||
<fo:block text-align="right">
|
||||
<fo:external-graphic src="url('images/inverse-logo.jpg')" width="3in" content-width="scale-to-fit"/>
|
||||
</fo:block>
|
||||
</xsl:template>
|
||||
|
||||
<!-- stylesheet options -->
|
||||
<xsl:param name="title.font.family">Lato-Medium</xsl:param>
|
||||
<xsl:param name="chapter.autolabel" select="0"/>
|
||||
<xsl:attribute-set name="component.title.properties">
|
||||
<xsl:attribute name="padding-bottom">0.5em</xsl:attribute>
|
||||
<xsl:attribute name="border-bottom">solid 2px</xsl:attribute>
|
||||
<xsl:attribute name="margin-bottom">1em</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
<xsl:attribute-set name="section.title.level1.properties">
|
||||
<xsl:attribute name="border-bottom">solid 1px</xsl:attribute>
|
||||
<xsl:attribute name="margin-top">1em</xsl:attribute>
|
||||
<xsl:attribute name="margin-bottom">1em</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
<xsl:attribute-set name="section.title.level2.properties">
|
||||
<xsl:attribute name="margin-top">1em</xsl:attribute>
|
||||
<xsl:attribute name="margin-bottom">1em</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
<xsl:attribute-set name="section.title.level3.properties">
|
||||
<xsl:attribute name="margin-top">1em</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
<xsl:attribute-set name="section.title.level4.properties">
|
||||
<xsl:attribute name="margin-top">1em</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
<!-- paragraph spacing -->
|
||||
<xsl:attribute-set name="normal.para.spacing">
|
||||
<xsl:attribute name="space-before.optimum">1.5em</xsl:attribute>
|
||||
<xsl:attribute name="space-before.minimum">1.5em</xsl:attribute>
|
||||
<xsl:attribute name="space-before.maximum">2.2em</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
<!-- default fonts -->
|
||||
<xsl:param name="body.font.family">Lato-Light</xsl:param>
|
||||
<xsl:param name="body.font.master">10</xsl:param>
|
||||
<xsl:param name="monospace.font.family">Incosolata</xsl:param>
|
||||
|
||||
<!-- revision table layout -->
|
||||
<xsl:attribute-set name="revhistory.title.properties">
|
||||
<xsl:attribute name="font-size">12pt</xsl:attribute>
|
||||
<xsl:attribute name="font-weight">bold</xsl:attribute>
|
||||
<xsl:attribute name="text-align">center</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
<xsl:attribute-set name="revhistory.table.properties">
|
||||
<xsl:attribute name="break-before">page</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
<xsl:attribute-set name="revhistory.table.cell.properties">
|
||||
<xsl:attribute name="border-bottom">1px solid</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
<!-- Table Of Contents (TOC) options -->
|
||||
<!-- We only want 2 level of ToC depth -->
|
||||
<xsl:param name="toc.section.depth" select="2"/>
|
||||
|
||||
<!-- titles left margin -->
|
||||
<xsl:attribute-set name="section.title.properties">
|
||||
<xsl:attribute name="start-indent"><xsl:value-of select="$body.start.indent"/></xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
<xsl:attribute-set name="list.item.spacing">
|
||||
<xsl:attribute name="space-before.optimum">0em</xsl:attribute>
|
||||
<xsl:attribute name="space-before.minimum">0em</xsl:attribute>
|
||||
<xsl:attribute name="space-before.maximum">0.2em</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
<!-- lists type -->
|
||||
<xsl:template name="itemizedlist.label.markup">
|
||||
<xsl:param name="itemsymbol" select="'square'"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$itemsymbol='square'"><fo:inline font-family="Lato">∏</fo:inline></xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
<xsl:template name="next.itemsymbol">
|
||||
<xsl:param name="itemsymbol" select="'default'"/>
|
||||
<xsl:choose>
|
||||
<xsl:otherwise>square</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!-- admonition -->
|
||||
<xsl:param name="admon.graphics" select="1"></xsl:param>
|
||||
<xsl:param name="admon.graphics.path">images/</xsl:param>
|
||||
<xsl:param name="admon.graphics.extension">.png</xsl:param>
|
||||
<xsl:attribute-set name="graphical.admonition.properties">
|
||||
<xsl:attribute name="border-top">1px solid</xsl:attribute>
|
||||
<xsl:attribute name="border-bottom">1px solid</xsl:attribute>
|
||||
<xsl:attribute name="padding-top">0.5em</xsl:attribute>
|
||||
<xsl:attribute name="padding-bottom">0.5em</xsl:attribute>
|
||||
<xsl:attribute name="margin-left">2em</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
|
||||
<!-- grey boxes around code (screen, programlisting) -->
|
||||
<xsl:param name="shade.verbatim" select="1"/>
|
||||
<xsl:attribute-set name="shade.verbatim.style">
|
||||
<xsl:attribute name="background-color">#E0E0E0</xsl:attribute>
|
||||
<xsl:attribute name="border">thin #9F9F9F solid</xsl:attribute>
|
||||
<xsl:attribute name="margin">0pt</xsl:attribute>
|
||||
<xsl:attribute name="padding">0.5em</xsl:attribute>
|
||||
<!-- prevent page breaks in screen and programlisting tags -->
|
||||
<xsl:attribute name="keep-together.within-column">always</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
<!-- breaking long lines in code (screen, programlisting) -->
|
||||
<xsl:attribute-set name="monospace.verbatim.properties">
|
||||
<xsl:attribute name="wrap-option">wrap</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
<!-- don't show raw links in [ .. ] after a link -->
|
||||
<xsl:param name="ulink.show" select="0"/>
|
||||
|
||||
<!-- blue underlined hyperlink -->
|
||||
<xsl:attribute-set name="xref.properties">
|
||||
<xsl:attribute name="color">blue</xsl:attribute>
|
||||
<xsl:attribute name="text-decoration">underline</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
<!-- copyright in range instead of seperated years -->
|
||||
<xsl:param name="make.year.ranges" select="1" />
|
||||
|
||||
<!-- variablelist behavior (asciidoc's term:: lists) -->
|
||||
<!-- <xsl:param name="variablelist.term.break.after" select="1" /> -->
|
||||
|
||||
</xsl:stylesheet>
|
||||
<!-- vim: set shiftwidth=2 tabstop=2 expandtab: -->
|
||||
@@ -165,6 +165,13 @@
|
||||
<xsl:attribute name="text-decoration">underline</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
<!-- strong emphasis in bold -->
|
||||
<xsl:template match="emphasis[@role='strong']">
|
||||
<fo:inline font-family="Lato" font-weight="normal">
|
||||
<xsl:apply-templates/>
|
||||
</fo:inline>
|
||||
</xsl:template>
|
||||
|
||||
<!-- copyright in range instead of seperated years -->
|
||||
<xsl:param name="make.year.ranges" select="1" />
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- TODO have the build system take care of this -->
|
||||
<releaseinfo>Version 2.2.9 - September 2014</releaseinfo>
|
||||
<subtitle>for version 2.2.9</subtitle>
|
||||
<date>2014-09-26</date>
|
||||
<releaseinfo>Version 2.2.10 - November 2014</releaseinfo>
|
||||
<subtitle>for version 2.2.10</subtitle>
|
||||
<date>2014-11-21</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.9
|
||||
:release_version: 2.2.10
|
||||
|
||||
// vim: set syntax=asciidoc tabstop=2 shiftwidth=2 expandtab:
|
||||
|
||||
+1
-2
@@ -6,8 +6,7 @@ include ../Version
|
||||
|
||||
ADDITIONAL_OBJCFLAGS += -fPIE
|
||||
ADDITIONAL_INCLUDE_DIRS +=
|
||||
ADDITIONAL_LIB_DIRS += -L../SOPE/GDLContentStore/obj/
|
||||
ADDITIONAL_LDFLAGS += -Wl,--no-as-needed -fPIE -pie
|
||||
ADDITIONAL_LDFLAGS += -Wl,--no-as-needed -fPIE -pie -Wl,--rpath,$(GNUSTEP_SYSTEM_LIBRARIES)/sogo
|
||||
|
||||
SOGOD = sogod
|
||||
TOOL_NAME = $(SOGOD)
|
||||
|
||||
@@ -9,10 +9,9 @@ ADDITIONAL_INCLUDE_DIRS += \
|
||||
-I..
|
||||
|
||||
ADDITIONAL_LIB_DIRS += \
|
||||
-L../SoObjects/SOGo/SOGo.framework \
|
||||
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/
|
||||
|
||||
SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
|
||||
-L../SoObjects/SOGo/SOGo.framework/sogo \
|
||||
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \
|
||||
-L../SOPE/GDLContentStore/$(GNUSTEP_OBJ_DIR)/
|
||||
|
||||
$(SOGOD)_TOOL_LIBS += \
|
||||
-lSOGo \
|
||||
|
||||
@@ -1,3 +1,34 @@
|
||||
2.2.10 (2014-11-21)
|
||||
-------------------
|
||||
|
||||
Enhancements
|
||||
- no longer leaking database passwords in the logs (#2953)
|
||||
- added support for multiple calendars and address books over ActiveSync
|
||||
- updated timezone information (#2968)
|
||||
- updated Brazilian Portuguese, Czech, Dutch, Finnish, French, German, Hungarian, Polish,
|
||||
Russian, Spanish (Argentina), and Spanish (Spain) translations
|
||||
- updated CKEditor to version 4.4.5
|
||||
|
||||
Bug fixes
|
||||
- fixed freebusy lookup with "Show time as busy" (#2930)
|
||||
- don't escape <br>'s in a card's note field
|
||||
- fixed folder's display name when subscribing to a folder
|
||||
- fixed folder's display name when the active user subscribes another user to one of her/his folders
|
||||
- fixed error with new user default sorting value for the mailer module (#2952)
|
||||
- fixed ActiveSync PING command flooding the server (#2940)
|
||||
- fixed many interop issues with Windows Phones over ActiveSync
|
||||
- fixed automatic return receipts crash when not in the recepient list (#2965)
|
||||
- fixed support for Sieve folder encoding parameter (#2622)
|
||||
- fixed rename of subscribed addressbooks
|
||||
- sanitize strings before escaping them when using EAS
|
||||
- fixed handling of event invitations on iOS/EAS with no organizer (#2978)
|
||||
- fixed corrupted png files (#2975)
|
||||
- improved dramatically the BSON decoding speed
|
||||
- added WindowSize support for GCS collections when using EAS
|
||||
- fixed IMAP search with non-ASCII folder names
|
||||
- fixed extraction of email addresses when pasting text with tabs (#2945)
|
||||
- fixed Outlook attachment corruption issues when using AES (#2957)
|
||||
|
||||
2.2.9a (2014-09-29)
|
||||
-------------------
|
||||
|
||||
@@ -11,7 +42,7 @@ New features
|
||||
- support for recurrent tasks (#2160)
|
||||
- support for alarms on recurrent events / tasks
|
||||
|
||||
Enchancements
|
||||
Enhancements
|
||||
- alarms can now be snoozed for 1 day
|
||||
- better iOS/Mac OS X Calendar compability regarding alarms (#1920)
|
||||
- force default classification over CalDAV if none is set (#2326)
|
||||
@@ -36,7 +67,7 @@ New features
|
||||
- new user settings for threads collapsing
|
||||
- IMAP global search support (#2670)
|
||||
|
||||
Enchancements
|
||||
Enhancements
|
||||
- major refactoring of the GCS component saving code (dropped OGoContentStore)
|
||||
- printing calendars in colors is now possible in all views; list, daily, weekly and multicolumns
|
||||
- new option to print calendars events and tasks with a background color or with a border color
|
||||
|
||||
@@ -133,10 +133,11 @@ $(PLREADER_TOOL)_OBJC_FILES += \
|
||||
|
||||
DBMSGREADER_TOOL = dbmsgreader
|
||||
$(DBMSGREADER_TOOL)_OBJC_FILES += \
|
||||
dbmsgreader.m
|
||||
dbmsgreader.m \
|
||||
NSObject+PropertyList.m
|
||||
|
||||
$(DBMSGREADER_TOOL)_LIB_DIRS += \
|
||||
-L../SoObjects/SOGo/SOGo.framework/ -lSOGo \
|
||||
-L../SoObjects/SOGo/SOGo.framework/sogo -lSOGo \
|
||||
-L../SOPE/GDLContentStore/obj/ -lGDLContentStore \
|
||||
-L../SOPE/NGCards/obj/ -lNGCards \
|
||||
-lNGObjWeb
|
||||
@@ -160,12 +161,12 @@ LIBMAPISTORE_LIBS = $(shell pkg-config libmapistore --libs) -lmapiproxy -lWEExte
|
||||
|
||||
$(MAPISTORESOGO)_INSTALL_DIR = $(DESTDIR)/$(SAMBA_LIB_DIR)/mapistore_backends
|
||||
$(MAPISTORESOGO)_LIB_DIRS += \
|
||||
-L../SoObjects/SOGo/SOGo.framework/ -lSOGo -lgnustep-base -lobjc -lNGObjWeb \
|
||||
-L../SoObjects/SOGo/SOGo.framework/sogo/ -lSOGo -lgnustep-base -lobjc -lNGObjWeb \
|
||||
$(LIBMAPI_LIBS) \
|
||||
$(LIBMAPISTORE_LIBS)
|
||||
|
||||
$(SOGOBACKEND)_LIB_DIRS += \
|
||||
-L../SoObjects/SOGo/SOGo.framework/ -lSOGo \
|
||||
-L../SoObjects/SOGo/SOGo.framework/sogo/ -lSOGo \
|
||||
$(LIBMAPI_LIBS) \
|
||||
$(LIBMAPISTORE_LIBS)
|
||||
|
||||
@@ -178,6 +179,8 @@ ADDITIONAL_INCLUDE_DIRS += \
|
||||
-DBACKEND_BUNDLE_NAME="@\"$(BUNDLE_NAME)$(BUNDLE_EXTENSION)\"" \
|
||||
-DSOGO_BUNDLES_DIR="@\"$(BUNDLE_INSTALL_DIR)\""
|
||||
|
||||
ADDITIONAL_LDFLAGS += -Wl,--rpath,$(SOGO_SYSLIBDIR)/sogo
|
||||
|
||||
-include GNUmakefile.preamble
|
||||
include $(GNUSTEP_MAKEFILES)/bundle.make
|
||||
include $(GNUSTEP_MAKEFILES)/library.make
|
||||
|
||||
@@ -1218,7 +1218,9 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
int rc;
|
||||
NSRange range;
|
||||
NSString *stringValue;
|
||||
NSString *trimingString = @"\r\n\n";
|
||||
|
||||
/* FIXME: there is a confusion in NGCards around "comment" and "description" */
|
||||
stringValue = [event comment];
|
||||
@@ -1226,6 +1228,14 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||
&& ![stringValue isEqualToString: @"\r\n"]
|
||||
&& ![stringValue isEqualToString: @"\n"])
|
||||
{
|
||||
/* Avoiding those trail weird characters at event description */
|
||||
range = [stringValue rangeOfString: trimingString
|
||||
options: NSBackwardsSearch];
|
||||
if (range.location > 0)
|
||||
{
|
||||
stringValue = [stringValue substringToIndex: (NSMaxRange(range) -1)];
|
||||
}
|
||||
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
*data = [stringValue asUnicodeInMemCtx: memCtx];
|
||||
}
|
||||
|
||||
@@ -61,10 +61,10 @@
|
||||
}
|
||||
|
||||
+ (struct mapistore_contexts_list *) listAllContextsForUser: (NSString *) userName
|
||||
withTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
withIndexing: (struct indexing_context *) indexing
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName
|
||||
withTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
withIndexing: (struct indexing_context *) indexing
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
+ (enum mapistore_error) createRootFolder: (NSString **) mapistoreUriP
|
||||
withFID: (uint64_t ) fid
|
||||
@@ -75,11 +75,11 @@
|
||||
+ (int) openContext: (MAPIStoreContext **) contextPtr
|
||||
withURI: (const char *) newUri
|
||||
connectionInfo: (struct mapistore_connection_info *) newConnInfo
|
||||
andTDBIndexing: (struct tdb_wrap *) indexingTdb;
|
||||
andTDBIndexing: (struct indexing_context *) indexing;
|
||||
|
||||
- (id) initFromURL: (NSURL *) newUri
|
||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
||||
andTDBIndexing: (struct tdb_wrap *) indexingTdb;
|
||||
andTDBIndexing: (struct indexing_context *) indexing;
|
||||
|
||||
- (NSURL *) url;
|
||||
- (struct mapistore_connection_info *) connectionInfo;
|
||||
|
||||
@@ -100,7 +100,7 @@ static NSMutableDictionary *contextClassMapping;
|
||||
}
|
||||
|
||||
+ (struct mapistore_contexts_list *) listAllContextsForUser: (NSString *) userName
|
||||
withTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
withIndexing: (struct indexing_context *) indexing
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
struct mapistore_contexts_list *list, *current;
|
||||
@@ -112,7 +112,7 @@ static NSMutableDictionary *contextClassMapping;
|
||||
list = NULL;
|
||||
|
||||
userContext = [MAPIStoreUserContext userContextWithUsername: userName
|
||||
andTDBIndexing: indexingTdb];
|
||||
andTDBIndexing: indexing];
|
||||
[userContext activateWithUser: [userContext sogoUser]];
|
||||
|
||||
classes = GSObjCAllSubclassesOfClass (self);
|
||||
@@ -121,7 +121,7 @@ static NSMutableDictionary *contextClassMapping;
|
||||
{
|
||||
currentClass = [classes objectAtIndex: count];
|
||||
current = [currentClass listContextsForUser: userName
|
||||
withTDBIndexing: indexingTdb
|
||||
withIndexing: indexing
|
||||
inMemCtx: memCtx];
|
||||
if (current)
|
||||
DLIST_CONCATENATE(list, current, void);
|
||||
@@ -131,7 +131,7 @@ static NSMutableDictionary *contextClassMapping;
|
||||
}
|
||||
|
||||
+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName
|
||||
withTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
withIndexing: (struct indexing_context *) indexing
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
return NULL;
|
||||
@@ -216,7 +216,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||
+ (int) openContext: (MAPIStoreContext **) contextPtr
|
||||
withURI: (const char *) newUri
|
||||
connectionInfo: (struct mapistore_connection_info *) newConnInfo
|
||||
andTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
andTDBIndexing: (struct indexing_context *) indexing
|
||||
{
|
||||
MAPIStoreContext *context;
|
||||
Class contextClass;
|
||||
@@ -239,7 +239,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||
{
|
||||
context = [[contextClass alloc] initFromURL: baseURL
|
||||
withConnectionInfo: newConnInfo
|
||||
andTDBIndexing: indexingTdb];
|
||||
andTDBIndexing: indexing];
|
||||
if (context)
|
||||
{
|
||||
[context autorelease];
|
||||
@@ -272,7 +272,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||
|
||||
- (id) initFromURL: (NSURL *) newUrl
|
||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
||||
andTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
andTDBIndexing: (struct indexing_context *) indexing
|
||||
{
|
||||
NSString *username;
|
||||
|
||||
@@ -291,7 +291,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||
|
||||
ASSIGN (userContext,
|
||||
[MAPIStoreUserContext userContextWithUsername: username
|
||||
andTDBIndexing: indexingTdb]);
|
||||
andTDBIndexing: indexing]);
|
||||
|
||||
#if 0
|
||||
mapistore_mgmt_backend_register_user (newConnInfo,
|
||||
@@ -374,17 +374,14 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||
{
|
||||
if ([objectURL hasPrefix: url])
|
||||
{
|
||||
*path = [[objectURL substringFromIndex: 7]
|
||||
asUnicodeInMemCtx: memCtx];
|
||||
[self logWithFormat: @"found path '%s' for fmid %.16x",
|
||||
*path, fmid];
|
||||
*path = [[objectURL substringFromIndex: 7] asUnicodeInMemCtx: memCtx];
|
||||
[self logWithFormat: @"found path '%s' for fmid 0x%.16"PRIx64"", *path, fmid];
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
[self logWithFormat: @"context (%@, %@) does not contain"
|
||||
@" found fmid: 0x%.16x",
|
||||
objectURL, url, fmid];
|
||||
[self logWithFormat: @"context (%@, %@) does not contain "
|
||||
@"found fmid: 0x%.16"PRIx64"", objectURL, url, fmid];
|
||||
*path = NULL;
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
@@ -534,7 +531,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||
{
|
||||
//[self warnWithFormat: @"no id exist yet for '%@', requesting one...",
|
||||
// childURL];
|
||||
openchangedb_get_new_folderID (connInfo->oc_ctx, &mappingId);
|
||||
mapistore_indexing_get_new_folderID (connInfo->mstore_ctx, &mappingId);
|
||||
[mapping registerURL: childURL withID: mappingId];
|
||||
contextId = 0;
|
||||
|
||||
@@ -597,9 +594,9 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||
memCtx = talloc_zero(NULL, TALLOC_CTX);
|
||||
newFMIDs = [NSMutableArray arrayWithCapacity: max];
|
||||
|
||||
if (openchangedb_get_new_folderIDs (connInfo->oc_ctx,
|
||||
memCtx, max, &numbers)
|
||||
!= MAPI_E_SUCCESS || numbers->cValues != max)
|
||||
if (mapistore_indexing_get_new_folderIDs (connInfo->mstore_ctx,
|
||||
memCtx, max, &numbers)
|
||||
!= MAPISTORE_SUCCESS || numbers->cValues != max)
|
||||
abort ();
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
}
|
||||
|
||||
+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName
|
||||
withTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
withIndexing: (struct indexing_context *) indexing
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
struct mapistore_contexts_list *firstContext = NULL, *context;
|
||||
@@ -72,7 +72,7 @@
|
||||
inContainer: nil];
|
||||
[root setOwner: userName];
|
||||
userContext = [MAPIStoreUserContext userContextWithUsername: userName
|
||||
andTDBIndexing: indexingTdb];
|
||||
andTDBIndexing: indexing];
|
||||
[userContext ensureFolderTableExists];
|
||||
[root setTableUrl: [userContext folderTableURL]];
|
||||
names = [root toManyRelationshipKeys];
|
||||
|
||||
@@ -433,10 +433,16 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
return rc;
|
||||
}
|
||||
|
||||
- (int) deleteFolder
|
||||
- (void) deleteFolderImpl
|
||||
{
|
||||
// TODO: raise exception in case underlying delete fails?
|
||||
// [propsMessage delete];
|
||||
[dbFolder delete];
|
||||
}
|
||||
|
||||
- (int) deleteFolder
|
||||
{
|
||||
[self deleteFolderImpl];
|
||||
|
||||
[self cleanupCaches];
|
||||
|
||||
@@ -890,7 +896,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||
{
|
||||
fmid = [mapping idFromURL: [self url]];
|
||||
[mapping unregisterURLWithID: fmid];
|
||||
[self deleteFolder];
|
||||
[self deleteFolderImpl];
|
||||
[mapping registerURL: [newFolder url]
|
||||
withID: fmid];
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
}
|
||||
|
||||
+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName
|
||||
withTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
withIndexing: (struct indexing_context *) indexing
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
struct mapistore_contexts_list *firstContext = NULL, *context;
|
||||
@@ -79,7 +79,7 @@
|
||||
if (moduleName)
|
||||
{
|
||||
userContext = [MAPIStoreUserContext userContextWithUsername: userName
|
||||
andTDBIndexing: indexingTdb];
|
||||
andTDBIndexing: indexing];
|
||||
parentFolder = [[userContext rootFolders] objectForKey: moduleName];
|
||||
baseUrl = [NSString stringWithFormat: @"sogo://%@@%@/",
|
||||
userName, moduleName];
|
||||
|
||||
@@ -83,7 +83,7 @@ MakeDisplayFolderName (NSString *folderName)
|
||||
}
|
||||
|
||||
+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName
|
||||
withTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
withIndexing: (struct indexing_context *) indexing
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
struct mapistore_contexts_list *firstContext = NULL, *context;
|
||||
@@ -100,7 +100,7 @@ MakeDisplayFolderName (NSString *folderName)
|
||||
WOContext *woContext;
|
||||
|
||||
userContext = [MAPIStoreUserContext userContextWithUsername: userName
|
||||
andTDBIndexing: indexingTdb];
|
||||
andTDBIndexing: indexing];
|
||||
accountFolder = [[userContext rootFolders] objectForKey: @"mail"];
|
||||
woContext = [userContext woContext];
|
||||
|
||||
@@ -245,7 +245,7 @@ MakeDisplayFolderName (NSString *folderName)
|
||||
}
|
||||
|
||||
+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName
|
||||
withTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
withIndexing: (struct indexing_context *) indexing
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
struct mapistore_contexts_list *context;
|
||||
@@ -256,7 +256,7 @@ MakeDisplayFolderName (NSString *folderName)
|
||||
WOContext *woContext;
|
||||
|
||||
userContext = [MAPIStoreUserContext userContextWithUsername: userName
|
||||
andTDBIndexing: indexingTdb];
|
||||
andTDBIndexing: indexing];
|
||||
accountFolder = [[userContext rootFolders] objectForKey: @"mail"];
|
||||
woContext = [userContext woContext];
|
||||
|
||||
|
||||
@@ -367,7 +367,7 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
||||
msgData->recipients_count = max;
|
||||
msgData->recipients = talloc_array (msgData, struct mapistore_message_recipient, max);
|
||||
current = 0;
|
||||
for (type = 0; type < 4; type++)
|
||||
for (type = MAPI_ORIG; type <= MAPI_BCC; type++)
|
||||
{
|
||||
recipients = [allRecipients objectForKey: recTypes[type]];
|
||||
recipientsMax = [recipients count];
|
||||
@@ -541,7 +541,7 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
|
||||
NSArray *list;
|
||||
NSCalendarDate *date;
|
||||
NSDictionary *recipients;
|
||||
NSUInteger type, bccLimit;
|
||||
enum ulRecipClass type, bccLimit;
|
||||
SOGoUser *activeUser;
|
||||
NSNumber *priority;
|
||||
|
||||
@@ -561,8 +561,8 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers,
|
||||
bccLimit = MAPI_BCC;
|
||||
else
|
||||
bccLimit = MAPI_CC;
|
||||
bccLimit++;
|
||||
for (type = MAPI_TO; type < bccLimit; type++)
|
||||
|
||||
for (type = MAPI_TO; type <= bccLimit; type++)
|
||||
{
|
||||
recId = recTypes[type];
|
||||
list = MakeRecipientsList ([recipients objectForKey: recId]);
|
||||
@@ -865,7 +865,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
|
||||
NSMutableArray *recipientEmails;
|
||||
NSArray *list;
|
||||
NSString *recId, *from, *msgClass;
|
||||
NSUInteger count;
|
||||
enum ulRecipClass type;
|
||||
SOGoUser *activeUser;
|
||||
SOGoDomainDefaults *dd;
|
||||
NSException *error;
|
||||
@@ -881,9 +881,9 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
|
||||
|
||||
recipientEmails = [NSMutableArray arrayWithCapacity: 32];
|
||||
recipients = [properties objectForKey: @"recipients"];
|
||||
for (count = 0; count < 3; count++)
|
||||
for (type = MAPI_ORIG; type <= MAPI_BCC; type++)
|
||||
{
|
||||
recId = recTypes[count];
|
||||
recId = recTypes[type];
|
||||
list = [recipients objectForKey: recId];
|
||||
[recipientEmails
|
||||
addObjectsFromArray: [list objectsForKey: @"email"
|
||||
|
||||
@@ -32,17 +32,15 @@
|
||||
{
|
||||
void *memCtx;
|
||||
NSString *username;
|
||||
struct tdb_wrap *indexing;
|
||||
NSMutableDictionary *mapping; /* FID/MID -> url */
|
||||
NSMutableDictionary *reverseMapping; /* url -> FID/MID */
|
||||
struct indexing_context *indexing;
|
||||
NSUInteger useCount;
|
||||
}
|
||||
|
||||
+ (id) mappingForUsername: (NSString *) username
|
||||
withIndexing: (struct tdb_wrap *) indexing;
|
||||
withIndexing: (struct indexing_context *) indexing;
|
||||
|
||||
- (id) initForUsername: (NSString *) username
|
||||
withIndexing: (struct tdb_wrap *) indexing;
|
||||
withIndexing: (struct indexing_context *) indexing;
|
||||
|
||||
|
||||
- (void) increaseUseCount;
|
||||
|
||||
+67
-172
@@ -33,16 +33,15 @@
|
||||
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
|
||||
#undef DEBUG
|
||||
#include <mapistore/mapistore.h>
|
||||
#include <mapistore/mapistore_errors.h>
|
||||
|
||||
#import "MAPIStoreTypes.h"
|
||||
|
||||
#import "MAPIStoreMapping.h"
|
||||
|
||||
#include <talloc.h>
|
||||
#include <tdb.h>
|
||||
|
||||
struct tdb_wrap {
|
||||
struct tdb_context *tdb;
|
||||
};
|
||||
|
||||
static NSMutableDictionary *mappingRegistry = nil;
|
||||
|
||||
@@ -59,51 +58,9 @@ MAPIStoreMappingKeyFromId (uint64_t idNbr)
|
||||
return [NSString stringWithUnsignedLongLong: idNbr];
|
||||
}
|
||||
|
||||
static int
|
||||
MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
||||
void *data)
|
||||
{
|
||||
NSMutableDictionary *mapping;
|
||||
id idKey;
|
||||
NSString *uri;
|
||||
char *idStr, *uriStr;
|
||||
uint64_t idNbr;
|
||||
|
||||
// get the key
|
||||
// key examples : key(18) = "0x6900000000000001"
|
||||
// key(31) = "SOFT_DELETED:0xb100020000000001"
|
||||
//
|
||||
idStr = (char *) data1.dptr;
|
||||
idKey = nil;
|
||||
|
||||
if (strncmp(idStr, "SOFT_DELETED:", 13) != 0)
|
||||
{
|
||||
// It's very important here to use strtoull and NOT strtoll as
|
||||
// the latter will overflow a long long with typical key values.
|
||||
idNbr = strtoull(idStr, NULL, 0);
|
||||
// idKey = [NSNumber numberWithUnsignedLongLong: idNbr];
|
||||
idKey = MAPIStoreMappingKeyFromId(idNbr);
|
||||
}
|
||||
|
||||
// get the value and null-terminate it
|
||||
uriStr = (char *)malloc(sizeof(char *) * data2.dsize+1);
|
||||
memset(uriStr, 0, data2.dsize+1);
|
||||
memcpy(uriStr, (const char *) data2.dptr, data2.dsize);
|
||||
uri = [NSString stringWithUTF8String: uriStr];
|
||||
free (uriStr);
|
||||
|
||||
mapping = data;
|
||||
|
||||
if (uri && idKey)
|
||||
{
|
||||
[mapping setObject: uri forKey: idKey];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ (id) mappingForUsername: (NSString *) username
|
||||
withIndexing: (struct tdb_wrap *) indexing
|
||||
withIndexing: (struct indexing_context *) indexing
|
||||
{
|
||||
id mapping;
|
||||
|
||||
@@ -123,8 +80,6 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
||||
if ((self = [super init]))
|
||||
{
|
||||
memCtx = talloc_zero (NULL, TALLOC_CTX);
|
||||
mapping = [NSMutableDictionary new];
|
||||
reverseMapping = [NSMutableDictionary new];
|
||||
indexing = NULL;
|
||||
useCount = 0;
|
||||
}
|
||||
@@ -153,29 +108,12 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
||||
}
|
||||
|
||||
- (id) initForUsername: (NSString *) newUsername
|
||||
withIndexing: (struct tdb_wrap *) newIndexing
|
||||
withIndexing: (struct indexing_context *) newIndexing
|
||||
{
|
||||
NSString *idNbr, *uri;
|
||||
NSArray *keys;
|
||||
NSUInteger count, max;
|
||||
|
||||
if ((self = [self init]))
|
||||
{
|
||||
ASSIGN (username, newUsername);
|
||||
indexing = newIndexing;
|
||||
(void) talloc_reference (memCtx, newIndexing);
|
||||
tdb_traverse_read (indexing->tdb, MAPIStoreMappingTDBTraverse, mapping);
|
||||
keys = [mapping allKeys];
|
||||
max = [keys count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
idNbr = [keys objectAtIndex: count];
|
||||
uri = [mapping objectForKey: idNbr];
|
||||
//[self logWithFormat: @"preregistered id '%@' for url '%@'", idNbr, uri];
|
||||
[reverseMapping setObject: idNbr forKey: uri];
|
||||
}
|
||||
|
||||
//[self logWithFormat: @"Complete mapping: %@ \nComplete reverse mapping: %@", mapping, reverseMapping];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -184,83 +122,72 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
||||
- (void) dealloc
|
||||
{
|
||||
[username release];
|
||||
[mapping release];
|
||||
[reverseMapping release];
|
||||
talloc_free (memCtx);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *) urlFromID: (uint64_t) idNbr
|
||||
{
|
||||
return [mapping objectForKey: MAPIStoreMappingKeyFromId (idNbr)];
|
||||
char* url = NULL;
|
||||
enum mapistore_error ret;
|
||||
bool soft_delete = false;
|
||||
|
||||
ret = indexing->get_uri(indexing, [username UTF8String],
|
||||
memCtx, idNbr, &url, &soft_delete);
|
||||
if (ret != MAPISTORE_SUCCESS)
|
||||
return NULL;
|
||||
NSString *res = [[[NSString alloc] initWithUTF8String:url] autorelease];
|
||||
talloc_free(url);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
- (uint64_t) idFromURL: (NSString *) url
|
||||
{
|
||||
id key;
|
||||
enum mapistore_error ret;
|
||||
uint64_t idNbr;
|
||||
bool softDeleted;
|
||||
|
||||
key = [reverseMapping objectForKey: url];
|
||||
if (key)
|
||||
idNbr = [key unsignedLongLongValue];
|
||||
ret = indexing->get_fmid(indexing, [username UTF8String], [url UTF8String],
|
||||
false, &idNbr, &softDeleted);
|
||||
|
||||
if (ret == MAPISTORE_SUCCESS && !softDeleted)
|
||||
return idNbr;
|
||||
else
|
||||
idNbr = NSNotFound;
|
||||
|
||||
return idNbr;
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
- (void) _updateFolderWithURL: (NSString *) oldURL
|
||||
withURL: (NSString *) urlString
|
||||
{
|
||||
NSArray *allKeys;
|
||||
NSUInteger count, max;
|
||||
NSString *currentKey, *newKey;
|
||||
id idKey;
|
||||
TDB_DATA key, dbuf;
|
||||
const char *searchURL;
|
||||
uint64_t idNbr;
|
||||
bool softDeleted;
|
||||
NSString *current;
|
||||
NSString *newURL;
|
||||
|
||||
[oldURL retain];
|
||||
if ([oldURL isEqualToString: urlString]) return;
|
||||
|
||||
allKeys = [reverseMapping allKeys];
|
||||
max = [allKeys count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
currentKey = [allKeys objectAtIndex: count];
|
||||
if ([currentKey hasPrefix: oldURL])
|
||||
{
|
||||
newKey = [currentKey stringByReplacingPrefix: oldURL
|
||||
withPrefix: urlString];
|
||||
searchURL = [[oldURL stringByAppendingString:@"*"] UTF8String];
|
||||
|
||||
idKey = [reverseMapping objectForKey: currentKey];
|
||||
[mapping setObject: newKey forKey: idKey];
|
||||
[reverseMapping setObject: idKey forKey: newKey];
|
||||
[reverseMapping removeObjectForKey: currentKey];
|
||||
while (indexing->get_fmid(indexing, [username UTF8String],
|
||||
searchURL,true, &idNbr, &softDeleted) == MAPISTORE_SUCCESS)
|
||||
{
|
||||
// Ignore deleted
|
||||
if (softDeleted) continue;
|
||||
|
||||
/* update the record in the indexing database */
|
||||
key.dptr = (unsigned char *) talloc_asprintf (NULL, "0x%.16"PRIx64,
|
||||
(uint64_t) [idKey unsignedLongLongValue]);
|
||||
key.dsize = strlen ((const char *) key.dptr);
|
||||
|
||||
dbuf.dptr = (unsigned char *) talloc_strdup (NULL,
|
||||
[newKey UTF8String]);
|
||||
dbuf.dsize = strlen ((const char *) dbuf.dptr);
|
||||
tdb_store (indexing->tdb, key, dbuf, TDB_MODIFY);
|
||||
talloc_free (key.dptr);
|
||||
talloc_free (dbuf.dptr);
|
||||
}
|
||||
}
|
||||
|
||||
[oldURL release];
|
||||
current = [self urlFromID:idNbr];
|
||||
newURL = [current stringByReplacingPrefix: oldURL withPrefix: urlString];
|
||||
indexing->update_fmid(indexing, [username UTF8String], idNbr, [newURL UTF8String]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) updateID: (uint64_t) idNbr
|
||||
withURL: (NSString *) urlString
|
||||
{
|
||||
NSString *oldURL;
|
||||
id idKey;
|
||||
TDB_DATA key, dbuf;
|
||||
|
||||
idKey = MAPIStoreMappingKeyFromId (idNbr);
|
||||
oldURL = [mapping objectForKey: idKey];
|
||||
oldURL = [self urlFromID: idNbr];
|
||||
if (oldURL)
|
||||
{
|
||||
if ([oldURL hasSuffix: @"/"]) /* is container ? */
|
||||
@@ -268,28 +195,16 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
||||
if (![urlString hasSuffix: @"/"])
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"a container url must have an ending '/'"];
|
||||
tdb_transaction_start (indexing->tdb);
|
||||
[self _updateFolderWithURL: oldURL withURL: urlString];
|
||||
tdb_transaction_commit (indexing->tdb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ([urlString hasSuffix: @"/"])
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"a leaf url must not have an ending '/'"];
|
||||
[mapping setObject: urlString forKey: idKey];
|
||||
[reverseMapping setObject: idKey forKey: urlString];
|
||||
[reverseMapping removeObjectForKey: oldURL];
|
||||
|
||||
/* update the record in the indexing database */
|
||||
key.dptr = (unsigned char *) talloc_asprintf(NULL, "0x%.16"PRIx64, idNbr);
|
||||
key.dsize = strlen((const char *) key.dptr);
|
||||
|
||||
dbuf.dptr = (unsigned char *) talloc_strdup (NULL, [urlString UTF8String]);
|
||||
dbuf.dsize = strlen((const char *) dbuf.dptr);
|
||||
tdb_store (indexing->tdb, key, dbuf, TDB_MODIFY);
|
||||
talloc_free (key.dptr);
|
||||
talloc_free (dbuf.dptr);
|
||||
indexing->update_fmid(indexing, [username UTF8String],
|
||||
idNbr, [urlString UTF8String]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,37 +212,37 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
||||
- (BOOL) registerURL: (NSString *) urlString
|
||||
withID: (uint64_t) idNbr
|
||||
{
|
||||
id idKey;
|
||||
BOOL rc;
|
||||
TDB_DATA key, dbuf;
|
||||
NSString *oldURL;
|
||||
uint64_t oldIdNbr;
|
||||
bool rc;
|
||||
|
||||
idKey = MAPIStoreMappingKeyFromId (idNbr);
|
||||
if ([mapping objectForKey: idKey]
|
||||
|| [reverseMapping objectForKey: urlString])
|
||||
oldURL = [self urlFromID: idNbr];
|
||||
if (oldURL != NULL)
|
||||
{
|
||||
[self errorWithFormat:
|
||||
@"attempt to double register an entry ('%@', %lld,"
|
||||
@" 0x%.16"PRIx64")",
|
||||
urlString, idNbr, idNbr];
|
||||
rc = NO;
|
||||
@"url with idNbr already registered: (oldUrl='%@', newUrl='%@', id=x%.16"PRIx64")",
|
||||
oldURL, urlString, idNbr];
|
||||
return NO;
|
||||
}
|
||||
|
||||
oldIdNbr = [self idFromURL: urlString];
|
||||
if (oldIdNbr != NSNotFound)
|
||||
{
|
||||
[self errorWithFormat:
|
||||
@"attempt to double register an entry with idNbr ('%@', %lld,"
|
||||
@" 0x%.16"PRIx64", oldid=0x%.16"PRIx64")",
|
||||
urlString, idNbr, idNbr, oldIdNbr];
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
[mapping setObject: urlString forKey: idKey];
|
||||
[reverseMapping setObject: idKey forKey: urlString];
|
||||
rc = YES;
|
||||
// [self logWithFormat: @"registered url '%@' with id %lld (0x%.16"PRIx64")",
|
||||
// urlString, idNbr, idNbr];
|
||||
|
||||
/* Add the record given its fid and mapistore_uri */
|
||||
key.dptr = (unsigned char *) talloc_asprintf(NULL, "0x%.16"PRIx64, idNbr);
|
||||
key.dsize = strlen((const char *) key.dptr);
|
||||
|
||||
dbuf.dptr = (unsigned char *) talloc_strdup(NULL, [urlString UTF8String]);
|
||||
dbuf.dsize = strlen((const char *) dbuf.dptr);
|
||||
tdb_store (indexing->tdb, key, dbuf, TDB_INSERT);
|
||||
talloc_free (key.dptr);
|
||||
talloc_free (dbuf.dptr);
|
||||
indexing->add_fmid(indexing, [username UTF8String],
|
||||
idNbr, [urlString UTF8String]);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -341,7 +256,6 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
||||
max = [urlStrings count];
|
||||
if (max == [idNbrs count])
|
||||
{
|
||||
tdb_transaction_start (indexing->tdb);
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
newID = [[idNbrs objectAtIndex: count]
|
||||
@@ -349,7 +263,6 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
||||
[self registerURL: [urlStrings objectAtIndex: count]
|
||||
withID: newID];
|
||||
}
|
||||
tdb_transaction_commit (indexing->tdb);
|
||||
}
|
||||
else
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
@@ -358,26 +271,8 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
||||
|
||||
- (void) unregisterURLWithID: (uint64_t) idNbr
|
||||
{
|
||||
NSString *urlString;
|
||||
id idKey;
|
||||
TDB_DATA key;
|
||||
|
||||
idKey = MAPIStoreMappingKeyFromId (idNbr);
|
||||
urlString = [mapping objectForKey: idKey];
|
||||
if (urlString)
|
||||
{
|
||||
// [self logWithFormat: @"unregistering url '%@' with id %lld (0x%.16"PRIx64")",
|
||||
// urlString, idNbr, idNbr];
|
||||
[reverseMapping removeObjectForKey: urlString];
|
||||
[mapping removeObjectForKey: idKey];
|
||||
|
||||
/* We hard-delete the entry from the indexing database */
|
||||
key.dptr = (unsigned char *) talloc_asprintf(NULL, "0x%.16"PRIx64, idNbr);
|
||||
key.dsize = strlen((const char *) key.dptr);
|
||||
|
||||
tdb_delete(indexing->tdb, key);
|
||||
talloc_free(key.dptr);
|
||||
}
|
||||
indexing->del_fmid(indexing, [username UTF8String],
|
||||
idNbr, MAPISTORE_PERMANENT_DELETE);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
}
|
||||
|
||||
+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName
|
||||
withTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
withIndexing: (struct indexing_context *) indexing
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
struct mapistore_contexts_list *context;
|
||||
|
||||
+302
-92
@@ -49,9 +49,32 @@
|
||||
|
||||
#include <mapistore/mapistore.h>
|
||||
#include <mapistore/mapistore_errors.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
static Class MAPIStoreContextK = Nil;
|
||||
static BOOL leakDebugging = NO;
|
||||
static BOOL initialization_done = NO;
|
||||
|
||||
#define NS_CURRENT_THREAD_REGISTER() \
|
||||
BOOL __nsrct_thread_registered = GSRegisterCurrentThread(); \
|
||||
if (!initialization_done) { \
|
||||
DEBUG(5, ("[SOGo: %s:%d] You should call sogo_backend_init() first. Current thread: %p, pid: %d\n", \
|
||||
__FUNCTION__, __LINE__, GSCurrentThread(), getpid())); \
|
||||
}
|
||||
#define NS_CURRENT_THREAD_TRY_UNREGISTER() \
|
||||
if (__nsrct_thread_registered) { \
|
||||
GSUnregisterCurrentThread(); \
|
||||
}
|
||||
|
||||
#define TRYCATCH_START @try {
|
||||
#define TRYCATCH_END(pool) \
|
||||
} @catch (NSException * e) { \
|
||||
enum mapistore_error ret = sogo_backend_handle_objc_exception(e, __PRETTY_FUNCTION__, __LINE__); \
|
||||
[pool release]; \
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER(); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
|
||||
static enum mapistore_error
|
||||
sogo_backend_unexpected_error()
|
||||
@@ -61,6 +84,35 @@ sogo_backend_unexpected_error()
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
static enum mapistore_error
|
||||
sogo_backend_handle_objc_exception(NSException *e, const char *fn_name, const int line_no)
|
||||
{
|
||||
NSString *callStackSymbols = nil;
|
||||
if ([e respondsToSelector:@selector(callStackSymbols)])
|
||||
{
|
||||
callStackSymbols = [[e callStackSymbols] componentsJoinedByString:@"\n\t"];
|
||||
}
|
||||
NSLog(@"[SOGo: %s:%d] - EXCEPTION: %@, reason: %@, backtrace: \n\t%@\n",
|
||||
fn_name, line_no, [e name], [e reason], callStackSymbols);
|
||||
|
||||
// Another point of view on the stack trace
|
||||
{
|
||||
void *frames[128];
|
||||
int i, len = backtrace(frames, 128);
|
||||
char **symbols = backtrace_symbols(frames, len);
|
||||
NSLog(@"Backtrace using execinfo.h:\n");
|
||||
for (i = 0; i < len; ++i)
|
||||
NSLog(@"\t%s", symbols[i]);
|
||||
free(symbols);
|
||||
}
|
||||
|
||||
if ([[e name] isEqual:@"NotImplementedException"])
|
||||
{
|
||||
return MAPISTORE_ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return MAPISTORE_ERROR;
|
||||
}
|
||||
|
||||
static void
|
||||
sogo_backend_atexit (void)
|
||||
{
|
||||
@@ -73,6 +125,7 @@ sogo_backend_atexit (void)
|
||||
GSUnregisterCurrentThread ();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\details Initialize sogo mapistore backend
|
||||
|
||||
@@ -88,7 +141,13 @@ sogo_backend_init (void)
|
||||
SoProductRegistry *registry;
|
||||
char *argv[] = { SAMBA_PREFIX "/sbin/samba", NULL };
|
||||
|
||||
GSRegisterCurrentThread ();
|
||||
GSRegisterCurrentThread();
|
||||
|
||||
if (initialization_done) {
|
||||
DEBUG(0, ("SOGo backend already initialized.\n"));
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
/* Here we work around a bug in GNUstep which decodes XML user
|
||||
@@ -130,6 +189,9 @@ sogo_backend_init (void)
|
||||
|
||||
[pool release];
|
||||
|
||||
DEBUG(0, ("[SOGo: %s:%d] backend init SUCCESS. Current thread: %p, pid: %d\n", __FUNCTION__, __LINE__, GSCurrentThread(), getpid()));
|
||||
initialization_done = YES;
|
||||
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -144,7 +206,7 @@ sogo_backend_init (void)
|
||||
static enum mapistore_error
|
||||
sogo_backend_create_context(TALLOC_CTX *mem_ctx,
|
||||
struct mapistore_connection_info *conn_info,
|
||||
struct tdb_wrap *indexingTdb,
|
||||
struct indexing_context *indexing,
|
||||
const char *uri, void **context_object)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
@@ -153,23 +215,25 @@ sogo_backend_create_context(TALLOC_CTX *mem_ctx,
|
||||
|
||||
DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
|
||||
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
if (MAPIStoreContextK)
|
||||
{
|
||||
TRYCATCH_START
|
||||
rc = [MAPIStoreContextK openContext: &context
|
||||
withURI: uri
|
||||
connectionInfo: conn_info
|
||||
andTDBIndexing: indexingTdb];
|
||||
andTDBIndexing: indexing];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*context_object = [context tallocWrapper: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
}
|
||||
else
|
||||
rc = MAPISTORE_ERROR;
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -178,7 +242,7 @@ static enum mapistore_error
|
||||
sogo_backend_create_root_folder (const char *username,
|
||||
enum mapistore_context_role role,
|
||||
uint64_t fid, const char *name,
|
||||
// struct tdb_wrap *indexingTdb,
|
||||
// struct indexing_context *indexing,
|
||||
TALLOC_CTX *mem_ctx, char **mapistore_urip)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
@@ -188,11 +252,12 @@ sogo_backend_create_root_folder (const char *username,
|
||||
|
||||
DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
|
||||
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
if (MAPIStoreContextK)
|
||||
{
|
||||
TRYCATCH_START
|
||||
userName = [NSString stringWithUTF8String: username];
|
||||
folderName = [NSString stringWithUTF8String: name];
|
||||
rc = [MAPIStoreContextK createRootFolder: &mapistoreUri
|
||||
@@ -202,18 +267,19 @@ sogo_backend_create_root_folder (const char *username,
|
||||
withRole: role];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*mapistore_urip = [mapistoreUri asUnicodeInMemCtx: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
}
|
||||
else
|
||||
rc = MAPISTORE_ERROR;
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static enum mapistore_error
|
||||
sogo_backend_list_contexts(const char *username, struct tdb_wrap *indexingTdb,
|
||||
sogo_backend_list_contexts(const char *username, struct indexing_context *indexing,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct mapistore_contexts_list **contexts_listp)
|
||||
{
|
||||
@@ -223,22 +289,24 @@ sogo_backend_list_contexts(const char *username, struct tdb_wrap *indexingTdb,
|
||||
|
||||
DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
|
||||
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
if (MAPIStoreContextK)
|
||||
{
|
||||
TRYCATCH_START
|
||||
userName = [NSString stringWithUTF8String: username];
|
||||
*contexts_listp = [MAPIStoreContextK listAllContextsForUser: userName
|
||||
withTDBIndexing: indexingTdb
|
||||
withIndexing: indexing
|
||||
inMemCtx: mem_ctx];
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
TRYCATCH_END(pool)
|
||||
}
|
||||
else
|
||||
rc = MAPISTORE_ERROR;
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -273,11 +341,15 @@ sogo_context_get_path(void *backend_object, TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
wrapper = backend_object;
|
||||
context = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [context getPath: path ofFMID: fmid inMemCtx: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -303,13 +375,17 @@ sogo_context_get_root_folder(void *backend_object, TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
wrapper = backend_object;
|
||||
context = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [context getRootFolder: &folder withFID: fid];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*folder_object = [folder tallocWrapper: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -342,14 +418,18 @@ sogo_folder_open_folder(void *folder_object, TALLOC_CTX *mem_ctx, uint64_t fid,
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder openFolder: &childFolder withFID: fid];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*childfolder_object = [childFolder tallocWrapper: mem_ctx];
|
||||
// [context tearDownRequest];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -382,13 +462,17 @@ sogo_folder_create_folder(void *folder_object, TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder createFolder: &childFolder withRow: aRow andFID: fid];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*childfolder_object = [childFolder tallocWrapper: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -421,11 +505,15 @@ sogo_folder_delete(void *folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder deleteFolder];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -449,11 +537,15 @@ sogo_folder_get_child_count(void *folder_object, enum mapistore_table_type table
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder getChildCount: child_count ofTableType: table_type];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -481,16 +573,20 @@ sogo_folder_open_message(void *folder_object,
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder openMessage: &message
|
||||
withMID: mid
|
||||
forWriting: write_access
|
||||
inMemCtx: mem_ctx];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*message_object = [message tallocWrapper: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -519,15 +615,19 @@ sogo_folder_create_message(void *folder_object,
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder createMessage: &message
|
||||
withMID: mid
|
||||
isAssociated: associated];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*message_object = [message tallocWrapper: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -551,11 +651,15 @@ sogo_folder_delete_message(void *folder_object, uint64_t mid, uint8_t flags)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder deleteMessageWithMID: mid andFlags: flags];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -589,8 +693,10 @@ sogo_folder_move_copy_messages(void *folder_object,
|
||||
wrapper = source_folder_object;
|
||||
sourceFolder = wrapper->instance;
|
||||
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [targetFolder moveCopyMessagesWithMIDs: src_mids
|
||||
andCount: mid_count
|
||||
fromFolder: sourceFolder
|
||||
@@ -598,8 +704,10 @@ sogo_folder_move_copy_messages(void *folder_object,
|
||||
andChangeKeys: target_change_keys
|
||||
wantCopy: want_copy
|
||||
inMemCtx: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -632,7 +740,7 @@ sogo_folder_move_folder(void *folder_object, void *target_folder_object,
|
||||
else
|
||||
targetFolder = nil;
|
||||
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
if (new_folder_name)
|
||||
@@ -640,14 +748,16 @@ sogo_folder_move_folder(void *folder_object, void *target_folder_object,
|
||||
else
|
||||
newFolderName = nil;
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [moveFolder moveCopyToFolder: targetFolder
|
||||
withNewName: newFolderName
|
||||
isMove: YES
|
||||
isRecursive: YES
|
||||
inMemCtx: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -677,19 +787,21 @@ sogo_folder_copy_folder(void *folder_object, void *target_folder_object, TALLOC_
|
||||
wrapper = target_folder_object;
|
||||
targetFolder = wrapper->instance;
|
||||
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
newFolderName = [NSString stringWithUTF8String: new_folder_name];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [copyFolder moveCopyToFolder: targetFolder
|
||||
withNewName: newFolderName
|
||||
isMove: NO
|
||||
isRecursive: recursive
|
||||
inMemCtx: mem_ctx];
|
||||
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -715,15 +827,19 @@ sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder getDeletedFMIDs: fmidsp
|
||||
andCN: cnp
|
||||
fromChangeNumber: change_num
|
||||
inTableType: table_type
|
||||
inMemCtx: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -750,16 +866,20 @@ sogo_folder_open_table(void *folder_object, TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder getTable: &table
|
||||
andRowCount: row_count
|
||||
tableType: table_type
|
||||
andHandleId: handle_id];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*table_object = [table tallocWrapper: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -785,13 +905,17 @@ sogo_folder_modify_permissions(void *folder_object, uint8_t flags,
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder modifyPermissions: permissions
|
||||
withCount: pcount
|
||||
andFlags: flags];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -815,12 +939,16 @@ sogo_folder_preload_message_bodies(void *folder_object, enum mapistore_table_typ
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [folder preloadMessageBodiesWithMIDs: mids
|
||||
ofTableType: table_type];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -846,12 +974,16 @@ sogo_message_get_message_data(void *message_object,
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
[message getMessageData: msg_dataP
|
||||
inMemCtx: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
else
|
||||
@@ -877,14 +1009,18 @@ sogo_message_create_attachment (void *message_object, TALLOC_CTX *mem_ctx, void
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [message createAttachment: &attachment inAID: aidp];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*attachment_object = [attachment tallocWrapper: mem_ctx];
|
||||
// [context tearDownRequest];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -910,14 +1046,18 @@ sogo_message_open_attachment (void *message_object, TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [message getAttachment: &attachment withAID: aid];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*attachment_object = [attachment tallocWrapper: mem_ctx];
|
||||
// [context tearDownRequest];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -942,15 +1082,19 @@ sogo_message_get_attachment_table (void *message_object, TALLOC_CTX *mem_ctx, vo
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [message getAttachmentTable: &table
|
||||
andRowCount: row_count];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*table_object = [table tallocWrapper: mem_ctx];
|
||||
// [context tearDownRequest];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -977,14 +1121,18 @@ sogo_message_modify_recipients (void *message_object,
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [message modifyRecipientsWithRecipients: recipients
|
||||
andCount: count
|
||||
andColumns: columns];
|
||||
// [context tearDownRequest];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1008,12 +1156,16 @@ sogo_message_set_read_flag (void *message_object, uint8_t flag)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [message setReadFlag: flag];
|
||||
// [context tearDownRequest];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1037,12 +1189,16 @@ sogo_message_save (void *message_object, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [message saveMessage: mem_ctx];
|
||||
// [context tearDownRequest];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1066,12 +1222,16 @@ sogo_message_submit (void *message_object, enum SubmitFlags flags)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [message submitWithFlags: flags];
|
||||
// [context tearDownRequest];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1100,16 +1260,20 @@ sogo_message_attachment_open_embedded_message (void *attachment_object,
|
||||
{
|
||||
wrapper = attachment_object;
|
||||
attachment = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [attachment openEmbeddedMessage: &message
|
||||
withMID: midP
|
||||
withMAPIStoreMsg: msg
|
||||
inMemCtx: mem_ctx];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*message_object = [message tallocWrapper: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1137,15 +1301,19 @@ sogo_message_attachment_create_embedded_message (void *attachment_object,
|
||||
{
|
||||
wrapper = attachment_object;
|
||||
attachment = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [attachment createEmbeddedMessage: &message
|
||||
withMAPIStoreMsg: msg
|
||||
inMemCtx: mem_ctx];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*message_object = [message tallocWrapper: mem_ctx];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [attachment createEmbeddedMessage: &message
|
||||
withMAPIStoreMsg: msg
|
||||
inMemCtx: mem_ctx];
|
||||
if (rc == MAPISTORE_SUCCESS)
|
||||
*message_object = [message tallocWrapper: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1169,11 +1337,15 @@ static enum mapistore_error sogo_table_get_available_properties(void *table_obje
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [table getAvailableProperties: propertiesP inMemCtx: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1197,12 +1369,16 @@ sogo_table_set_columns (void *table_object, uint16_t count, enum MAPITAGS *prope
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [table setColumns: properties
|
||||
withCount: count];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1226,14 +1402,18 @@ sogo_table_set_restrictions (void *table_object, struct mapi_SRestriction *restr
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
[table setRestrictions: restrictions];
|
||||
//[table cleanupCaches];
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
*table_status = TBLSTAT_COMPLETE;
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1257,14 +1437,18 @@ sogo_table_set_sort_order (void *table_object, struct SSortOrderSet *sort_order,
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
[table setSortOrder: sort_order];
|
||||
[table cleanupCaches];
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
*table_status = TBLSTAT_COMPLETE;
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1290,12 +1474,16 @@ sogo_table_get_row (void *table_object, TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [table getRow: data withRowID: row_id andQueryType: query_type
|
||||
inMemCtx: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1321,12 +1509,16 @@ sogo_table_get_row_count (void *table_object,
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [table getRowCount: row_countp
|
||||
withQueryType: query_type];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1350,11 +1542,15 @@ sogo_table_handle_destructor (void *table_object, uint32_t handle_id)
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
[table destroyHandle: handle_id];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
else
|
||||
@@ -1380,11 +1576,15 @@ static enum mapistore_error sogo_properties_get_available_properties(void *objec
|
||||
{
|
||||
wrapper = object;
|
||||
propObject = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [propObject getAvailableProperties: propertiesP inMemCtx: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1411,13 +1611,17 @@ sogo_properties_get_properties (void *object,
|
||||
{
|
||||
wrapper = object;
|
||||
propObject = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [propObject getProperties: data withTags: properties
|
||||
andCount: count
|
||||
inMemCtx: mem_ctx];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1441,11 +1645,15 @@ sogo_properties_set_properties (void *object, struct SRow *aRow)
|
||||
{
|
||||
wrapper = object;
|
||||
propObject = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
rc = [propObject addPropertiesFromRow: aRow];
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1472,9 +1680,10 @@ sogo_manager_generate_uri (TALLOC_CTX *mem_ctx,
|
||||
|
||||
/* This fixes a crash occurring during the instantiation of the
|
||||
NSAutoreleasePool below. */
|
||||
GSRegisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_REGISTER();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
TRYCATCH_START
|
||||
// printf("rootURI = %s\n", rootURI);
|
||||
if (rootURI)
|
||||
partialURLString = [NSString stringWithUTF8String: rootURI];
|
||||
@@ -1494,9 +1703,10 @@ sogo_manager_generate_uri (TALLOC_CTX *mem_ctx,
|
||||
|
||||
// printf("uri = %s\n", [partialURLString UTF8String]);
|
||||
*uri = talloc_strdup (mem_ctx, [partialURLString UTF8String]);
|
||||
TRYCATCH_END(pool)
|
||||
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
NS_CURRENT_THREAD_TRY_UNREGISTER();
|
||||
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -63,10 +63,10 @@
|
||||
}
|
||||
|
||||
+ (id) userContextWithUsername: (NSString *) username
|
||||
andTDBIndexing: (struct tdb_wrap *) indexingTdb;
|
||||
andTDBIndexing: (struct indexing_context *) indexing;
|
||||
|
||||
- (id) initWithUsername: (NSString *) newUsername
|
||||
andTDBIndexing: (struct tdb_wrap *) indexingTdb;
|
||||
andTDBIndexing: (struct indexing_context *) indexing;
|
||||
|
||||
- (NSString *) username;
|
||||
- (SOGoUser *) sogoUser;
|
||||
|
||||
@@ -60,7 +60,7 @@ static NSMapTable *contextsTable = nil;
|
||||
}
|
||||
|
||||
+ (id) userContextWithUsername: (NSString *) username
|
||||
andTDBIndexing: (struct tdb_wrap *) indexingTdb;
|
||||
andTDBIndexing: (struct indexing_context *) indexing;
|
||||
{
|
||||
id userContext;
|
||||
|
||||
@@ -68,7 +68,7 @@ static NSMapTable *contextsTable = nil;
|
||||
if (!userContext)
|
||||
{
|
||||
userContext = [[self alloc] initWithUsername: username
|
||||
andTDBIndexing: indexingTdb];
|
||||
andTDBIndexing: indexing];
|
||||
[userContext autorelease];
|
||||
[contextsTable setObject: userContext forKey: username];
|
||||
}
|
||||
@@ -100,16 +100,12 @@ static NSMapTable *contextsTable = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *) _readUserPassword: (NSString *) newUsername
|
||||
- (NSString *) _readPasswordFile: (NSString *) path
|
||||
{
|
||||
NSString *password, *path;
|
||||
NSString *password;
|
||||
NSData *content;
|
||||
|
||||
password = nil;
|
||||
|
||||
path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR
|
||||
@"/mapistore/%@/password", newUsername];
|
||||
|
||||
password = nil;
|
||||
content = [NSData dataWithContentsOfFile: path];
|
||||
|
||||
if (content)
|
||||
@@ -124,8 +120,26 @@ static NSMapTable *contextsTable = nil;
|
||||
return password;
|
||||
}
|
||||
|
||||
- (NSString *) _readUserPassword: (NSString *) newUsername
|
||||
{
|
||||
NSString *password, *path;
|
||||
|
||||
path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR
|
||||
@"/mapistore/%@/password", newUsername];
|
||||
|
||||
password = [self _readPasswordFile: path];
|
||||
if (password == nil)
|
||||
{
|
||||
// Try to get master password
|
||||
path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR @"/mapistore/master.password"];
|
||||
password = [self _readPasswordFile: path];
|
||||
}
|
||||
|
||||
return password;
|
||||
}
|
||||
|
||||
- (id) initWithUsername: (NSString *) newUsername
|
||||
andTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||
andTDBIndexing: (struct indexing_context *) indexing
|
||||
{
|
||||
NSString *userPassword;
|
||||
|
||||
@@ -133,9 +147,9 @@ static NSMapTable *contextsTable = nil;
|
||||
{
|
||||
/* "username" will be retained by table */
|
||||
username = newUsername;
|
||||
if (indexingTdb)
|
||||
if (indexing)
|
||||
ASSIGN (mapping, [MAPIStoreMapping mappingForUsername: username
|
||||
withIndexing: indexingTdb]);
|
||||
withIndexing: indexing]);
|
||||
|
||||
authenticator = [MAPIStoreAuthenticator new];
|
||||
[authenticator setUsername: username];
|
||||
|
||||
@@ -47,13 +47,13 @@ MAPIStoreTallocWrapperDestroy (void *data)
|
||||
struct MAPIStoreTallocWrapper *wrapper;
|
||||
NSAutoreleasePool *pool;
|
||||
|
||||
GSRegisterCurrentThread ();
|
||||
// GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
wrapper = data;
|
||||
//NSLog (@"destroying wrapped object (wrapper: %p; object: %p (%@))...\n", wrapper, wrapper->instance, NSStringFromClass([wrapper->instance class]));
|
||||
[wrapper->instance release];
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
// GSUnregisterCurrentThread ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/* dbmsgdump.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2014 Kamen Mazdrashki <kmazdrashki@zentyal.com>
|
||||
*
|
||||
* Based on implementation done by Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A format-agnostic dump extensions for:
|
||||
* NSArray
|
||||
* NSObject
|
||||
* NSDictionary
|
||||
*/
|
||||
|
||||
#ifndef NSOBJECT_PROPERTYLIST_H
|
||||
#define NSOBJECT_PROPERTYLIST_H
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
|
||||
|
||||
@interface NSObject (plext)
|
||||
|
||||
- (void) displayWithIndentation: (NSInteger) anInt;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSDictionary (plext)
|
||||
|
||||
- (void) displayKey: (NSString *) key
|
||||
withIndentation: (NSInteger) anInt;
|
||||
|
||||
- (void) displayWithIndentation: (NSInteger) anInt;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSArray (plext)
|
||||
|
||||
- (void) displayCount: (NSUInteger) count
|
||||
withIndentation: (NSInteger) anInt;
|
||||
|
||||
- (void) displayWithIndentation: (NSInteger) anInt;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* NSOBJECT_PROPERTYLIST_H */
|
||||
@@ -32,14 +32,10 @@
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
|
||||
#import <SOGo/BSONCodec.h>
|
||||
#import "NSObject+PropertyList.h"
|
||||
|
||||
const char *indentationStep = " ";
|
||||
|
||||
@interface NSObject (plext)
|
||||
|
||||
- (void) displayWithIndentation: (NSInteger) anInt;
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSObject (plext)
|
||||
|
||||
@@ -139,46 +135,3 @@ const char *indentationStep = " ";
|
||||
|
||||
@end
|
||||
|
||||
static void
|
||||
OCDumpPListData (NSData *content)
|
||||
{
|
||||
//NSDictionary *d;
|
||||
//NSPropertyListFormat format;
|
||||
//NSString *error = nil;
|
||||
//const char *formatName;
|
||||
|
||||
//d = [NSPropertyListSerialization propertyListFromData: content
|
||||
// mutabilityOption: NSPropertyListImmutable
|
||||
// format: &format
|
||||
// errorDescription: &error];
|
||||
//d = [content BSONValue];
|
||||
|
||||
// if (d)
|
||||
// {
|
||||
// switch (format)
|
||||
// {
|
||||
// case NSPropertyListOpenStepFormat:
|
||||
// formatName = "OpenStep";
|
||||
// break;
|
||||
// case NSPropertyListXMLFormat_v1_0:
|
||||
// formatName = "XML";
|
||||
// break;
|
||||
// case NSPropertyListBinaryFormat_v1_0:
|
||||
// formatName = "Binary";
|
||||
// break;
|
||||
// case NSPropertyListGNUstepFormat:
|
||||
// formatName = "GNUstep";
|
||||
// break;
|
||||
// case NSPropertyListGNUstepBinaryFormat:
|
||||
// formatName = "GNUstep binary";
|
||||
// break;
|
||||
// default: formatName = "unknown";
|
||||
// }
|
||||
|
||||
// printf ("File format is: %s\n", formatName);
|
||||
// [d displayWithIndentation: 0];
|
||||
// printf ("\n");
|
||||
// }
|
||||
// else
|
||||
// printf ("an error occurred: %s\n", [error UTF8String]);
|
||||
}
|
||||
|
||||
@@ -36,10 +36,20 @@
|
||||
#import "MAPIStoreUserContext.h"
|
||||
#import <SOGo/SOGoCacheGCSObject.h>
|
||||
|
||||
#import "NSObject+PropertyList.m"
|
||||
#import <SOGo/BSONCodec.h>
|
||||
#import "NSObject+PropertyList.h"
|
||||
|
||||
Class MAPIStoreUserContextK, SOGoMAPIDBObjectK;
|
||||
|
||||
static void
|
||||
DumpBSONData(NSData *data)
|
||||
{
|
||||
NSDictionary *dvalue;
|
||||
dvalue = [data BSONValue];
|
||||
[dvalue displayWithIndentation:0];
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
DbDumpObject (NSString *username, NSString *path)
|
||||
{
|
||||
@@ -55,8 +65,9 @@ DbDumpObject (NSString *username, NSString *path)
|
||||
record = [dbobject lookupRecord: path newerThanVersion: -1];
|
||||
if (record)
|
||||
{
|
||||
printf("record found: %p\n", record);
|
||||
content = [[record objectForKey: @"c_content"] dataByDecodingBase64];
|
||||
OCDumpPListData (content);
|
||||
DumpBSONData(content);
|
||||
}
|
||||
else
|
||||
NSLog (@"record not found");
|
||||
@@ -99,9 +110,12 @@ int main (int argc, char *argv[], char *envp[])
|
||||
SOGoMAPIDBObjectK = NSClassFromString (@"SOGoMAPIDBObject");
|
||||
|
||||
arguments = [[NSProcessInfo processInfo] arguments];
|
||||
if ([arguments count] > 2)
|
||||
if ([arguments count] > 2) {
|
||||
DbDumpObject ([arguments objectAtIndex: 1],
|
||||
[arguments objectAtIndex: 2]);
|
||||
} else if ([arguments count] > 1) {
|
||||
DumpBSONData([[arguments objectAtIndex:1] dataByDecodingBase64]);
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
|
||||
@@ -228,6 +228,15 @@
|
||||
[start setTimeZone: tz];
|
||||
if (isAllDay)
|
||||
{
|
||||
/* when user TZ is positive (East) all-day events were not
|
||||
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 setTimeZone: nil];
|
||||
}
|
||||
@@ -251,6 +260,15 @@
|
||||
[end setTimeZone: tz];
|
||||
if (isAllDay)
|
||||
{
|
||||
/* when user TZ is positive (East) all-day events were not
|
||||
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 setTimeZone: nil];
|
||||
}
|
||||
|
||||
@@ -29,6 +29,50 @@
|
||||
|
||||
#import "NSObject+PropertyList.m"
|
||||
|
||||
static void
|
||||
OCDumpPListData (NSData *content)
|
||||
{
|
||||
//NSDictionary *d;
|
||||
//NSPropertyListFormat format;
|
||||
//NSString *error = nil;
|
||||
//const char *formatName;
|
||||
|
||||
//d = [NSPropertyListSerialization propertyListFromData: content
|
||||
// mutabilityOption: NSPropertyListImmutable
|
||||
// format: &format
|
||||
// errorDescription: &error];
|
||||
//d = [content BSONValue];
|
||||
|
||||
// if (d)
|
||||
// {
|
||||
// switch (format)
|
||||
// {
|
||||
// case NSPropertyListOpenStepFormat:
|
||||
// formatName = "OpenStep";
|
||||
// break;
|
||||
// case NSPropertyListXMLFormat_v1_0:
|
||||
// formatName = "XML";
|
||||
// break;
|
||||
// case NSPropertyListBinaryFormat_v1_0:
|
||||
// formatName = "Binary";
|
||||
// break;
|
||||
// case NSPropertyListGNUstepFormat:
|
||||
// formatName = "GNUstep";
|
||||
// break;
|
||||
// case NSPropertyListGNUstepBinaryFormat:
|
||||
// formatName = "GNUstep binary";
|
||||
// break;
|
||||
// default: formatName = "unknown";
|
||||
// }
|
||||
|
||||
// printf ("File format is: %s\n", formatName);
|
||||
// [d displayWithIndentation: 0];
|
||||
// printf ("\n");
|
||||
// }
|
||||
// else
|
||||
// printf ("an error occurred: %s\n", [error UTF8String]);
|
||||
}
|
||||
|
||||
static void
|
||||
PLReaderDumpPListFile (NSString *filename)
|
||||
{
|
||||
|
||||
@@ -276,7 +276,7 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
|
||||
EOAdaptorChannel *channel;
|
||||
GCSChannelHandle *handle;
|
||||
NSCalendarDate *now, *lastFailure;
|
||||
NSString *urlId;
|
||||
NSString *urlId, *url;
|
||||
|
||||
channel = nil;
|
||||
urlId = [_url gcsURLId];
|
||||
@@ -304,10 +304,10 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
|
||||
}
|
||||
else
|
||||
{
|
||||
url = [NSString stringWithFormat: @"%@://%@%@", [_url scheme], [_url host], [_url path]];
|
||||
if (debugPools)
|
||||
{
|
||||
[self logWithFormat: @"DBPOOL: create new DB channel for URL: %@",
|
||||
[_url absoluteString]];
|
||||
[self logWithFormat: @"DBPOOL: create new DB channel for %@", url];
|
||||
}
|
||||
|
||||
/* create channel */
|
||||
@@ -330,15 +330,13 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
|
||||
|
||||
if (lastFailure)
|
||||
{
|
||||
[self logWithFormat: @"db for %@ is now back up",
|
||||
[_url absoluteString]];
|
||||
[self logWithFormat: @"db for %@ is now back up", url];
|
||||
[lastFailures removeObjectForKey: urlId];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[self errorWithFormat: @"could not open channel %@ for URL: %@",
|
||||
channel, [_url absoluteString]];
|
||||
[self errorWithFormat: @"could not open channel %@ for %@", channel, url];
|
||||
channel = nil;
|
||||
[lastFailures setObject: now forKey: urlId];
|
||||
[self warnWithFormat: @" will prevent opening of this"
|
||||
|
||||
@@ -74,6 +74,7 @@ ifneq ($(frameworks),yes)
|
||||
ifneq ($(FHS_INSTALL_ROOT),)
|
||||
GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include
|
||||
endif
|
||||
GNUSTEP_TARGET_LDIR=sogo
|
||||
include $(GNUSTEP_MAKEFILES)/library.make
|
||||
else
|
||||
include $(GNUSTEP_MAKEFILES)/framework.make
|
||||
|
||||
@@ -131,6 +131,7 @@ ifneq ($(frameworks),yes)
|
||||
ifneq ($(FHS_INSTALL_ROOT),)
|
||||
GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include
|
||||
endif
|
||||
GNUSTEP_TARGET_LDIR=sogo
|
||||
include $(GNUSTEP_MAKEFILES)/library.make
|
||||
else
|
||||
include $(GNUSTEP_MAKEFILES)/framework.make
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Abidjan
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Accra
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Addis_Ababa
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Algiers
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Asmara
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Bamako
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Bangui
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Banjul
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Bissau
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Blantyre
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Brazzaville
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Bujumbura
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Cairo
|
||||
X-LIC-LOCATION:Africa/Cairo
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:+0200
|
||||
TZOFFSETFROM:+0300
|
||||
TZOFFSETTO:+0200
|
||||
TZNAME:EET
|
||||
DTSTART:19700101T000000
|
||||
DTSTART:19700924T235959
|
||||
RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1TH
|
||||
END:STANDARD
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0300
|
||||
TZOFFSETTO:+0300
|
||||
TZNAME:EEST
|
||||
DTSTART:19700424T010000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1FR
|
||||
END:DAYLIGHT
|
||||
END:VTIMEZONE
|
||||
END:VCALENDAR
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Casablanca
|
||||
X-LIC-LOCATION:Africa/Casablanca
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0000
|
||||
TZOFFSETTO:+0100
|
||||
TZNAME:WEST
|
||||
DTSTART:19700426T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0000
|
||||
TZNAME:WET
|
||||
DTSTART:19700927T030000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU
|
||||
DTSTART:19701025T030000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||
END:STANDARD
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0100
|
||||
TZNAME:WEST
|
||||
DTSTART:19700329T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||
END:DAYLIGHT
|
||||
END:VTIMEZONE
|
||||
END:VCALENDAR
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Ceuta
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Conakry
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Dakar
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Dar_es_Salaam
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Djibouti
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Douala
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/El_Aaiun
|
||||
X-LIC-LOCATION:Africa/El_Aaiun
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:+0000
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0000
|
||||
TZNAME:WET
|
||||
DTSTART:19700101T000000
|
||||
DTSTART:19701025T030000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||
END:STANDARD
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0100
|
||||
TZNAME:WEST
|
||||
DTSTART:19700329T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||
END:DAYLIGHT
|
||||
END:VTIMEZONE
|
||||
END:VCALENDAR
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Freetown
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Gaborone
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Harare
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Johannesburg
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Juba
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Kampala
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Khartoum
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Kigali
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Kinshasa
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Lagos
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Libreville
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Lome
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Luanda
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Lubumbashi
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Lusaka
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Malabo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Maputo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Maseru
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Mbabane
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Mogadishu
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Monrovia
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Nairobi
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Ndjamena
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Niamey
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Nouakchott
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Ouagadougou
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Porto-Novo
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Sao_Tome
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Tripoli
|
||||
X-LIC-LOCATION:Africa/Tripoli
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0100
|
||||
TZOFFSETTO:+0200
|
||||
TZNAME:CEST
|
||||
DTSTART:19700327T010000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1FR
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:+0200
|
||||
TZOFFSETTO:+0100
|
||||
TZNAME:CET
|
||||
DTSTART:19701030T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1FR
|
||||
TZOFFSETTO:+0200
|
||||
TZNAME:EET
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
END:VCALENDAR
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Tunis
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Africa/Windhoek
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Adak
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Anchorage
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Anguilla
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Antigua
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2012j//EN
|
||||
PRODID:-//Inverse inc.//NONSGML Olson 2014g//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Araguaina
|
||||
X-LIC-LOCATION:America/Araguaina
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0200
|
||||
TZNAME:BRST
|
||||
DTSTART:19701018T000000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=3SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0300
|
||||
TZOFFSETTO:-0300
|
||||
TZNAME:BRT
|
||||
DTSTART:19700215T000000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=2;BYDAY=3SU
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
END:VCALENDAR
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user