[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#682684: unblock: sogo/1.3.16-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package sogo

Debian changelog:

sogo (1.3.16-1) unstable; urgency=low

  * New upstream release. (Closes: #677119)
    - 0004-Add-support-for-GnuTLS.patch: Updated to new hashes in 1.3.16.
    - 0007-GNUstep-1.24-fix.patch: Removed, was backported from upstream.
  * Do not assume deluser is available in postrm. (Closes: #678099)
  * Suggest postgresql or mysql-server. (Closes: #678047)
  * Build with hardening
    - 0007-Compile-daemon-as-PIE.patch: Compile the daemon as a PIE.

 -- Jeroen Dekkers <jeroen@dekkers.ch>  Sat, 30 Jun 2012 02:55:17 +0200

I actually wanted to have this package uploaded before the freeze, but
that didn't happen because my sponsor didn't manage to upload it on
time. The new upstream release only has bugfixes except one new
feature: the addition of more secure hash functions. Currently the SQL
user backend only has unsalted MD5 and SHA1, the new version adds
salting, SHA256 and SHA512. In my opinion it is not responsible
anymore to save passwords using unsalted MD5/SHA1 hashing, so I really
want to have this change included in wheezy.

The new upstream release also has the following minor changes:

 - it's no longer possible to click the "Upload" button multiple times
 - allow delivery of mail with no subject, but alert the user
 - fixed LDAP group expansion
 - fixed exception when reading ACL of a deleted mailbox
 - fixed exception when composing a mail while the database server is down
 - fixed handling of all-day repeating events with exception dates
 - fixed Sieve filter editor when matching all messages
 - fixed creation of URLs (A-tag) in messages
 - updated Dutch, German, French translations

The debdiff is attached. Note that the "OpenChange" directory isn't
enabled in 1.3.x, so any changes in that directory can be ignored.

unblock sogo/1.3.16-1

-- System Information:
Debian Release: wheezy/sid
  APT prefers precise-updates
  APT policy: (990, 'precise-updates'), (990, 'precise-security'), (990, 'precise-backports'), (990, 'precise'), (500, 'quantal')
Architecture: amd64 (x86_64)

Kernel: Linux 3.2.0-26-generic (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff -Nru sogo-1.3.15a/Apache/SOGo.conf sogo-1.3.16/Apache/SOGo.conf
--- sogo-1.3.15a/Apache/SOGo.conf	2012-05-18 17:27:01.000000000 +0200
+++ sogo-1.3.16/Apache/SOGo.conf	2012-06-07 17:40:39.000000000 +0200
@@ -9,6 +9,13 @@
     AllowOverride None
     Order deny,allow
     Allow from all
+
+    # Explicitly allow caching of static content to avoid browser specific behavior.
+    # A resource's URL MUST change in order to have the client load the new version.
+    <IfModule expires_module>
+      ExpiresActive On
+      ExpiresDefault "access plus 1 year"
+    </IfModule>
 </Directory>
 
 <LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*\.(jpg|png|gif|css|js)">
@@ -64,4 +71,4 @@
 # The remote address will appear in SOGo's log files and in the X-Forward
 # header of emails.
 RewriteEngine On
-RewriteRule ^/SOGo/(.*)$ /SOGo/$1 [env=REMOTE_HOST:%{REMOTE_ADDR},PT]
\ No newline at end of file
+RewriteRule ^/SOGo/(.*)$ /SOGo/$1 [env=REMOTE_HOST:%{REMOTE_ADDR},PT]
diff -Nru sogo-1.3.15a/ChangeLog sogo-1.3.16/ChangeLog
--- sogo-1.3.15a/ChangeLog	2012-05-18 17:27:01.000000000 +0200
+++ sogo-1.3.16/ChangeLog	2012-06-07 17:40:39.000000000 +0200
@@ -1,8 +1,112 @@
+2012-06-04  Francis Lachapelle  <flachapelle@inverse.ca>
+
+	* UI/WebServerResources/UIxFilterEditor.js (savePreferences):
+	don't validate filters if they are not visible (when matching all
+	incoming messages).
+
+	* SoObjects/Appointments/SOGoAppointmentFolder.m
+	(-_appendCycleException:firstInstanceCalendarDateRange:fromRow:forRange:withTimeZone:toArray:):
+	adjust recurrence id according to timezone when dealing with a
+	floating all-day event.
+
+2012-06-01  Francis Lachapelle  <flachapelle@inverse.ca>
+
+	* SoObjects/SOGo/NSString+Utilities.m
+	(-_handleURLs:textToMatch:prefix:inRanges:): don't reset the
+	prefix for the subsequent matching strings. This fixes links in
+	messages with multiple email addresses, some of which already
+	prefixed by "mailto;".
+
+2012-06-01  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+	* UI/MailPartViewers/UIxMailPartAlternativeViewer.m
+	(-childPartName): fixed a potential crash by building the NSString
+	from the integer itself, with the proper format string.
+
+	* SoObjects/SOGo/NSString+Crypto.m
+	(-isEqualToCrypted:withDefaultScheme:): invoke "intValue" rather
+	than "integerValue" on the encoding number as the int type is not
+	crucial and it breaks the build with old versions of GNUstep.
+
+	* SoObjects/SOGo/NSString+Crypto.[hm]: new module that provides
+	category methods for returning encrypted passwords strings and
+	their encryption algorithm.
+
+2012-05-31  Ludovic Marcotte  <lmarcotte@inverse.ca>
+
+	* SoObjects/SOGo/SOGoGroup.m - we now handle lowercase
+	all attribute names
+	* SoObject/SOGo/LDAPSource.m - moved the lowercasing
+	of attributes to SOPE.
+	* Added patch from bug #1608. This add many more password
+	schemes for SQL authentication.
+	* SoObject/Mailer/SOGoMailFolder.m (-_readMailboxACL): we
+	now create the mailbox if we are trying to read ACL of
+	a deleted mailbox.
+	* UI/MailerUI/UIxMailEditor.m (-personalContactInfos): we check
+	if the folder still exist and if the database isn't down
+	before performing any address books search operations.
+	* UI/MailerUI/UIxMailMainFrame.m (-unseenCountFolders): we no
+	longer fill up the list of mailboxes to with the ones that are
+	targets for "fileinto" methods if Sieve scripts aren't enabled
+	in SOGo's domain defaults.
+
+2012-05-29  Francis Lachapelle  <flachapelle@inverse.ca>
+
+	* UI/WebServerResources/UIxMailEditor.js (validateEditorInput):
+	merged with onValidate.
+	(onValidate): don't force the subject to be defined, but alert
+	the user.
+
+	* UI/MailerUI/UIxMailView.m (-messageSubject): don't set the
+	subject to "Untitled" if it's not set.
+
+	* UI/MailPartViewers/UIxMailPartMessageViewer.m (-messageSubject): idem.
+
+	* UI/MailerUI/UIxMailEditor.m (-validateForSend): don't force the
+	subject to be defined.
+
+	* SoObjects/Mailer/SOGoMailObject+Draft.m (-subjectForReply): make
+	sure subject is a defined value to avoid "null" strings in the
+	reply message.
+
+2012-05-28  Francis Lachapelle  <flachapelle@inverse.ca>
+
+	* UI/WebServerResources/SchedulerUI.js (validateUploadForm): hide
+	Cancel button when the form is valid and disable the Submit button.
+
+	* UI/WebServerResources/ContactsUI.js (validateUploadForm): idem.
+
+2012-05-24  Jean Raby  <jraby@inverse.ca>
+
+	* debian*/rules: Restart sogod after pkg upgrade (dh_installinit -R)
+	* Scripts/sogo-init.d-*: add support for conditional restart.
+	  Patch from Romain Le Disez
+	* sogo.spec: Restart sogod during post installation if it was already running
+
+	* Apache/SOGo.conf:
+	Use mod_expires to allow long term caching of static content. (1 year)
+	Note that from now on, a resource's URL _must_ change to let the client
+	reload it.  This is now done automatically for 'rsrc' in the wox templates,
+	but must be done manually for files referenced from css and js.
+
+2012-05-23  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+	* UI/WebServerResources/generic.js
+	(clickEventWrapper.button_clickEventWrappe): don't invoke
+	"preventDefault" on elements that do not have a tagName of "A".
+
 2012-05-18  Jean Raby  <jraby@inverse.ca>
 
 	* SoObjects/Mailer/SOGoDraftObject.m (bodyPartForAttachmentWithName):
 	Merge back lost code to handle encoding of binary and rcf822 attachments.
 
+2012-05-15  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+	* OpenChange/gen-property-selectors.py: the use of the "{}" to
+	construct a set is only valid on py2.7 therefore we make use of
+	set([]) instead.
+
 2012-05-15  Jean Raby  <jraby@inverse.ca>
 
 	* SoObjects/Appointments/SOGoAppointmentObject.m (_handleResourcesConflicts):
@@ -10,9 +114,12 @@
 	to read its freebusy info.
 	Without this, sogo would always auto-accept invitations from 'unprivileged'
 	users, potentially bypassing the multiplebooking parameter.
-	
+
 2012-05-14  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
 
+	* OpenChange/gen-property-selectors.py: "bannedProps" is now a
+	set, for faster lookups.
+
 	* UI/WebServerResources/UIxContactsUserFolders.js: folder ids are
 	in the form "user:module/folder", therefore we must remove the
 	first char, which is a slash.
@@ -73,6 +180,12 @@
 	link, remove double-quotes and escape single-quotes from the fullname.
 	(-secondaryEmail): idem.
 
+2012-05-04  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+	* OpenChange/MAPIStoreSOGo.m: register and unregister current
+	thread before and after each backend operation, in order to avoid
+	issues in multithreaded environment.
+
 2012-05-01  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
 
 	* UI/WebServerResources/generic.js (accessToSubscribedFolder): use
@@ -385,6 +498,31 @@
 	* OGoContentStore/OCSContactFieldExtractor.m
 	(-extractQuickFieldsFromVCard): idem.
 
+2012-03-30  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+	* OpenChange/MAPIStoreCalendarMessage.m (-save): remove comment if
+	content is "\n".
+
+	* OpenChange/MAPIStoreTasksMessage.m (-save): do not reset fields
+	that have not been passed in the properties array, since only
+	RopDeleteProperties should remove them.
+	Remove comment if content is "\n".
+
+	* OpenChange/MAPIStoreObject.m (-addPropertiesFromRow:): dates are
+	now all converted to the user's timezone, even though it just
+	inverts the problem we currently have.
+
+	* OpenChange/MAPIApplication.m (-init): utcTZ is now initialized
+	here.
+
+	* OpenChange/MAPIStoreTypes.[hm]: new host module for utcTZ.
+
+	* OpenChange/MAPIStoreUserContext.m (-timeZone): new method that
+	returns the timezone of an owner user.
+
+	* OpenChange/MAPIStoreObject.m (-ownerTimeZone): removed method,
+	replaced with the one above.
+
 2012-03-29  Francis Lachapelle  <flachapelle@inverse.ca>
 
 	* UI/WebServerResources/UIxPreferences.js (savePreferences): fixed
@@ -397,8 +535,38 @@
 
 	* UI/WebServerResources/MailerUI.js (startDragging): idem.
 
+2012-03-29  Francis Lachapelle  <flachapelle@inverse.ca>
+
+	* UI/WebServerResources/UIxPreferences.js (savePreferences): fixed
+	validation of end date of vacation of message when not using ISO
+	format (currently limited to French).
+
+	* UI/WebServerResources/ContactsUI.js (startDragging): create an
+	overlapping safety block (div) to avoid possible selection of the
+	underlying text.
+
+	* UI/WebServerResources/MailerUI.js (startDragging): idem.
+
+2012-03-28  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+	* SoObjects/Contacts/SOGoFolder+CardDAV.m (_isValidFilter:):
+	accept "email" as filter name.
+	(_appendObject:withBaseURL:toREPORTResponse:): fixed the ordering
+	of XML elements as the address*-data props where put outside of
+	the <D:prop> tree.
+
+	* SoObjects/SOGo/LDAPSource.m (-allEntryIDs): take the _filter
+	ivar into account.
+
 2012-03-28  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
 
+	* OpenChange/SOGoMAPIFSMessage.m
+	(_readFileChangesDataWithDate:andInode:): use the inode number
+	rather than the filesize as change indicator since a new file is
+	created each time the dictionary is written to disk, thanks to the
+	"atomically" flag.
+	(-save): write the file atomically.
+
 	* SoObjects/Contacts/SOGoFolder+CardDAV.m (_isValidFilter:):
 	accept "email" as filter name.
 	(_appendObject:withBaseURL:toREPORTResponse:): fixed the ordering
@@ -410,6 +578,24 @@
 
 2012-03-27  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
 
+	* SoObjects/Contacts/SOGoContactFolders.m
+	(-lookupName:inContext:acquire:): overriden method that enables
+	the lookup of hidden public sources with iOS devices.
+
+	* SoObjects/Contacts/SOGoContactLDIFEntry.m (-davAddressData): new
+	getter similar to davCalendarData.
+
+	* SoObjects/Contacts/SOGoContactSourceFolder.m
+	(-davAddressbookMultiget): new REPORT handler based on
+	-[SOGoAppointmentFolder davCalendarMultiget].
+
+	* SoObjects/Contacts/SOGoUserFolder+Contacts.m
+	(-davDirectoryGateway): new getter that returns the url to the
+	first available directory source.
+	(-davResourceType): declare resource as "directory" (carddav).
+
+2012-03-27  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
 	* SoObjects/Contacts/SOGoContactFolders.m
 	(-lookupName:inContext:acquire:): overriden method that enables
 	the lookup of hidden public sources with iOS devices.
Binary files /tmp/lp5QWHfbpA/sogo-1.3.15a/Documentation/SOGo Installation Guide.odt and /tmp/TEeyt1iGWB/sogo-1.3.16/Documentation/SOGo Installation Guide.odt differ
Binary files /tmp/lp5QWHfbpA/sogo-1.3.15a/Documentation/SOGo Mobile Devices Configuration.odt and /tmp/TEeyt1iGWB/sogo-1.3.16/Documentation/SOGo Mobile Devices Configuration.odt differ
Binary files /tmp/lp5QWHfbpA/sogo-1.3.15a/Documentation/SOGo Mozilla Thunderbird Configuration.odt and /tmp/TEeyt1iGWB/sogo-1.3.16/Documentation/SOGo Mozilla Thunderbird Configuration.odt differ
Binary files /tmp/lp5QWHfbpA/sogo-1.3.15a/Documentation/SOGo Native Microsoft Outlook Configuration.odt and /tmp/TEeyt1iGWB/sogo-1.3.16/Documentation/SOGo Native Microsoft Outlook Configuration.odt differ
diff -Nru sogo-1.3.15a/NEWS sogo-1.3.16/NEWS
--- sogo-1.3.15a/NEWS	2012-05-18 17:27:03.000000000 +0200
+++ sogo-1.3.16/NEWS	2012-06-07 17:40:39.000000000 +0200
@@ -1,3 +1,24 @@
+1.3.16 (2012-06-07)
+-------------------
+Enhancements
+ - new password schemes for SQL authentication (crypt-md5, ssha (including
+   256/512 variants), cram-md5, smd5, crypt, crypt-md5)
+ - new unique names for static resources to avoid browser caching when
+   updating SOGo
+ - it's no longer possible to click the "Upload" button multiple times
+ - allow delivery of mail with no subject, but alert the user
+ - updated Dutch, German, French translations
+Bug Fixes
+ - fixed compilation under GNU/kFreeBSD
+ - fixed compilation for arm architecture
+ - fixed exceptions under 64bit GNUstep 1.24
+ - fixed LDAP group expansion
+ - fixed exception when reading ACL of a deleted mailbox
+ - fixed exception when composing a mail while the database server is down
+ - fixed handling of all-day repeating events with exception dates
+ - fixed Sieve filter editor when matching all messages
+ - fixed creation of URLs (A-tag) in messages
+
 1.3.15 (2012-05-15)
 -------------------
 New Features
diff -Nru sogo-1.3.15a/OpenChange/MAPIApplication.m sogo-1.3.16/OpenChange/MAPIApplication.m
--- sogo-1.3.15a/OpenChange/MAPIApplication.m	2012-05-18 17:27:03.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIApplication.m	2012-06-07 17:40:40.000000000 +0200
@@ -21,6 +21,7 @@
  */
 
 #import <Foundation/NSUserDefaults.h>
+#import <Foundation/NSTimeZone.h>
 
 #import <SOGo/SOGoProductLoader.h>
 #import <SOGo/SOGoSystemDefaults.h>
@@ -28,6 +29,7 @@
 #import <Appointments/iCalEntityObject+SOGo.h>
 
 #import "MAPIStoreUserContext.h"
+#import "MAPIStoreTypes.h"
 
 #import "MAPIApplication.h"
 
@@ -49,6 +51,9 @@
 
       MAPIApp = [super init];
       [MAPIApp retain];
+
+      utcTZ = [NSTimeZone timeZoneWithName: @"UTC"];
+      [utcTZ retain];
     }
 
   return MAPIApp;
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreAppointmentWrapper.h sogo-1.3.16/OpenChange/MAPIStoreAppointmentWrapper.h
--- sogo-1.3.15a/OpenChange/MAPIStoreAppointmentWrapper.h	2012-05-18 17:27:03.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreAppointmentWrapper.h	2012-06-07 17:40:40.000000000 +0200
@@ -35,8 +35,6 @@
 
 @class SOGoUser;
 
-extern NSTimeZone *utcTZ;
-
 @interface MAPIStoreAppointmentWrapper : NSObject
 {
   struct mapistore_connection_info *connInfo;
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreAppointmentWrapper.m sogo-1.3.16/OpenChange/MAPIStoreAppointmentWrapper.m
--- sogo-1.3.15a/OpenChange/MAPIStoreAppointmentWrapper.m	2012-05-18 17:27:03.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreAppointmentWrapper.m	2012-06-07 17:40:40.000000000 +0200
@@ -59,16 +59,12 @@
 #include <mapistore/mapistore_errors.h>
 #include <mapistore/mapistore_nameid.h>
 
-NSTimeZone *utcTZ;
-
 static NSCharacterSet *hexCharacterSet = nil;
 
 @implementation MAPIStoreAppointmentWrapper
 
 + (void) initialize
 {
-  utcTZ = [NSTimeZone timeZoneWithName: @"UTC"];
-  [utcTZ retain];
   if (!hexCharacterSet)
     {
       hexCharacterSet = [NSCharacterSet characterSetWithCharactersInString: @"1234567890abcdefABCDEF"];
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreCalendarMessage.m sogo-1.3.16/OpenChange/MAPIStoreCalendarMessage.m
--- sogo-1.3.15a/OpenChange/MAPIStoreCalendarMessage.m	2012-05-18 17:27:03.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreCalendarMessage.m	2012-06-07 17:40:40.000000000 +0200
@@ -118,7 +118,7 @@
               [MAPIStoreAppointmentWrapper wrapperWithICalEvent: event
                                                         andUser: [userContext sogoUser]
                                                  andSenderEmail: nil
-                                                     inTimeZone: [self ownerTimeZone]
+                                                     inTimeZone: [userContext timeZone]
                                              withConnectionInfo: [context connectionInfo]]);
     }
 
@@ -766,10 +766,12 @@
     isAllDay = [value boolValue];
   if (!isAllDay)
     {
-      tzName = [[self ownerTimeZone] name];
+      tzName = [[[self userContext] timeZone] name];
       tz = [iCalTimeZone timeZoneForName: tzName];
       [vCalendar addTimeZone: tz];
     }
+  else
+    tz = nil;
   
   // start
   value = [properties objectForKey: MAPIPropertyKey (PR_START_DATE)];
@@ -779,18 +781,18 @@
   if (value)
     {
       start = (iCalDateTime *) [newEvent uniqueChildWithTag: @"dtstart"];
+      [start setTimeZone: tz];
       if (isAllDay)
         {
-          tzOffset = [[value timeZone] secondsFromGMTForDate: value];
-          value = [value dateByAddingYears: 0 months: 0 days: 0
-                                     hours: 0 minutes: 0
-                                   seconds: -tzOffset];
-          [start setTimeZone: nil];
           [start setDate: value];
+          [start setTimeZone: nil];
         }
       else
         {
-          [start setTimeZone: tz];
+          tzOffset = [[value timeZone] secondsFromGMTForDate: value];
+          value = [value dateByAddingYears: 0 months: 0 days: 0
+                                     hours: 0 minutes: 0
+                                   seconds: tzOffset];
           [start setDateTime: value];
         }
     }
@@ -802,18 +804,18 @@
   if (value)
     {
       end = (iCalDateTime *) [newEvent uniqueChildWithTag: @"dtend"];
+      [end setTimeZone: tz];
       if (isAllDay)
         {
-          tzOffset = [[value timeZone] secondsFromGMTForDate: value];
-          value = [value dateByAddingYears: 0 months: 0 days: 0
-                                     hours: 0 minutes: 0
-                                   seconds: -tzOffset];
-          [end setTimeZone: nil];
           [end setDate: value];
+          [end setTimeZone: nil];
         }
       else
         {
-          [end setTimeZone: tz];
+          tzOffset = [[value timeZone] secondsFromGMTForDate: value];
+          value = [value dateByAddingYears: 0 months: 0 days: 0
+                                     hours: 0 minutes: 0
+                                   seconds: tzOffset];
           [end setDateTime: value];
         }
     }
@@ -872,10 +874,13 @@
           value = [value htmlToText];
         }
     }
-  if (value && [value length] == 0)
-    value = nil;
-  [newEvent setComment: value];
-      
+  if (value)
+    {
+      if ([value length] == 0 || [value isEqualToString: @"\\n"])
+        value = nil;
+      [newEvent setComment: value];
+    }
+
   /* recurrence */
   value = [properties
                 objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreContactsAttachment.m sogo-1.3.16/OpenChange/MAPIStoreContactsAttachment.m
--- sogo-1.3.15a/OpenChange/MAPIStoreContactsAttachment.m	2012-05-18 17:27:03.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreContactsAttachment.m	2012-06-07 17:40:40.000000000 +0200
@@ -35,8 +35,6 @@
 
 #include <mapistore/mapistore_errors.h>
 
-extern NSTimeZone *utcTZ;
-
 /* TODO: handle URL pictures via PidTagAttachMethod = ref ? */
 
 @implementation MAPIStoreContactsAttachment
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreContext.h sogo-1.3.16/OpenChange/MAPIStoreContext.h
--- sogo-1.3.15a/OpenChange/MAPIStoreContext.h	2012-05-18 17:27:03.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreContext.h	2012-06-07 17:40:40.000000000 +0200
@@ -55,8 +55,8 @@
 {
   struct mapistore_connection_info *connInfo;
   NSMutableArray *containersBag;
-  SOGoUser *activeUser;
-  MAPIStoreUserContext *userContext;
+  SOGoUser *activeUser;              /* the user accessing the resource */
+  MAPIStoreUserContext *userContext; /* the owner or the resource */
   NSURL *contextUrl;
 }
 
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreFAIMessage.m sogo-1.3.16/OpenChange/MAPIStoreFAIMessage.m
--- sogo-1.3.15a/OpenChange/MAPIStoreFAIMessage.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreFAIMessage.m	2012-06-07 17:40:40.000000000 +0200
@@ -28,6 +28,7 @@
 #import "MAPIStoreFAIMessage.h"
 
 #undef DEBUG
+#include <stdbool.h>
 #include <talloc.h>
 #include <util/time.h>
 #include <mapistore/mapistore.h>
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreFallbackContext.m sogo-1.3.16/OpenChange/MAPIStoreFallbackContext.m
--- sogo-1.3.15a/OpenChange/MAPIStoreFallbackContext.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreFallbackContext.m	2012-06-07 17:40:40.000000000 +0200
@@ -31,6 +31,7 @@
 #import "MAPIStoreFallbackContext.h"
 
 #undef DEBUG
+#include <inttypes.h>
 #include <mapistore/mapistore.h>
 
 @implementation MAPIStoreFallbackContext
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreMailMessage.m sogo-1.3.16/OpenChange/MAPIStoreMailMessage.m
--- sogo-1.3.15a/OpenChange/MAPIStoreMailMessage.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreMailMessage.m	2012-06-07 17:40:40.000000000 +0200
@@ -284,7 +284,7 @@
                                  wrapperWithICalEvent: event
                                               andUser: [context activeUser]
                                        andSenderEmail: senderEmail
-                                           inTimeZone: [self ownerTimeZone]
+                                           inTimeZone: [[self userContext] timeZone]
                                    withConnectionInfo: [context connectionInfo]];
           [appointmentWrapper retain];
         }
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreMailVolatileMessage.m sogo-1.3.16/OpenChange/MAPIStoreMailVolatileMessage.m
--- sogo-1.3.15a/OpenChange/MAPIStoreMailVolatileMessage.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreMailVolatileMessage.m	2012-06-07 17:40:40.000000000 +0200
@@ -29,6 +29,7 @@
 #import <Foundation/NSData.h>
 #import <Foundation/NSDictionary.h>
 #import <Foundation/NSString.h>
+#import <Foundation/NSTimeZone.h>
 #import <Foundation/NSValue.h>
 #import <NGExtensions/NGHashMap.h>
 #import <NGExtensions/NSObject+Logs.h>
@@ -495,7 +496,11 @@
 
   date = [mailProperties objectForKey: MAPIPropertyKey (PR_CLIENT_SUBMIT_TIME)];
   if (date)
-    [headers addObject: [date rfc822DateString] forKey: @"date"];
+    {
+      date = [date addYear: 0 month: 0 day: 0
+                      hour: 0 minute: 0 second: [[date timeZone] secondsFromGMT]];
+      [headers addObject: [date rfc822DateString] forKey: @"date"];
+    }
   [headers addObject: @"1.0" forKey: @"MIME-Version"];
 }
 
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreObject.h sogo-1.3.16/OpenChange/MAPIStoreObject.h
--- sogo-1.3.15a/OpenChange/MAPIStoreObject.h	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreObject.h	2012-06-07 17:40:40.000000000 +0200
@@ -77,8 +77,6 @@
 - (uint64_t) objectId;
 - (NSString *) url;
 
-- (NSTimeZone *) ownerTimeZone;
-
 /* properties */
 
 - (BOOL) canGetProperty: (enum MAPITAGS) propTag;
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreObject.m sogo-1.3.16/OpenChange/MAPIStoreObject.m
--- sogo-1.3.15a/OpenChange/MAPIStoreObject.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreObject.m	2012-06-07 17:40:40.000000000 +0200
@@ -20,7 +20,9 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#import <Foundation/NSCalendarDate.h>
 #import <Foundation/NSDictionary.h>
+#import <Foundation/NSTimeZone.h>
 #import <NGExtensions/NSObject+Logs.h>
 #import <SOGo/SOGoObject.h>
 #import <SOGo/SOGoUser.h>
@@ -210,21 +212,6 @@
                     containerURL, [self nameInContainer]];
 }
 
-- (NSTimeZone *) ownerTimeZone
-{
-  NSString *owner;
-  SOGoUserDefaults *ud;
-  NSTimeZone *tz;
-  WOContext *woContext;
-
-  woContext = [[self userContext] woContext];
-  owner = [sogoObject ownerInContext: woContext];
-  ud = [[SOGoUser userWithLogin: owner] userDefaults];
-  tz = [ud timeZone];
-
-  return tz;
-}
-
 - (void) addProperties: (NSDictionary *) newNewProperties
 {
   [properties addEntriesFromDictionary: newNewProperties];
@@ -447,16 +434,37 @@
   struct SPropValue *cValue;
   NSUInteger counter;
   NSMutableDictionary *newProperties;
+  NSTimeZone *tz;
+  NSInteger tzOffset;
+  id value;
+
+  tz = nil;
 
   newProperties = [NSMutableDictionary dictionaryWithCapacity: aRow->cValues];
   for (counter = 0; counter < aRow->cValues; counter++)
     {
       cValue = aRow->lpProps + counter;
-      if ((cValue->ulPropTag & 0xfff) == PT_STRING8)
-        [self warnWithFormat:
-                @"attempting to set string property as PR_STRING8: %.8x",
-              cValue->ulPropTag];
-      [newProperties setObject: NSObjectFromSPropValue (cValue)
+      value = NSObjectFromSPropValue (cValue);
+      switch (cValue->ulPropTag & 0xffff)
+        {
+        case PT_STRING8:
+        case PT_MV_STRING8:
+          [self warnWithFormat:
+                  @"attempting to set string property as PR_STRING8: %.8x",
+                cValue->ulPropTag];
+          break;
+        case PT_SYSTIME:
+          if (!tz)
+            {
+              tz = [[self userContext] timeZone];
+              tzOffset = -[tz secondsFromGMT];
+            }
+          value = [value addYear: 0 month: 0 day: 0
+                            hour: 0 minute: 0 second: tzOffset];
+          [value setTimeZone: tz];
+          break;
+        }
+      [newProperties setObject: value
                         forKey: MAPIPropertyKey (cValue->ulPropTag)];
     }
 
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreRecurrenceUtils.m sogo-1.3.16/OpenChange/MAPIStoreRecurrenceUtils.m
--- sogo-1.3.15a/OpenChange/MAPIStoreRecurrenceUtils.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreRecurrenceUtils.m	2012-06-07 17:40:40.000000000 +0200
@@ -21,6 +21,7 @@
  */
 
 #import <Foundation/NSArray.h>
+#import <Foundation/NSString.h>
 
 #import <NGExtensions/NSCalendarDate+misc.h>
 #import <NGExtensions/NSObject+Logs.h>
@@ -32,6 +33,7 @@
 #import "NSDate+MAPIStore.h"
 #import "MAPIStoreRecurrenceUtils.h"
 
+#include <stdbool.h>
 #include <talloc.h>
 #include <util/time.h>
 #include <gen_ndr/property.h>
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreSOGo.m sogo-1.3.16/OpenChange/MAPIStoreSOGo.m
--- sogo-1.3.15a/OpenChange/MAPIStoreSOGo.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreSOGo.m	2012-06-07 17:40:40.000000000 +0200
@@ -64,9 +64,11 @@
 {
   NSAutoreleasePool *pool;
 
+  GSRegisterCurrentThread ();
   pool = [NSAutoreleasePool new];
   NSLog (@"allocated classes:\n%s", GSDebugAllocationList (YES));
   [pool release];
+  GSUnregisterCurrentThread ();
 }
 
 /**
@@ -84,6 +86,7 @@
   SoProductRegistry *registry;
   char *argv[] = { SAMBA_PREFIX "/sbin/samba", NULL };
 
+  GSRegisterCurrentThread ();
   pool = [NSAutoreleasePool new];
 
   /* Here we work around a bug in GNUstep which decodes XML user
@@ -149,6 +152,7 @@
 
   DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
 
+  GSRegisterCurrentThread ();
   pool = [NSAutoreleasePool new];
 
   if (MAPIStoreContextK)
@@ -164,6 +168,7 @@
     rc = MAPISTORE_ERROR;
 
   [pool release];
+  GSUnregisterCurrentThread ();
 
   return rc;
 }
@@ -182,6 +187,7 @@
 
   DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
 
+  GSRegisterCurrentThread ();
   pool = [NSAutoreleasePool new];
 
   if (MAPIStoreContextK)
@@ -200,6 +206,7 @@
     rc = MAPISTORE_ERROR;
 
   [pool release];
+  GSUnregisterCurrentThread ();
 
   return rc;
 }
@@ -215,6 +222,7 @@
 
   DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
 
+  GSRegisterCurrentThread ();
   pool = [NSAutoreleasePool new];
 
   if (MAPIStoreContextK)
@@ -229,6 +237,7 @@
     rc = MAPISTORE_ERROR;
 
   [pool release];
+  GSUnregisterCurrentThread ();
 
   return rc;
 }
@@ -263,9 +272,11 @@
     {
       wrapper = backend_object;
       context = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [context getPath: path ofFMID: fmid inMemCtx: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -291,11 +302,13 @@
     {
       wrapper = backend_object;
       context = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [context getRootFolder: &folder withFID: fid];
       if (rc == MAPISTORE_SUCCESS)
         *folder_object = [folder tallocWrapper: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -328,12 +341,14 @@
     {
       wrapper = folder_object;
       folder = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [folder openFolder: &childFolder withFID: fid];
       if (rc == MAPISTORE_SUCCESS)
         *childfolder_object = [childFolder tallocWrapper: mem_ctx];
       // [context tearDownRequest];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -366,11 +381,13 @@
     {
       wrapper = folder_object;
       folder = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [folder createFolder: &childFolder withRow: aRow andFID: fid];
       if (rc == MAPISTORE_SUCCESS)
         *childfolder_object = [childFolder tallocWrapper: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -403,9 +420,11 @@
     {
       wrapper = folder_object;
       folder = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [folder deleteFolder];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -429,9 +448,11 @@
     {
       wrapper = folder_object;
       folder = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [folder getChildCount: child_count ofTableType: table_type];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -459,6 +480,7 @@
     {
       wrapper = folder_object;
       folder = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [folder openMessage: &message
                        withMID: mid
@@ -467,6 +489,7 @@
       if (rc == MAPISTORE_SUCCESS)
         *message_object = [message tallocWrapper: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -495,6 +518,7 @@
     {
       wrapper = folder_object;
       folder = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [folder createMessage: &message
                          withMID: mid
@@ -502,6 +526,7 @@
       if (rc == MAPISTORE_SUCCESS)
         *message_object = [message tallocWrapper: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -525,9 +550,11 @@
     {
       wrapper = folder_object;
       folder = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [folder deleteMessageWithMID: mid andFlags: flags];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -560,6 +587,7 @@
       wrapper = source_folder_object;
       sourceFolder = wrapper->MAPIStoreSOGoObject;
 
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [targetFolder moveCopyMessagesWithMIDs: src_mids
                                          andCount: mid_count
@@ -568,6 +596,7 @@
                                     andChangeKeys: target_change_keys
                                          wantCopy: want_copy];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -593,6 +622,7 @@
     {
       wrapper = folder_object;
       folder = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [folder getDeletedFMIDs: fmidsp
                              andCN: cnp
@@ -600,6 +630,7 @@
                        inTableType: table_type
                           inMemCtx: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -626,6 +657,7 @@
     {
       wrapper = folder_object;
       folder = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [folder getTable: &table
                 andRowCount: row_count
@@ -634,6 +666,7 @@
       if (rc == MAPISTORE_SUCCESS)
         *table_object = [table tallocWrapper: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -659,11 +692,13 @@
     {
       wrapper = folder_object;
       folder = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [folder modifyPermissions: permissions
                            withCount: pcount
                             andFlags: flags];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -689,10 +724,12 @@
     {
       wrapper = message_object;
       message = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       [message getMessageData: msg_dataP
                      inMemCtx: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
       rc = MAPISTORE_SUCCESS;
     }
   else
@@ -718,12 +755,14 @@
     {
       wrapper = message_object;
       message = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [message createAttachment: &attachment inAID: aidp];
       if (rc == MAPISTORE_SUCCESS)
         *attachment_object = [attachment tallocWrapper: mem_ctx];
       // [context tearDownRequest];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -749,12 +788,14 @@
     {
       wrapper = message_object;
       message = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [message getAttachment: &attachment withAID: aid];
       if (rc == MAPISTORE_SUCCESS)
         *attachment_object = [attachment tallocWrapper: mem_ctx];
       // [context tearDownRequest];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -779,6 +820,7 @@
     {
       wrapper = message_object;
       message = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [message getAttachmentTable: &table
                            andRowCount: row_count];
@@ -786,6 +828,7 @@
         *table_object = [table tallocWrapper: mem_ctx];
       // [context tearDownRequest];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -812,12 +855,14 @@
     {
       wrapper = message_object;
       message = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [message modifyRecipientsWithRecipients: recipients
                                           andCount: count
                                         andColumns: columns];
       // [context tearDownRequest];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -841,10 +886,12 @@
     {
       wrapper = message_object;
       message = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [message setReadFlag: flag];
       // [context tearDownRequest];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -868,10 +915,12 @@
     {
       wrapper = message_object;
       message = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [message saveMessage];
       // [context tearDownRequest];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -895,10 +944,12 @@
     {
       wrapper = message_object;
       message = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [message submitWithFlags: flags];
       // [context tearDownRequest];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -923,12 +974,11 @@
 
   DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
 
-  pool = [NSAutoreleasePool new];
-
   if (attachment_object)
     {
       wrapper = attachment_object;
       attachment = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [attachment openEmbeddedMessage: &message
                                    withMID: midP
@@ -937,6 +987,7 @@
       if (rc == MAPISTORE_SUCCESS)
         *message_object = [message tallocWrapper: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -960,9 +1011,11 @@
     {
       wrapper = table_object;
       table = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [table getAvailableProperties: propertiesP inMemCtx: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -986,10 +1039,12 @@
     {
       wrapper = table_object;
       table = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [table setColumns: properties
                    withCount: count];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -1013,12 +1068,14 @@
     {
       wrapper = table_object;
       table = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       [table setRestrictions: restrictions];
       [table cleanupCaches];
       rc = MAPISTORE_SUCCESS;
       *table_status = TBLSTAT_COMPLETE;
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -1042,12 +1099,14 @@
     {
       wrapper = table_object;
       table = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       [table setSortOrder: sort_order];
       [table cleanupCaches];
       rc = MAPISTORE_SUCCESS;
       *table_status = TBLSTAT_COMPLETE;
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -1073,10 +1132,12 @@
     {
       wrapper = table_object;
       table = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [table getRow: data withRowID: row_id andQueryType: query_type
                 inMemCtx: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -1102,10 +1163,12 @@
     {
       wrapper = table_object;
       table = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [table getRowCount: row_countp
                 withQueryType: query_type];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -1129,9 +1192,11 @@
     {
       wrapper = table_object;
       table = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       [table destroyHandle: handle_id];
       [pool release];
+      GSUnregisterCurrentThread ();
       rc = MAPISTORE_SUCCESS;
     }
   else
@@ -1157,9 +1222,11 @@
     {
       wrapper = object;
       propObject = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [propObject getAvailableProperties: propertiesP inMemCtx: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -1186,11 +1253,13 @@
     {
       wrapper = object;
       propObject = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [propObject getProperties: data withTags: properties
                             andCount: count
                             inMemCtx: mem_ctx];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -1214,9 +1283,11 @@
     {
       wrapper = object;
       propObject = wrapper->MAPIStoreSOGoObject;
+      GSRegisterCurrentThread ();
       pool = [NSAutoreleasePool new];
       rc = [propObject addPropertiesFromRow: aRow];
       [pool release];
+      GSUnregisterCurrentThread ();
     }
   else
     {
@@ -1244,7 +1315,6 @@
   /* This fixes a crash occurring during the instantiation of the
      NSAutoreleasePool below. */
   GSRegisterCurrentThread ();
-
   pool = [NSAutoreleasePool new];
 
   // printf("rootURI = %s\n", rootURI);
@@ -1268,7 +1338,6 @@
   *uri = talloc_strdup (mem_ctx, [partialURLString UTF8String]);
 
   [pool release];
-
   GSUnregisterCurrentThread ();
 
   return MAPISTORE_SUCCESS;
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreTasksMessage.m sogo-1.3.16/OpenChange/MAPIStoreTasksMessage.m
--- sogo-1.3.15a/OpenChange/MAPIStoreTasksMessage.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreTasksMessage.m	2012-06-07 17:40:40.000000000 +0200
@@ -329,7 +329,8 @@
   iCalToDo *vToDo;
   id value;
   iCalDateTime *date;
-  NSString *status, *priority;
+  iCalTimeZone *tz;
+  NSString *status, *priority, *tzName;
   NSCalendarDate *now;
   NSInteger tzOffset;
   double doubleValue;
@@ -338,6 +339,10 @@
   vCalendar = [vToDo parent];
   [vCalendar setProdID: @"-//Inverse inc.//OpenChange+SOGo//EN"];
 
+  tzName = [[[self userContext] timeZone] name];
+  tz = [iCalTimeZone timeZoneForName: tzName];
+  [vCalendar addTimeZone: tz];
+
   // summary
   value = [properties
             objectForKey: MAPIPropertyKey (PR_NORMALIZED_SUBJECT_UNICODE)];
@@ -358,12 +363,12 @@
           value = [value htmlToText];
         }
     }
-  if (value && [value length] == 0)
-    value = nil;
-  [vToDo setComment: value];
-
   if (value)
-    [vToDo setComment: value];
+    {
+      if ([value length] == 0 || [value isEqualToString: @"\\n"])
+        value = nil;
+      [vToDo setComment: value];
+    }
 
   // location
   value = [properties objectForKey: MAPIPropertyKey (PidLidLocation)];
@@ -388,31 +393,17 @@
   if (value)
     {
       date = (iCalDateTime *) [vToDo uniqueChildWithTag: @"dtstart"];
-      tzOffset = [[value timeZone] secondsFromGMTForDate: value];
-      value = [value dateByAddingYears: 0 months: 0 days: 0
-                                 hours: 0 minutes: 0
-                               seconds: -tzOffset];
-      [date setDate: value];
-    }
-  else
-    {
-      [vToDo setStartDate: nil]; 
+      [date setTimeZone: tz];
+      [date setDateTime: value];
     }
-
+  
   // due
   value = [properties objectForKey: MAPIPropertyKey (PidLidTaskDueDate)];
   if (value)
     {
       date = (iCalDateTime *) [vToDo uniqueChildWithTag: @"due"];
-      tzOffset = [[value timeZone] secondsFromGMTForDate: value];
-      value = [value dateByAddingYears: 0 months: 0 days: 0
-                                 hours: 0 minutes: 0
-                               seconds: -tzOffset];
-      [date setDate: value];
-    }
-  else
-    {
-      [vToDo setDue: nil];
+      [date setTimeZone: tz];
+      [date setDateTime: value];
     }
 
   // completed
@@ -426,10 +417,6 @@
                                seconds: -tzOffset];
       [date setDate: value];
     }
-  else
-    {
-      [vToDo setCompleted: nil];
-    }
 
   // status
   value = [properties objectForKey: MAPIPropertyKey (PidLidTaskStatus)];
@@ -459,10 +446,8 @@
         default: // IMPORTANCE_NORMAL
           priority = @"5";
         }
+      [vToDo setPriority: priority];
     }
-  else
-    priority = @"0"; // None
-  [vToDo setPriority: priority];
 
   // percent complete
   // NOTE: this does not seem to work on Outlook 2003. PidLidPercentComplete's value
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreTypes.h sogo-1.3.16/OpenChange/MAPIStoreTypes.h
--- sogo-1.3.15a/OpenChange/MAPIStoreTypes.h	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreTypes.h	2012-06-07 17:40:40.000000000 +0200
@@ -32,6 +32,9 @@
 
 @class NSData;
 @class NSDictionary;
+@class NSTimeZone;
+
+extern NSTimeZone *utcTZ;
 
 uint8_t *MAPIBoolValue (void *memCtx, BOOL value);
 uint32_t *MAPILongValue (void *memCtx, uint32_t value);
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreTypes.m sogo-1.3.16/OpenChange/MAPIStoreTypes.m
--- sogo-1.3.15a/OpenChange/MAPIStoreTypes.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreTypes.m	2012-06-07 17:40:40.000000000 +0200
@@ -36,6 +36,8 @@
 #include <mapistore/mapistore.h>
 #include <mapistore/mapistore_errors.h>
 
+NSTimeZone *utcTZ;
+
 uint8_t *
 MAPIBoolValue (void *memCtx, BOOL value)
 {
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreUserContext.h sogo-1.3.16/OpenChange/MAPIStoreUserContext.h
--- sogo-1.3.15a/OpenChange/MAPIStoreUserContext.h	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreUserContext.h	2012-06-07 17:40:40.000000000 +0200
@@ -27,6 +27,7 @@
 
 @class NSMutableDictionary;
 @class NSString;
+@class NSTimeZone;
 
 @class WOContext;
 
@@ -43,6 +44,7 @@
 {
   NSString *username;
   SOGoUser *sogoUser;
+  NSTimeZone *timeZone;
 
   SOGoUserFolder *userFolder;
   NSMutableArray *containersBag;
@@ -63,6 +65,8 @@
 - (NSString *) username;
 - (SOGoUser *) sogoUser;
 
+- (NSTimeZone *) timeZone;
+
 - (SOGoUserFolder *) userFolder;
 
 - (NSDictionary *) rootFolders;
diff -Nru sogo-1.3.15a/OpenChange/MAPIStoreUserContext.m sogo-1.3.16/OpenChange/MAPIStoreUserContext.m
--- sogo-1.3.15a/OpenChange/MAPIStoreUserContext.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/MAPIStoreUserContext.m	2012-06-07 17:40:40.000000000 +0200
@@ -137,6 +137,20 @@
   return sogoUser;
 }
 
+- (NSTimeZone *) timeZone
+{
+  if (!timeZone)
+    {
+      SOGoUser *user;
+
+      user = [self sogoUser];
+      timeZone = [[user userDefaults] timeZone];
+      [timeZone retain];
+    }
+
+  return timeZone;
+}
+
 - (SOGoUserFolder *) userFolder
 {
   if (!userFolder)
diff -Nru sogo-1.3.15a/OpenChange/NSArray+MAPIStore.m sogo-1.3.16/OpenChange/NSArray+MAPIStore.m
--- sogo-1.3.15a/OpenChange/NSArray+MAPIStore.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/NSArray+MAPIStore.m	2012-06-07 17:40:40.000000000 +0200
@@ -29,6 +29,7 @@
 #import "NSArray+MAPIStore.h"
 
 #undef DEBUG
+#include <stdbool.h>
 #include <talloc.h>
 #include <util/time.h>
 #include <gen_ndr/exchange.h>
diff -Nru sogo-1.3.15a/OpenChange/NSDate+MAPIStore.m sogo-1.3.16/OpenChange/NSDate+MAPIStore.m
--- sogo-1.3.15a/OpenChange/NSDate+MAPIStore.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/NSDate+MAPIStore.m	2012-06-07 17:40:40.000000000 +0200
@@ -27,6 +27,7 @@
 #import "NSDate+MAPIStore.h"
 
 #undef DEBUG
+#include <stdbool.h>
 #include <talloc.h>
 #include <util/time.h>
 #include <mapistore/mapistore.h>
diff -Nru sogo-1.3.15a/OpenChange/NSObject+MAPIStore.m sogo-1.3.16/OpenChange/NSObject+MAPIStore.m
--- sogo-1.3.15a/OpenChange/NSObject+MAPIStore.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/NSObject+MAPIStore.m	2012-06-07 17:40:40.000000000 +0200
@@ -21,6 +21,7 @@
  */
 
 #import <Foundation/NSAutoreleasePool.h>
+#import <Foundation/NSThread.h>
 #import <NGExtensions/NSObject+Logs.h>
 
 #import "MAPIStoreTypes.h"
@@ -44,11 +45,13 @@
   struct MAPIStoreTallocWrapper *wrapper;
   NSAutoreleasePool *pool;
 
+  GSRegisterCurrentThread ();
   pool = [NSAutoreleasePool new];
   wrapper = data;
   // NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject);
   [wrapper->MAPIStoreSOGoObject release];
   [pool release];
+  GSUnregisterCurrentThread ();
 
   return 0;
 }
diff -Nru sogo-1.3.15a/OpenChange/SOGoMAPIFSFolder.m sogo-1.3.16/OpenChange/SOGoMAPIFSFolder.m
--- sogo-1.3.15a/OpenChange/SOGoMAPIFSFolder.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/SOGoMAPIFSFolder.m	2012-06-07 17:40:40.000000000 +0200
@@ -39,6 +39,7 @@
 #import "SOGoMAPIFSFolder.h"
 
 #undef DEBUG
+#include <stdbool.h>
 #include <talloc.h>
 #include <util/time.h>
 #include <mapistore/mapistore.h>
diff -Nru sogo-1.3.15a/OpenChange/SOGoMAPIFSMessage.h sogo-1.3.16/OpenChange/SOGoMAPIFSMessage.h
--- sogo-1.3.15a/OpenChange/SOGoMAPIFSMessage.h	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/SOGoMAPIFSMessage.h	2012-06-07 17:40:40.000000000 +0200
@@ -31,7 +31,7 @@
 @interface SOGoMAPIFSMessage : SOGoMAPIVolatileMessage
 {
   NSString *completeFilename;
-  NSUInteger fileSize;
+  NSUInteger inode;
   NSData *lastModificationTime;
 }
 
diff -Nru sogo-1.3.15a/OpenChange/SOGoMAPIFSMessage.m sogo-1.3.16/OpenChange/SOGoMAPIFSMessage.m
--- sogo-1.3.15a/OpenChange/SOGoMAPIFSMessage.m	2012-05-18 17:27:04.000000000 +0200
+++ sogo-1.3.16/OpenChange/SOGoMAPIFSMessage.m	2012-06-07 17:40:40.000000000 +0200
@@ -41,7 +41,7 @@
   if ((self = [super init]))
     {
       completeFilename = nil;
-      fileSize = 0;
+      inode = 0;
       lastModificationTime = nil;
     }
 
@@ -86,7 +86,7 @@
 }
 
 - (BOOL) _readFileChangesDataWithDate: (NSDate **) newLMTime
-                              andSize: (NSUInteger *) newFileSize
+                             andInode: (NSUInteger *) newInode
 {
   BOOL rc;
   NSDictionary *attributes;
@@ -97,7 +97,7 @@
   if (attributes)
     {
       *newLMTime = [attributes fileModificationDate];
-      *newFileSize = [attributes fileSize];
+      *newInode = [attributes fileSystemFileNumber];
       rc = YES;
     }
   else
@@ -107,22 +107,22 @@
 }
 
 - (BOOL) _checkFileChangesDataWithDate: (NSDate **) newLMTime
-                               andSize: (NSUInteger *) newFileSize
+                              andInode: (NSUInteger *) newInode
 {
   BOOL hasChanged = NO;
   NSDate *lastLMTime;
-  NSUInteger lastFileSize;
+  NSUInteger lastInode;
 
   if ([self _readFileChangesDataWithDate: &lastLMTime
-                                 andSize: &lastFileSize])
+                                andInode: &lastInode])
     {
-      if (fileSize != lastFileSize
+      if (inode != lastInode
           || ![lastModificationTime isEqual: lastLMTime])
         {
           if (lastLMTime)
             *newLMTime = lastLMTime;
-          if (newFileSize)
-            *newFileSize = lastFileSize;
+          if (newInode)
+            *newInode = lastInode;
           hasChanged = YES;
         }
     }
@@ -136,10 +136,10 @@
   NSString *error;
   NSPropertyListFormat format;
   NSDate *lastLMTime;
-  NSUInteger lastFileSize;
+  NSUInteger lastInode;
 
   if ([self _checkFileChangesDataWithDate: &lastLMTime
-                                  andSize: &lastFileSize])
+                                 andInode: &lastInode])
     {
       [self logWithFormat: @"file '%@' new or modified: rereading properties",
             [self completeFilename]];
@@ -158,7 +158,7 @@
                   @" of message: '%@'", error];
         }
       ASSIGN (lastModificationTime, lastLMTime);
-      fileSize = lastFileSize;
+      inode = lastInode;
     }
 
   return [super properties];
@@ -168,7 +168,7 @@
 {
   NSData *content;
   NSDate *lastLMTime;
-  NSUInteger lastFileSize;
+  NSUInteger lastInode;
 
   [container ensureDirectory];
 
@@ -178,14 +178,13 @@
               dataFromPropertyList: [self properties]
                             format: NSPropertyListBinaryFormat_v1_0
                   errorDescription: NULL];
-  if (![content writeToFile: [self completeFilename] atomically: NO])
+  if (![content writeToFile: [self completeFilename] atomically: YES])
     [NSException raise: @"MAPIStoreIOException"
 		 format: @"could not save message"];
 
-  [self _readFileChangesDataWithDate: &lastLMTime
-                             andSize: &lastFileSize];
+  [self _readFileChangesDataWithDate: &lastLMTime andInode: &lastInode];
   ASSIGN (lastModificationTime, lastLMTime);
-  fileSize = lastFileSize;
+  inode = lastInode;
   // [self logWithFormat: @"fs message written to '%@'", [self completeFilename]];
 }
 
diff -Nru sogo-1.3.15a/OpenChange/gen-property-selectors.py sogo-1.3.16/OpenChange/gen-property-selectors.py
--- sogo-1.3.15a/OpenChange/gen-property-selectors.py	2012-05-18 17:27:05.000000000 +0200
+++ sogo-1.3.16/OpenChange/gen-property-selectors.py	2012-06-07 17:40:40.000000000 +0200
@@ -106,32 +106,37 @@
 
 # hack: some properties have multiple and incompatible types. Sometimes those
 # props are not related at all...
-bannedProps = [ "PidTagBodyHtml", "PidTagFavAutosubfolders",
-                "PidTagAttachDataObj", "PidTagAclTable", "PidTagAclData",
-                "PidTagRulesTable", "PidTagRulesData", "PidTagDisableWinsock",
-                "PidTagHierarchyServer", "PidTagOfflineAddrbookEntryid",
-                "PidTagShorttermEntryidFromObject",
-                "PidTagNormalMessageSizeExtended",
-                "PidTagAssocMessageSizeExtended", "PidTagMessageSizeExtended",
-                "PidTagOabContainerGuid",
-                "PidTagOfflineAddressBookMessageClass", "PidTagScriptData",
-                "PidTagOfflineAddressBookTruncatedProperties",
-                "PidTagOfflineAddressBookContainerGuid",
-                "PidTagOfflineAddressBookDistinguishedName",
-                "PidTagOfflineAddressBookShaHash",
-                "PidTagSenderTelephoneNumber", "PidTagGatewayNeedsToRefresh",
-                "PidTagWlinkType", "PidTagWlinkFlags",
-                "PidTagWlinkGroupClsid", "PidTagWlinkGroupName",
-                "PidTagWlinkGroupHeaderID",
-                "PidTagScheduleInfoDelegatorWantsCopy", "PidTagWlinkOrdinal",
-                "PidTagWlinkSection", "PidTagWlinkCalendarColor",
-                "PidTagWlinkAddressBookEID", "PidTagWlinkFolderType",
-                "PidTagScheduleInfoDelegateNames",
-                "PidTagScheduleInfoDelegateEntryIds", 
-                "PidTagBusiness2TelephoneNumbers",
-                "PidTagHome2TelephoneNumbers",
-                "PidTagAttachDataObject", "PidTagShorttermEntryIdFromObject",
-                ]
+bannedProps = set(["PidTagBodyHtml", "PidTagFavAutosubfolders",
+                   "PidTagAttachDataObj", "PidTagAclTable", "PidTagAclData",
+                   "PidTagRulesTable", "PidTagRulesData",
+                   "PidTagDisableWinsock",
+                   "PidTagHierarchyServer", "PidTagOfflineAddrbookEntryid",
+                   "PidTagShorttermEntryidFromObject",
+                   "PidTagNormalMessageSizeExtended",
+                   "PidTagAssocMessageSizeExtended",
+                   "PidTagMessageSizeExtended",
+                   "PidTagOabContainerGuid",
+                   "PidTagOfflineAddressBookMessageClass", "PidTagScriptData",
+                   "PidTagOfflineAddressBookTruncatedProperties",
+                   "PidTagOfflineAddressBookContainerGuid",
+                   "PidTagOfflineAddressBookDistinguishedName",
+                   "PidTagOfflineAddressBookShaHash",
+                   "PidTagSenderTelephoneNumber",
+                   "PidTagGatewayNeedsToRefresh",
+                   "PidTagWlinkType", "PidTagWlinkFlags",
+                   "PidTagWlinkGroupClsid", "PidTagWlinkGroupName",
+                   "PidTagWlinkGroupHeaderID",
+                   "PidTagScheduleInfoDelegatorWantsCopy",
+                   "PidTagWlinkOrdinal",
+                   "PidTagWlinkSection", "PidTagWlinkCalendarColor",
+                   "PidTagWlinkAddressBookEID", "PidTagWlinkFolderType",
+                   "PidTagScheduleInfoDelegateNames",
+                   "PidTagScheduleInfoDelegateEntryIds", 
+                   "PidTagBusiness2TelephoneNumbers",
+                   "PidTagHome2TelephoneNumbers",
+                   "PidTagAttachDataObject",
+                   "PidTagShorttermEntryIdFromObject",
+                   ])
 
 def ParseExchangeH(names, lines):
     state = 0
@@ -199,7 +204,7 @@
     return found
 
 def ProcessHeaders(names, hdict):
-    for filename in hdict.keys():
+    for filename in hdict:
         header_filename = FindHFile(filename)
         header_file = open(header_filename, "r")
         lines = header_file.readlines()
@@ -228,8 +233,8 @@
 
     names = {}
     ProcessHeaders(names,
-                   { "gen_ndr/exchange.h": ParseExchangeH,
-                     "mapistore/mapistore_nameid.h": ParseMapistoreNameIDH })
+                   {"gen_ndr/exchange.h": ParseExchangeH,
+                    "mapistore/mapistore_nameid.h": ParseMapistoreNameIDH})
 
     getters = []
     getters_idx = []
@@ -243,12 +248,10 @@
 
     prop_types = {}
     # sanitization: only take unicode version of text properties
-    all_keys = names.keys()
-    for name in all_keys:
-        prop_tag = names[name]
+    for name, prop_tag in names.iteritems():
         prop_id = prop_tag >> 16
         prop_type = prop_tag & 0xffff
-        if not prop_types.has_key(prop_id):
+        if not prop_id in prop_types:
             prop_types[prop_id] = []
         prop_types[prop_id].append(prop_type)
         if (prop_type & 0xfff) == 0x001e:
@@ -256,19 +259,15 @@
         names[name] = prop_tag
 
     #sanitization: report multiple types for the same keynames
-    all_keys = prop_types.keys()
-    for prop_id in all_keys:
-        xtypes = prop_types[prop_id]
+    for prop_id, xtypes in prop_types.iteritems():
         cnt = len(xtypes)
         if cnt > 1:
             print "%d types available for prop id 0x%.4x: %s" % (cnt, prop_id, ", ".join(["%.4x" % x for x in xtypes]))
 
     supported_properties = []
-    all_keys = names.keys()
     current_getter_idx = 0
     highest_prop_idx = 0
-    for name in all_keys:
-        prop_tag = names[name]
+    for name, prop_tag in names.iteritems():
         supported_properties.append("  0x%.8x" % prop_tag);
         prop_idx = (prop_tag & 0xffff0000) >> 16
         getters_idx[prop_idx] = "  0x%.4x" % current_getter_idx
@@ -285,14 +284,14 @@
     filename = "%s.m" % output
     h_filename = "%s.h" % output
     outf = open(filename, "wb+")
-    outf.write(m_template % { "getters_idx": ",\n".join(getters_idx),
-                              "getters": ",\n".join(getters),
-                              "nbr_getters": len(getters),
-                              "last_property": highest_prop_idx,
-                              "nbr_supported_properties": len(supported_properties),
-                              "supported_properties": ",\n".join(supported_properties),
-                              "filename": filename,
-                              "h_filename": h_filename })
+    outf.write(m_template % {"getters_idx": ",\n".join(getters_idx),
+                             "getters": ",\n".join(getters),
+                             "nbr_getters": len(getters),
+                             "last_property": highest_prop_idx,
+                             "nbr_supported_properties": len(supported_properties),
+                             "supported_properties": ",\n".join(supported_properties),
+                             "filename": filename,
+                             "h_filename": h_filename})
     outf.close()
 
     outf = open(h_filename, "wb+")
@@ -301,7 +300,7 @@
         if ord(x) < 65 or ord(x) > 90:
             x = "_"
         exclusion = exclusion + x
-    outf.write(h_template % { "prototypes": "\n".join(prototypes),
-                              "h_exclusion": exclusion,
-                              "filename": h_filename })
+    outf.write(h_template % {"prototypes": "\n".join(prototypes),
+                             "h_exclusion": exclusion,
+                             "filename": h_filename })
     outf.close()
diff -Nru sogo-1.3.15a/SOPE/NGCards/CardElement.h sogo-1.3.16/SOPE/NGCards/CardElement.h
--- sogo-1.3.15a/SOPE/NGCards/CardElement.h	2012-05-18 17:27:05.000000000 +0200
+++ sogo-1.3.16/SOPE/NGCards/CardElement.h	2012-06-07 17:40:40.000000000 +0200
@@ -106,17 +106,18 @@
 
 - (void) addType: (NSString *) aType;
 
+/* rendering */
 - (NSArray *) orderOfAttributeKeys;
 - (NSArray *) orderOfValueKeys;
-
 - (NSString *) versitString;
 
 - (CardGroup *) searchParentOfClass: (Class) parentClass;
 
+/* conversion */
 - (id) elementWithClass: (Class) elementClass;
 
+/* copy */
 - (void) setAttributesAsCopy: (NSMutableDictionary *) someAttributes;
-
 - (NSMutableArray *) deepCopyOfArray: (NSArray *) oldArray
 			    withZone: (NSZone *) aZone;
 - (NSMutableDictionary *) deepCopyOfDictionary: (NSDictionary *) oldDictionary
diff -Nru sogo-1.3.15a/SOPE/NGCards/CardGroup.m sogo-1.3.16/SOPE/NGCards/CardGroup.m
--- sogo-1.3.15a/SOPE/NGCards/CardGroup.m	2012-05-18 17:27:05.000000000 +0200
+++ sogo-1.3.16/SOPE/NGCards/CardGroup.m	2012-06-07 17:40:40.000000000 +0200
@@ -354,7 +354,7 @@
 
 - (void) setChildrenAsCopy: (NSMutableArray *) someChildren
 {
-  unsigned int count, max;
+  NSUInteger count, max;
 
   ASSIGN (children, someChildren);
 
@@ -399,7 +399,7 @@
 - (NSString *) description
 {
   NSMutableString *str;
-  unsigned int count, max;
+  NSUInteger count, max;
 
   str = [NSMutableString stringWithCapacity:64];
   [str appendFormat:@"<%p[%@]:%@",
@@ -421,7 +421,7 @@
 - (void) replaceThisElement: (CardElement *) oldElement
                 withThisOne: (CardElement *) newElement
 {
-  unsigned int index;
+  NSUInteger index;
 
   index = [children indexOfObject: oldElement];
   if (index != NSNotFound)
diff -Nru sogo-1.3.15a/SOPE/NGCards/ChangeLog sogo-1.3.16/SOPE/NGCards/ChangeLog
--- sogo-1.3.15a/SOPE/NGCards/ChangeLog	2012-05-18 17:27:05.000000000 +0200
+++ sogo-1.3.16/SOPE/NGCards/ChangeLog	2012-06-07 17:40:40.000000000 +0200
@@ -1,3 +1,17 @@
+2012-05-30  Francis Lachapelle  <flachapelle@inverse.ca>
+
+	* iCalRepeatableEntityObject.m (-exceptionDatesWithTimeZone:)
+	(-rules:withTimeZone:): exception dates and exception rules must
+	also be adjusted for floating all-day repeating events.
+
+2012-05-29  Francis Lachapelle  <flachapelle@inverse.ca>
+
+	* iCalRecurrenceCalculator.m
+	(_removeExceptionDatesFromRanges:withDates:withinRange:startingWithDate:):
+	when removing exception dates, avoid removing dates matching the
+	end date of the occurrence. This fixes an issue with all-day
+	daily events.
+
 2012-04-23  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
 
 	* iCalMonthlyRecurrenceCalculator.m (NGMonthDaySet_clear): make
diff -Nru sogo-1.3.15a/SOPE/NGCards/iCalRecurrenceCalculator.m sogo-1.3.16/SOPE/NGCards/iCalRecurrenceCalculator.m
--- sogo-1.3.15a/SOPE/NGCards/iCalRecurrenceCalculator.m	2012-05-18 17:27:08.000000000 +0200
+++ sogo-1.3.16/SOPE/NGCards/iCalRecurrenceCalculator.m	2012-06-07 17:40:41.000000000 +0200
@@ -189,6 +189,7 @@
   NSCalendarDate *currentDate;
   NGCalendarDateRange *currentRange;
   unsigned int count, maxRanges;
+  NSComparisonResult compare;
 
   dates = [[self _dates: exdates withinRange: limits] objectEnumerator];
   while ((currentDate = [dates nextObject]))
@@ -197,8 +198,12 @@
       for (count = maxRanges; count > 0; count--)
 	{
 	  currentRange = [ranges objectAtIndex: count - 1];
-	  if ([currentRange containsDate: currentDate])
-	    [ranges removeObjectAtIndex: count - 1];
+          compare = [[currentRange startDate] compare: currentDate];
+          if ((compare == NSOrderedAscending || compare == NSOrderedSame) &&
+              [[currentRange endDate] compare: currentDate] == NSOrderedDescending)
+            {
+              [ranges removeObjectAtIndex: count - 1];
+            }
 	}
     }
 }
diff -Nru sogo-1.3.15a/SOPE/NGCards/iCalRepeatableEntityObject.h sogo-1.3.16/SOPE/NGCards/iCalRepeatableEntityObject.h
--- sogo-1.3.15a/SOPE/NGCards/iCalRepeatableEntityObject.h	2012-05-18 17:27:08.000000000 +0200
+++ sogo-1.3.16/SOPE/NGCards/iCalRepeatableEntityObject.h	2012-06-07 17:40:41.000000000 +0200
@@ -42,25 +42,25 @@
 - (void)setRecurrenceRules:(NSArray *)_rrule;
 - (BOOL)hasRecurrenceRules;
 - (NSArray *)recurrenceRules;
-- (NSArray *)recurrenceRulesWithTimeZone: (iCalTimeZone *) timezone;
+- (NSArray *)recurrenceRulesWithTimeZone: (id) timezone;
 
 - (void)removeAllExceptionRules;
 - (void)addToExceptionRules:(id)_rrule;
 - (BOOL)hasExceptionRules;
 - (NSArray *)exceptionRules;
-- (NSArray *)exceptionRulesWithTimeZone: (iCalTimeZone *) timezone;
+- (NSArray *)exceptionRulesWithTimeZone: (id) timezone;
 
 - (void)removeAllExceptionDates;
 - (void)addToExceptionDates:(NSCalendarDate *)_date;
 - (BOOL)hasExceptionDates;
 - (NSArray *)exceptionDates;
-- (NSArray *)exceptionDatesWithTimeZone: (iCalTimeZone*) theTimeZone;
+- (NSArray *)exceptionDatesWithTimeZone: (id) theTimeZone;
 
-- (NSArray *) rules: (NSArray *) theRules withTimeZone: (iCalTimeZone *) theTimeZone;
+- (NSArray *) rules: (NSArray *) theRules withTimeZone: (id) theTimeZone;
 
 - (BOOL)isRecurrent;
 - (BOOL)isWithinCalendarDateRange:(NGCalendarDateRange *)_range
-  firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir;
+   firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir;
 - (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r
   firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir;
 
diff -Nru sogo-1.3.15a/SOPE/NGCards/iCalRepeatableEntityObject.m sogo-1.3.16/SOPE/NGCards/iCalRepeatableEntityObject.m
--- sogo-1.3.15a/SOPE/NGCards/iCalRepeatableEntityObject.m	2012-05-18 17:27:08.000000000 +0200
+++ sogo-1.3.16/SOPE/NGCards/iCalRepeatableEntityObject.m	2012-06-07 17:40:41.000000000 +0200
@@ -1,6 +1,6 @@
 /*
   Copyright (C) 2004-2005 SKYRIX Software AG
-  Copyright (C) 2011 Inverse inc.
+  Copyright (C) 2012 Inverse inc.
 
   This file is part of SOPE.
 
@@ -24,10 +24,12 @@
 #import <Foundation/NSCalendarDate.h>
 #import <Foundation/NSEnumerator.h>
 #import <Foundation/NSString.h>
+#import <Foundation/NSTimeZone.h>
 
 #import <NGExtensions/NGCalendarDateRange.h>
 
 #import "NSCalendarDate+NGCards.h"
+#import "NSString+NGCards.h"
 #import "iCalDateTime.h"
 #import "iCalEvent.h"
 #import "iCalTimeZone.h"
@@ -79,7 +81,7 @@
   return [self childrenWithTag: @"rrule"];
 }
 
-- (NSArray *) recurrenceRulesWithTimeZone: (iCalTimeZone *) timezone
+- (NSArray *) recurrenceRulesWithTimeZone: (id) timezone
 {
   NSArray *rules;
 
@@ -113,7 +115,7 @@
   return [self childrenWithTag: @"exrule"];
 }
 
-- (NSArray *) exceptionRulesWithTimeZone: (iCalTimeZone *) timezone
+- (NSArray *) exceptionRulesWithTimeZone: (id) timezone
 {
   NSArray *rules;
 
@@ -131,12 +133,13 @@
  * @see exceptionRulesWithTimeZone:
  * @return a new array of iCalRecurrenceRule instances, adjusted for the timezone.
  */
-- (NSArray *) rules: (NSArray *) theRules withTimeZone: (iCalTimeZone *) theTimeZone
+- (NSArray *) rules: (NSArray *) theRules withTimeZone: (id) theTimeZone
 {
   NSArray *rules;
   NSCalendarDate *untilDate;
   NSMutableArray *fixedRules;
   iCalRecurrenceRule *currentRule;
+  int offset;
   unsigned int max, count;
 
   rules = theRules;
@@ -152,7 +155,14 @@
 	      untilDate = [currentRule untilDate];
 	      if (untilDate)
 		{
-		  untilDate = [theTimeZone computedDateForDate: untilDate];
+                  if ([theTimeZone isKindOfClass: [iCalTimeZone class]])
+                    untilDate = [(iCalTimeZone *) theTimeZone computedDateForDate: untilDate];
+                  else
+                    {
+                      offset = [(NSTimeZone *) theTimeZone secondsFromGMTForDate: untilDate];
+                      untilDate = (NSCalendarDate *) [untilDate dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
+                                                                          seconds:-offset];
+                    }
 		  [currentRule setUntilDate: untilDate];
 		}
 	      [fixedRules addObject: currentRule];
@@ -232,12 +242,13 @@
  * @see [iCalTimeZone computedDatesForStrings:]
  * @return the exception dates, adjusted to the timezone.
  */
-- (NSArray *) exceptionDatesWithTimeZone: (iCalTimeZone *) theTimeZone
+- (NSArray *) exceptionDatesWithTimeZone: (id) theTimeZone
 {
   NSArray *dates, *exDates;
   NSEnumerator *dateList;
   NSCalendarDate *exDate;
   NSString *dateString;
+  int offset;
   unsigned i;
 
   if (theTimeZone)
@@ -251,9 +262,21 @@
 	  for (i = 0; i < [exDates count]; i++)
 	    {
 	      dateString = [exDates objectAtIndex: i];
-	      exDate = [theTimeZone computedDateForString: dateString];
+              if ([theTimeZone isKindOfClass: [iCalTimeZone class]])
+                {
+                  exDate = [(iCalTimeZone *) theTimeZone computedDateForString: dateString];
+                }
+              else
+                {
+                  // Example: timezone is -0400, date is 2012-05-24 (00:00:00 +0000),
+                  //                      and changes to 2012-05-24 04:00:00 +0000
+                  exDate = [dateString asCalendarDate];
+                  offset = [(NSTimeZone *) theTimeZone secondsFromGMTForDate: exDate];
+                  exDate = (NSCalendarDate *) [exDate dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
+                                                               seconds:-offset];
+                }
 	      [(NSMutableArray *) dates addObject: exDate];
-	    }
+   	    }
 	}
     }
   else
diff -Nru sogo-1.3.15a/SOPE/NGCards/iCalTimeZone.m sogo-1.3.16/SOPE/NGCards/iCalTimeZone.m
--- sogo-1.3.15a/SOPE/NGCards/iCalTimeZone.m	2012-05-18 17:27:08.000000000 +0200
+++ sogo-1.3.16/SOPE/NGCards/iCalTimeZone.m	2012-06-07 17:40:41.000000000 +0200
@@ -270,6 +270,8 @@
 
 /**
  * Adjust a date with respect to this vTimeZone.
+ * Example: Timezone is -0400, the date is 2012-05-23 13:00:00 +0000:
+ *                              it returns 2012-05-23 09:00:00 +0000
  * @param theDate the string representing a date.
  * @return a new GMT date adjusted with the offset of this timezone.
  */
diff -Nru sogo-1.3.15a/Scripts/sogo-init.d-redhat sogo-1.3.16/Scripts/sogo-init.d-redhat
--- sogo-1.3.15a/Scripts/sogo-init.d-redhat	2012-05-18 17:27:08.000000000 +0200
+++ sogo-1.3.16/Scripts/sogo-init.d-redhat	2012-06-07 17:40:41.000000000 +0200
@@ -146,12 +146,17 @@
   restart)
 	restart
 	;;
+  condrestart|try-restart)
+	if status -p "$PIDFILE" $DAEMON >&/dev/null; then
+	  restart
+	fi
+	;;
   status)
   	status -p "$PIDFILE" $DAEMON
 	;;
   *)
 	N=/etc/init.d/$NAME
-	echo "Usage: $N {start|stop|restart|status}" >&2
+	echo "Usage: $N {start|stop|restart|condrestart|status}" >&2
 	exit 1
 	;;
 esac
diff -Nru sogo-1.3.15a/Scripts/sogo-init.d-sles sogo-1.3.16/Scripts/sogo-init.d-sles
--- sogo-1.3.15a/Scripts/sogo-init.d-sles	2012-05-18 17:27:08.000000000 +0200
+++ sogo-1.3.16/Scripts/sogo-init.d-sles	2012-06-07 17:40:41.000000000 +0200
@@ -96,6 +96,11 @@
 	startproc -u $USER $DAEMON $DAEMON_OPTS || true
 	echo "$NAME."
 	;;
+  condrestart|try-restart)
+	if checkproc -p "$PIDFILE" $DAEMON >&/dev/null; then
+	  restart
+	fi
+	;;
   status)
 	checkproc -p $PIDFILE $DAEMON
         result="$?"
@@ -115,7 +120,7 @@
 	fi
 	;;
   *)
-	echo "Usage: $NAME {start|stop|restart|status}" >&2
+	echo "Usage: $NAME {start|stop|restart|condrestart|status}" >&2
 	exit 1
 	;;
 esac
diff -Nru sogo-1.3.15a/SoObjects/Appointments/French.lproj/Localizable.strings sogo-1.3.16/SoObjects/Appointments/French.lproj/Localizable.strings
--- sogo-1.3.15a/SoObjects/Appointments/French.lproj/Localizable.strings	2012-05-18 17:27:08.000000000 +0200
+++ sogo-1.3.16/SoObjects/Appointments/French.lproj/Localizable.strings	2012-06-07 17:40:41.000000000 +0200
@@ -67,5 +67,4 @@
 = "%{Attendee} %{SentByText}choisit de reporter sa décision par rapport à votre invitation.";
 
 /* Resources */
-"Cannot access resource: \"%{Cn} %{SystemEmail}\"" = "Impossible d'accéder à la resource: \"%{Cn} %{SystemEmail}\"";
-"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Le nombre maximum (%{NumberOfSimultaneousBookings}) de réservation(s) simultanée(s) a été atteint pour la ressource \"%{Cn} %{SystemEmail}\".";
+"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "Le nombre maximal de réservations simultanées (%{NumberOfSimultaneousBookings}) est atteint pour la ressource «%{Cn} %{SystemEmail}». L'événement en conflit est «%{EventTitle}» et débute le %{StartDate}.";
\ No newline at end of file
diff -Nru sogo-1.3.15a/SoObjects/Appointments/SOGoAppointmentFolder.m sogo-1.3.16/SoObjects/Appointments/SOGoAppointmentFolder.m
--- sogo-1.3.15a/SoObjects/Appointments/SOGoAppointmentFolder.m	2012-05-18 17:27:09.000000000 +0200
+++ sogo-1.3.16/SoObjects/Appointments/SOGoAppointmentFolder.m	2012-06-07 17:40:41.000000000 +0200
@@ -744,7 +744,7 @@
     {
       currentRecord = [recordArray objectAtIndex: count];
       if ([[currentRecord objectForKey: @"startDate"]
-	    isEqual: matchDate])
+	    compare: matchDate] == NSOrderedSame)
 	recordIndex = count;
       else
 	count++;
@@ -773,18 +773,32 @@
 firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
 		       fromRow: (NSDictionary *) row
 		      forRange: (NGCalendarDateRange *) dateRange
+                  withTimeZone: (NSTimeZone *) tz
 		       toArray: (NSMutableArray *) ma
 {
   NSCalendarDate *startDate, *recurrenceId;
   NSMutableDictionary *newRecord;
   NSDictionary *oldRecord;
   NGCalendarDateRange *newRecordRange;
-  int recordIndex;
+  NSComparisonResult compare;
+  int recordIndex, secondsOffsetFromGMT;
 
   newRecord = nil;
   recurrenceId = [component recurrenceId];
   
-  if ([dateRange containsDate: recurrenceId])
+  if (tz)
+    {
+      // The following adjustment is necessary for floating all-day events.
+      // For example, the recurrence-id 20120523T000000Z for timezone -0400
+      // will become 20120523T000400Z
+      secondsOffsetFromGMT = [tz secondsFromGMTForDate: recurrenceId];
+      recurrenceId = (NSCalendarDate *) [recurrenceId dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
+                                                                seconds:-secondsOffsetFromGMT];
+    }
+
+  compare = [[dateRange startDate] compare: recurrenceId];
+  if ((compare == NSOrderedAscending || compare == NSOrderedSame) &&
+      [[dateRange endDate] compare: recurrenceId] == NSOrderedDescending)
     {
       recordIndex = [self _indexOfRecordMatchingDate: recurrenceId
 					     inArray: ma];
@@ -799,7 +813,9 @@
 	      oldRecord = [ma objectAtIndex: recordIndex];
 	      [newRecord setObject: [oldRecord objectForKey: @"c_recurrence_id"]
 			    forKey: @"c_recurrence_id"];
-	      
+//              [newRecord setObject: [NSNumber numberWithInt: [recurrenceId timeIntervalSince1970]]
+//			    forKey: @"c_recurrence_id"];
+
 	      // The first instance date is added to the dictionary so it can
 	      // be used by UIxCalListingActions to compute the DST offset.
 	      [newRecord setObject: [fir startDate] forKey: @"cycleStartDate"];
@@ -838,6 +854,7 @@
 - (void) _appendCycleExceptionsFromRow: (NSDictionary *) row
         firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
 			      forRange: (NGCalendarDateRange *) dateRange
+                          withTimeZone: (NSTimeZone *) tz
 			       toArray: (NSMutableArray *) ma
 {
   NSArray *elements, *components;
@@ -859,6 +876,7 @@
 		  firstInstanceCalendarDateRange: fir
 				fromRow: row
 			       forRange: dateRange
+                           withTimeZone: tz
 				toArray: ma];
 	}
     }
@@ -877,20 +895,19 @@
                    intoArray: (NSMutableArray *) theRecords
 {
   NSMutableDictionary *row, *fixedRow;
-  NSMutableArray *records, *newExDates;
+  NSMutableArray *records;
   NSDictionary *cycleinfo;
-  NSEnumerator *exDatesList;
   NGCalendarDateRange *firstRange, *recurrenceRange, *oneRange;
   NSArray *rules, *exRules, *exDates, *ranges;
   NSArray *elements, *components;
   NSString *content;
-  NSCalendarDate *checkStartDate, *checkEndDate, *firstStartDate,
-                    *firstEndDate;
+  NSCalendarDate *checkStartDate, *checkEndDate, *firstStartDate, *firstEndDate;
+  NSTimeZone *allDayTimeZone;
   iCalDateTime *dtstart;
   iCalEvent *component;
   iCalTimeZone *eventTimeZone;
   unsigned count, max, offset;
-  id exDate;
+  id tz;
 
   content = [theRecord objectForKey: @"c_cycleinfo"];
   if (![content isNotNull])
@@ -910,7 +927,8 @@
   rules = [cycleinfo objectForKey: @"rules"];
   exRules = [cycleinfo objectForKey: @"exRules"];
   exDates = [cycleinfo objectForKey: @"exDates"];
-  
+  eventTimeZone = allDayTimeZone = tz = nil;
+
   row = [self fixupRecord: theRecord];
   [row removeObjectForKey: @"c_cycleinfo"];
   [row setObject: sharedYes forKey: @"isRecurrentEvent"];
@@ -945,12 +963,6 @@
                   recurrenceRange = [NGCalendarDateRange calendarDateRangeWithStartDate: checkStartDate
                                                                                 endDate: checkEndDate];
                   
-                  // Adjust the exception dates
-                  exDates = [eventTimeZone computedDatesForStrings: exDates];
-                  
-                  // Adjust the recurrence rules "until" dates
-                  rules = [component recurrenceRulesWithTimeZone: eventTimeZone];
-                  exRules = [component exceptionRulesWithTimeZone: eventTimeZone];
                 }
               else 
                 {
@@ -959,29 +971,30 @@
                     {
                       // The event lasts all-day and has no timezone (floating); we convert the range of the first event
                       // to the user's timezone
-                      offset = [timeZone secondsFromGMTForDate: [firstRange startDate]];
+                      allDayTimeZone = timeZone;
+                      offset = [allDayTimeZone secondsFromGMTForDate: [firstRange startDate]];
                       firstStartDate = [[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
                                                                          seconds:-offset];
                       firstEndDate = [[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
                                                                      seconds:-offset];
-                      [firstStartDate setTimeZone: timeZone];
-                      [firstEndDate setTimeZone: timeZone];
+                      [firstStartDate setTimeZone: allDayTimeZone];
+                      [firstEndDate setTimeZone: allDayTimeZone];
                       firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate
                                                                                endDate: firstEndDate];
-        
-                      // Adjust the exception dates
-                      exDatesList = [exDates objectEnumerator];
-                      newExDates = [NSMutableArray arrayWithCapacity: [exDates count]];
-                      while ((exDate = [exDatesList nextObject]))
-                        {
-                          exDate = [[exDate asCalendarDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
-                                                                      seconds:-offset];
-                          [newExDates addObject: exDate];
-                        }
-                      exDates = newExDates;
                     }
                 }
-              
+
+              tz = eventTimeZone? eventTimeZone : allDayTimeZone;
+              if (tz)
+                {
+                  // Adjust the exception dates
+                  exDates = [component exceptionDatesWithTimeZone: tz];
+                  
+                  // Adjust the recurrence rules "until" dates
+                  rules = [component recurrenceRulesWithTimeZone: tz];
+                  exRules = [component exceptionRulesWithTimeZone: tz];
+                }
+
               // Calculate the occurrences for the given range
               records = [NSMutableArray array];
               ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: recurrenceRange
@@ -1004,6 +1017,7 @@
               [self _appendCycleExceptionsFromRow: row
                    firstInstanceCalendarDateRange: firstRange
                                          forRange: theRange
+                                     withTimeZone: allDayTimeZone
                                           toArray: records];
               
               [theRecords addObjectsFromArray: records];
diff -Nru sogo-1.3.15a/SoObjects/Appointments/SOGoCalendarComponent.m sogo-1.3.16/SoObjects/Appointments/SOGoCalendarComponent.m
--- sogo-1.3.15a/SoObjects/Appointments/SOGoCalendarComponent.m	2012-05-18 17:27:09.000000000 +0200
+++ sogo-1.3.16/SoObjects/Appointments/SOGoCalendarComponent.m	2012-06-07 17:40:41.000000000 +0200
@@ -399,8 +399,8 @@
 	  recID = [lookupName substringFromIndex: 9];
 	  occurence = [self lookupOccurence: recID];
 	  if (occurence)
-	    isNewOccurence = NO;
-	  else
+            isNewOccurence = NO;
+          else
 	    {
 	      occurence = [self newOccurenceWithID: recID];
 	      isNewOccurence = YES;
diff -Nru sogo-1.3.15a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m sogo-1.3.16/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m
--- sogo-1.3.15a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m	2012-05-18 17:27:09.000000000 +0200
+++ sogo-1.3.16/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m	2012-06-07 17:40:41.000000000 +0200
@@ -125,9 +125,7 @@
   NSArray *ranges;
   NGCalendarDateRange *checkRange, *firstRange;
   NSCalendarDate *startDate, *endDate;
-  NSTimeZone *timeZone;
-  id firstStartDate, firstEndDate;
-  iCalTimeZone *eventTimeZone;
+  id firstStartDate, firstEndDate, timeZone;
   BOOL doesOccur;
   int offset;
 
@@ -139,9 +137,11 @@
 
       // Set the range to check with respect to the event timezone (extracted from the start date)
       firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"];
-      eventTimeZone = [(iCalDateTime *)firstStartDate timeZone];
-      if (eventTimeZone)
-	startDate = [eventTimeZone computedDateForDate: theOccurenceDate];
+      timeZone = [(iCalDateTime *)firstStartDate timeZone];
+      if (timeZone)
+        {
+          startDate = [(iCalTimeZone *)timeZone computedDateForDate: theOccurenceDate];
+        }
       else
 	{
 	  startDate = theOccurenceDate;
@@ -150,13 +150,14 @@
 	      // The event lasts all-day and has no timezone (floating); we convert the range of the first event
 	      // to the occurence's timezone.
 	      timeZone = [theOccurenceDate timeZone];
-	      offset = [timeZone secondsFromGMTForDate: [firstRange startDate]];
+	      offset = [(NSTimeZone *)timeZone secondsFromGMTForDate: [firstRange startDate]];
 	      firstStartDate = (NSCalendarDate *)[[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
 										   seconds:-offset];
 	      firstEndDate = (NSCalendarDate *)[[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0
 									       seconds:-offset];
 	      [(NSCalendarDate *)firstStartDate setTimeZone: timeZone];
 	      [(NSCalendarDate *)firstEndDate setTimeZone: timeZone];
+
 	      firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate
 								       endDate: firstEndDate];
 	    }
@@ -168,9 +169,9 @@
       // Calculate the occurrences for the given date
       ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: checkRange
 						  firstInstanceCalendarDateRange: firstRange
-								 recurrenceRules: [self recurrenceRulesWithTimeZone: eventTimeZone]
-								  exceptionRules: [self exceptionRulesWithTimeZone: eventTimeZone]
-								  exceptionDates: [self exceptionDatesWithTimeZone: eventTimeZone]];
+								 recurrenceRules: [self recurrenceRulesWithTimeZone: timeZone]
+								  exceptionRules: [self exceptionRulesWithTimeZone: timeZone]
+								  exceptionDates: [self exceptionDatesWithTimeZone: timeZone]];
       doesOccur = [ranges dateRangeArrayContainsDate: startDate];
     }
 
diff -Nru sogo-1.3.15a/SoObjects/Mailer/SOGoMailFolder.m sogo-1.3.16/SoObjects/Mailer/SOGoMailFolder.m
--- sogo-1.3.15a/SoObjects/Mailer/SOGoMailFolder.m	2012-05-18 17:27:09.000000000 +0200
+++ sogo-1.3.16/SoObjects/Mailer/SOGoMailFolder.m	2012-06-07 17:40:41.000000000 +0200
@@ -1216,6 +1216,17 @@
   [mailboxACL release];
 
   mailboxACL = [[self imap4Connection] aclForMailboxAtURL: [self imap4URL]];
+
+  // If the mailbox doesn't exist, we create it. That could happen if
+  // a special mailbox (Drafts, Sent, Trash) is deleted from SOGo's web GUI
+  // or if any other mailbox is deleted behind SOGo's back.
+  if ([mailboxACL isKindOfClass: [NSException class]])
+    {
+      [[self imap4Connection] createMailbox: [[self imap4Connection] imap4FolderNameForURL: [self imap4URL]]
+				      atURL: [[self mailAccountFolder] imap4URL]];
+      mailboxACL = [[self imap4Connection] aclForMailboxAtURL: [self imap4URL]];
+    }
+
   [mailboxACL retain];
 
   [self _convertIMAPGroupnames];
diff -Nru sogo-1.3.15a/SoObjects/Mailer/SOGoMailObject+Draft.m sogo-1.3.16/SoObjects/Mailer/SOGoMailObject+Draft.m
--- sogo-1.3.15a/SoObjects/Mailer/SOGoMailObject+Draft.m	2012-05-18 17:27:10.000000000 +0200
+++ sogo-1.3.16/SoObjects/Mailer/SOGoMailObject+Draft.m	2012-06-07 17:40:41.000000000 +0200
@@ -53,12 +53,14 @@
     nil
   };
   BOOL hasPrefix;
-  unsigned int i;
+  NSUInteger i;
   NSString *subject, *newSubject;
 
   hasPrefix = NO;
 
   subject = [self decodedSubject];
+  if (![subject length]) subject = @"";
+
   i = 0;
   while (!hasPrefix && replyPrefixes[i])
     if ([subject hasPrefix: replyPrefixes[i]])
@@ -99,7 +101,7 @@
   NSDictionary *parts;
   NSString *rawPart, *content, *contentKey;
   SOGoUserDefaults *ud;
-  int index;
+  NSUInteger index;
   BOOL htmlComposition, htmlContent;
 
   content = @"";
@@ -189,7 +191,7 @@
   static NSString *sescape[] = { 
     @"/", @"..", @"~", @"\"", @"'", @" ", @".", nil 
   };
-  unsigned int count, length;
+  NSUInteger count, length;
 
   subject = [self decodedSubject];
   length = [subject length];
@@ -298,7 +300,7 @@
   NSString *newPath;
   NSArray *subparts;
   NSString *type;
-  unsigned int i;
+  NSUInteger i;
 
   type = [[part objectForKey: @"type"] lowercaseString];
   if ([type isEqualToString: @"multipart"])
diff -Nru sogo-1.3.15a/SoObjects/SOGo/GNUmakefile sogo-1.3.16/SoObjects/SOGo/GNUmakefile
--- sogo-1.3.15a/SoObjects/SOGo/GNUmakefile	2012-05-18 17:27:10.000000000 +0200
+++ sogo-1.3.16/SoObjects/SOGo/GNUmakefile	2012-06-07 17:40:41.000000000 +0200
@@ -46,6 +46,8 @@
 	NSObject+Utilities.h		\
 	NSString+DAV.h			\
 	NSString+Utilities.h		\
+	NSString+Crypto.h		\
+	NSData+Crypto.h			\
 	NSURL+DAV.h			\
 	\
 	SOGoAuthenticator.h		\
@@ -114,6 +116,8 @@
 	NSObject+Utilities.m		\
 	NSString+DAV.m  		\
 	NSString+Utilities.m		\
+	NSString+Crypto.m		\
+	NSData+Crypto.m			\
 	NSURL+DAV.m	  		\
 	\
 	SOGoSession.m			\
diff -Nru sogo-1.3.15a/SoObjects/SOGo/LDAPSource.m sogo-1.3.16/SoObjects/SOGo/LDAPSource.m
--- sogo-1.3.15a/SoObjects/SOGo/LDAPSource.m	2012-05-18 17:27:10.000000000 +0200
+++ sogo-1.3.16/SoObjects/SOGo/LDAPSource.m	2012-06-07 17:40:41.000000000 +0200
@@ -40,6 +40,7 @@
 #import "LDAPSourceSchema.h"
 #import "NSArray+Utilities.h"
 #import "NSString+Utilities.h"
+#import "NSString+Crypto.h"
 #import "SOGoDomainDefaults.h"
 #import "SOGoSystemDefaults.h"
 
@@ -52,64 +53,6 @@
                                  stringByReplacingString: @"'" withString: @"\\'"] \
                                  stringByReplacingString: @"%" withString: @"%%"]
 
-@interface NGLdapAttribute (SOGoLDAP)
-
-- (id) _asArrayOrString;
-
-@end
-
-@implementation NGLdapAttribute (SOGoLDAP)
-
-- (id) _asArrayOrString
-{
-  id value;
-  NSArray *arrayValue;
-
-  arrayValue = [self allStringValues];
-  if ([arrayValue count] == 1)
-    value = [arrayValue objectAtIndex: 0];
-  else
-    value = arrayValue;
-
-  return value;
-}
-
-@end
-
-@interface NGLdapEntry (SOGoLDAP)
-
-- (NSMutableDictionary *) _asDictionary;
-
-@end
-
-@implementation NGLdapEntry (SOGoLDAP)
-
-- (NSMutableDictionary *) _asDictionary
-{
-  NSMutableDictionary *ldapRecord;
-  NSDictionary *ldapAttributes;
-  NSArray *keys;
-  NSString *key;
-  NSUInteger count, max;
-  id value;
-  
-  ldapAttributes = [self attributes];
-  keys = [ldapAttributes allKeys];
-  max = [keys count];
-
-  ldapRecord = [NSMutableDictionary dictionaryWithCapacity: max];
-  for (count = 0; count < max; count++)
-    {
-      key = [keys objectAtIndex: count];
-      value = [[ldapAttributes objectForKey: key] _asArrayOrString];
-      if (value)
-        [ldapRecord setObject: value forKey: [key lowercaseString]];
-    }
-
-  return ldapRecord;
-}
-
-@end
 
 @implementation LDAPSource
 
@@ -639,26 +582,13 @@
  */
 - (NSString *) _encryptPassword: (NSString *) plainPassword
 {
-  if ([_userPasswordAlgorithm caseInsensitiveCompare: @"none"] == NSOrderedSame)
-    {
-      return plainPassword;
-    }
-  else if ([_userPasswordAlgorithm caseInsensitiveCompare: @"crypt"] == NSOrderedSame)
-    {
-      return [NSString stringWithFormat: @"{CRYPT}%@", [plainPassword asCryptStringUsingSalt: [plainPassword asMD5String]]];
-    }
-  else if ([_userPasswordAlgorithm caseInsensitiveCompare: @"md5"] == NSOrderedSame)
-    {
-      return [NSString stringWithFormat: @"{MD5}%@", [plainPassword asMD5String]];
-    }
-  else if ([_userPasswordAlgorithm caseInsensitiveCompare: @"sha"] == NSOrderedSame)
-    {
-      return [NSString stringWithFormat: @"{SHA}%@", [plainPassword asSHA1String]];
-    }
-  
-  [self errorWithFormat: @"Unsupported user-password algorithm: %@", _userPasswordAlgorithm];
-  
-  return plainPassword;
+  NSString *pass;
+  pass = [plainPassword asCryptedPassUsingScheme: _userPasswordAlgorithm];
+
+  if (pass == nil)
+    [self errorWithFormat: @"Unsupported user-password algorithm: %@", _userPasswordAlgorithm];
+
+  return [NSString stringWithFormat: @"{%@}%@", _userPasswordAlgorithm, pass];
 }
 
 //
@@ -1018,7 +948,7 @@
     resourceKinds = [[NSArray alloc] initWithObjects: @"location", @"thing",
                                      @"group", nil];
 
-  ldifRecord = [ldapEntry _asDictionary];
+  ldifRecord = [ldapEntry asDictionary];
   [ldifRecord setObject: self forKey: @"source"];
   [ldifRecord setObject: [ldapEntry dn] forKey: @"dn"];
   
@@ -1645,7 +1575,7 @@
           modifier = [NSArray arrayWithObject: user];
           while ((entry = [entries nextObject]))
             {
-              sourceRec = [entry _asDictionary];
+              sourceRec = [entry asDictionary];
               ab = [LDAPSource new];
               [ab setSourceID: [sourceRec objectForKey: @"ou"]];
               [ab setDisplayName: [sourceRec objectForKey: @"description"]];
diff -Nru sogo-1.3.15a/SoObjects/SOGo/NSData+Crypto.h sogo-1.3.16/SoObjects/SOGo/NSData+Crypto.h
--- sogo-1.3.15a/SoObjects/SOGo/NSData+Crypto.h	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/SoObjects/SOGo/NSData+Crypto.h	2012-06-07 17:40:41.000000000 +0200
@@ -0,0 +1,61 @@
+/* NSData+Crypto.h - this file is part of SOGo
+ *
+ * Copyright (C) 2012 Nicolas Höft
+ * Copyright (C) 2012 Inverse inc.
+ *
+ * Author: Nicolas Höft
+ *         Inverse inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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.
+ */
+
+#ifndef NSDATA_CRYPTO_H
+#define NSDATA_CRYPTO_H
+
+#import <Foundation/NSData.h>
+
+@class NSObject;
+
+@interface NSData (SOGoCryptoExtension)
+
+- (NSData *) asCryptedPassUsingScheme: (NSString *) passwordScheme
+                               withSalt: (NSData *) theSalt;
+
+- (NSData *) asMD5;
+- (NSData *) asSMD5UsingSalt: (NSData *) theSalt;
+- (NSData *) asSHA1;
+- (NSData *) asSSHAUsingSalt: (NSData *) theSalt;
+- (NSData *) asSHA256;
+- (NSData *) asSSHA256UsingSalt: (NSData *) theSalt;
+- (NSData *) asSHA512;
+- (NSData *) asSSHA512UsingSalt: (NSData *) theSalt;
+- (NSData *) asCramMD5;
+
+- (NSData *) asCryptUsingSalt: (NSData *) theSalt;
+- (NSData *) asMD5CryptUsingSalt: (NSData *) theSalt;
+
+- (NSData *) extractSalt: (NSString *) theScheme;
+
++ (NSData *) generateSaltForLength: (unsigned int) theLength
+                        withBase64: (BOOL) doBase64;
++ (NSData *) generateSaltForLength: (unsigned int) theLength;
+
++ (NSString *) encodeDataAsHexString: (NSData* ) theData;
++ (NSData *) decodeDataFromHexString: (NSString* ) theString;
+
+@end
+
+#endif /* NSDATA_CRYPTO_H */
diff -Nru sogo-1.3.15a/SoObjects/SOGo/NSData+Crypto.m sogo-1.3.16/SoObjects/SOGo/NSData+Crypto.m
--- sogo-1.3.15a/SoObjects/SOGo/NSData+Crypto.m	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/SoObjects/SOGo/NSData+Crypto.m	2012-06-07 17:40:41.000000000 +0200
@@ -0,0 +1,620 @@
+/* NSData+Crypto.m - this file is part of SOGo
+ *
+ * Copyright (C) 2012 Nicolas Höft
+ * Copyright (C) 2012 Inverse inc.
+ *
+ * Author: Nicolas Höft
+ *         Inverse inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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.
+ */
+
+#ifndef __OpenBSD__
+#include <crypt.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define _XOPEN_SOURCE 1
+#include <unistd.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+
+#import <Foundation/NSArray.h>
+#import <NGExtensions/NGBase64Coding.h>
+#import "NSData+Crypto.h"
+
+unsigned charTo4Bits(char c);
+
+
+@implementation NSData (SOGoCryptoExtension)
+
+/**
+ * Covert binary data to hex encoded data (lower-case).
+ *
+ * @param theData The NSData to be converted into a hex-encoded string.
+ * @return Hex-Encoded data
+ */
++ (NSString *) encodeDataAsHexString: (NSData *) theData
+{
+  unsigned int byteLength = [theData length], byteCounter = 0;
+  unsigned int stringLength = (byteLength * 2) + 1, stringCounter = 0;
+  unsigned char dstBuffer[stringLength];
+  unsigned char srcBuffer[byteLength];
+  unsigned char *srcPtr = srcBuffer;
+  [theData getBytes: srcBuffer];
+  const unsigned char t[16] = "0123456789abcdef";
+
+  for (; byteCounter < byteLength; byteCounter++)
+    {
+      unsigned src = *srcPtr;
+      dstBuffer[stringCounter++] = t[src >> 4];
+      dstBuffer[stringCounter++] = t[src & 15];
+      srcPtr++;
+    }
+
+  dstBuffer[stringCounter] = '\0';
+  return [NSString stringWithUTF8String: (char*)dstBuffer];
+}
+
+/**
+ * Covert hex-encoded data to binary data.
+ *
+ * @param theString The hex-encoded string to be converted into binary data (works both for upper and lowe case characters)
+ * @return binary data or nil if unsuccessful
+ */
++ (NSData *) decodeDataFromHexString: (NSString *) theString
+{
+  unsigned int stringLength = [theString length];
+  unsigned int byteLength = stringLength/2;
+  unsigned int byteCounter = 0;
+  unsigned char srcBuffer[stringLength];
+  [theString getCString:(char *)srcBuffer];
+  unsigned char *srcPtr = srcBuffer;
+  unsigned char dstBuffer[byteLength];
+  unsigned char *dst = dstBuffer;
+  while (byteCounter < byteLength)
+    {
+      unsigned char c = *srcPtr++;
+      unsigned char d = *srcPtr++;
+      unsigned hi = 0, lo = 0;
+      hi = charTo4Bits(c);
+      lo = charTo4Bits(d);
+      if (hi == 255 || lo == 255)
+        {
+          //errorCase
+          return nil;
+        }
+      dstBuffer[byteCounter++] = ((hi << 4) | lo);
+    }
+  return [NSData dataWithBytes: dst length: byteLength];
+}
+
+/**
+ * Generate a binary key which can be used for salting hashes.
+ *
+ * @param theLength length of the binary data to be generated in bytes
+ * @return Pseudo-random binary data with length theLength or nil, if an error occured
+ */
++ (NSData *) generateSaltForLength: (unsigned int) theLength
+{
+  return [NSData generateSaltForLength: theLength withBase64: NO];
+}
+
+/**
+ * Generate a binary key which can be used for salting hashes. When using
+ * with doBase64 == YES then the data will be longer than theLength
+ *
+ * @param theLength Length of the binary data to be generated in bytes
+ * @param doBase64 Convert the data into Base-64 before retuning it, be aware that this makes the binary data longer
+ * @return Pseudo-random binary data with length theLength or nil, if an error occured
+ */
++ (NSData *) generateSaltForLength: (unsigned int) theLength
+                withBase64: (BOOL) doBase64
+{
+  char *buf;
+  int fd;
+  NSData *data;
+
+  fd = open("/dev/urandom", O_RDONLY);
+
+  if (fd > 0)
+    {
+      buf = (char *)malloc(theLength);
+      read(fd, buf, theLength);
+      close(fd);
+
+      data = [NSData dataWithBytesNoCopy: buf  length: theLength  freeWhenDone: YES];
+      if(doBase64 == YES)
+        {
+          return [data dataByEncodingBase64WithLineLength: 1024];
+        }
+      return data;
+    }
+  return nil;
+}
+
+/**
+ * Encrypt/Hash the data with a given scheme
+ *
+ * @param passwordScheme The scheme to use for hashing/encryption.
+ * @param theSalt The salt to be used. If none is given but needed, it will be generated
+ * @return Binary data from the encryption by the specified scheme. On error the funciton returns nil.
+ */
+- (NSData *) asCryptedPassUsingScheme: (NSString *) passwordScheme
+                               withSalt: (NSData *) theSalt
+{
+  if ([passwordScheme caseInsensitiveCompare: @"none"] == NSOrderedSame ||
+      [passwordScheme caseInsensitiveCompare: @"plain"] == NSOrderedSame ||
+      [passwordScheme caseInsensitiveCompare: @"cleartext"] == NSOrderedSame)
+    {
+      return self;
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"crypt"] == NSOrderedSame)
+    {
+      return [self asCryptUsingSalt: theSalt];
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"md5-crypt"] == NSOrderedSame)
+    {
+      return [self asMD5CryptUsingSalt: theSalt];
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"md5"] == NSOrderedSame ||
+           [passwordScheme caseInsensitiveCompare: @"plain-md5"] == NSOrderedSame ||
+           [passwordScheme caseInsensitiveCompare: @"ldap-md5"] == NSOrderedSame)
+    {
+      return [self asMD5];
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"cram-md5"] == NSOrderedSame)
+    {
+      return [self asCramMD5];
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"smd5"] == NSOrderedSame)
+    {
+      return [self asSMD5UsingSalt: theSalt];
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"sha"] == NSOrderedSame)
+    {
+      return [self asSHA1];
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"ssha"] == NSOrderedSame)
+    {
+      return [self asSSHAUsingSalt: theSalt];
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"sha256"] == NSOrderedSame)
+    {
+      return [self asSHA256];
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"ssha256"] == NSOrderedSame)
+    {
+      return [self asSSHA256UsingSalt: theSalt];
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"sha512"] == NSOrderedSame)
+    {
+      return [self asSHA512];
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"ssha512"] == NSOrderedSame)
+    {
+      return [self asSSHA512UsingSalt: theSalt];
+    }
+  // in case the scheme was not detected, return nil
+  return nil;
+}
+
+
+/**
+ * Hash the data with MD5. Uses openssl functions to generate it
+ *
+ * @return Binary data from MD5 hashing. On error the funciton returns nil.
+ */
+- (NSData *) asMD5
+{
+  unsigned char md5[MD5_DIGEST_LENGTH];
+  memset(md5, 0, MD5_DIGEST_LENGTH);
+
+  MD5([self bytes], [self length], md5);
+
+  return [NSData dataWithBytes: md5  length: MD5_DIGEST_LENGTH];
+}
+
+/**
+ * Hash the data with CRAM-MD5. Uses openssl functions to generate it.
+ *
+ * Note that the actual CRAM-MD5 algorithm also needs a challenge
+ * but this is not provided, this function actually calculalates
+ * only the context data which can be used for the challange-response
+ * algorithm then. This is just the underlying algorithm to store the passwords.
+ *
+ * The code is adopts the dovecot behaviour of storing the passwords
+ *
+ * @return Binary data from CRAM-MD5 'hashing'. On error the funciton returns nil.
+ */
+- (NSData *) asCramMD5
+{
+  
+  MD5_CTX ctx;
+  unsigned char inner[64];
+  unsigned char outer[64];
+  unsigned char result[32];
+  unsigned char *r;
+  int i;
+  int len;
+  NSData *key;
+  
+  if ([self length] > 64)
+    {
+      key = [self asMD5];
+    }
+  else
+    {
+      key = self;
+    }
+
+  len = [key length];
+  // fill with both inner and outer with key
+  memcpy(inner, [key bytes], len);
+  // make sure the rest of the bytes is zero
+  memset(inner + len, 0, 64 - len);
+  memcpy(outer, inner, 64);
+  
+  for (i = 0; i < 64; i++)
+    {
+      inner[i] ^= 0x36;
+      outer[i] ^= 0x5c;
+    }
+// this transformation is needed for the correct cast to binary data
+#define CDPUT(p, c) {   \
+    *p = (c) & 0xff; p++;       \
+    *p = (c) >> 8 & 0xff; p++;  \
+    *p = (c) >> 16 & 0xff; p++; \
+    *p = (c) >> 24 & 0xff; p++; \
+}
+
+  // generate first set of context bytes from outer data
+  MD5_Init(&ctx);
+  MD5_Transform(&ctx, outer);
+  r = result;
+  // convert this to correct binary data according to RFC 1321
+  CDPUT(r, ctx.A);
+  CDPUT(r, ctx.B);
+  CDPUT(r, ctx.C);
+  CDPUT(r, ctx.D);
+
+  // second set with inner data is appended to result string
+  MD5_Init(&ctx);
+  MD5_Transform(&ctx, inner);
+  // convert this to correct binary data
+  CDPUT(r, ctx.A);
+  CDPUT(r, ctx.B);
+  CDPUT(r, ctx.C);
+  CDPUT(r, ctx.D);
+
+  return [NSData dataWithBytes: result length: 32];
+}
+
+/**
+ * Hash the data with SHA1. Uses openssl functions to generate it.
+ *
+ * @return Binary data from SHA1 hashing. On error the funciton returns nil.
+ */
+- (NSData *) asSHA1
+{
+  unsigned char sha[SHA_DIGEST_LENGTH];
+  memset(sha, 0, SHA_DIGEST_LENGTH);
+
+  SHA1([self bytes], [self length], sha);
+
+  return [NSData dataWithBytes: sha  length: SHA_DIGEST_LENGTH];
+}
+
+/**
+ * Hash the data with SHA256. Uses openssl functions to generate it.
+ *
+ * @return Binary data from SHA256 hashing. On error the funciton returns nil.
+ */
+- (NSData *) asSHA256
+{
+  unsigned char sha[SHA256_DIGEST_LENGTH];
+  memset(sha, 0, SHA256_DIGEST_LENGTH);
+
+  SHA256([self bytes], [self length], sha);
+
+  return [NSData dataWithBytes: sha  length: SHA256_DIGEST_LENGTH];
+}
+
+/**
+ * Hash the data with SHA512. Uses openssl functions to generate it.
+ *
+ * @return Binary data from SHA512 hashing. On error the funciton returns nil.
+ */
+- (NSData *) asSHA512
+{
+  unsigned char sha[SHA512_DIGEST_LENGTH];
+  memset(sha, 0, SHA512_DIGEST_LENGTH);
+
+  SHA512([self bytes], [self length], sha);
+
+  return [NSData dataWithBytes: sha  length: SHA512_DIGEST_LENGTH];
+}
+
+/**
+ * Hash the data with SSHA. Uses openssl functions to generate it.
+ *
+ * SSHA works following: SSHA(pass, salt) = SHA1(pass + salt) + saltData
+ *
+ * @param theSalt The salt to be used must not be nil, if empty, one will be generated
+ * @return Binary data from SHA1 hashing. On error the funciton returns nil.
+ */
+- (NSData *) asSSHAUsingSalt: (NSData *) theSalt
+{
+  // 
+  NSMutableData *sshaData;
+
+  // generate salt, if not available
+  if ([theSalt length] == 0) theSalt = [NSData generateSaltForLength: 8];
+
+  // put the pass and salt together as one data array
+  sshaData = [NSMutableData dataWithData: self];
+  [sshaData appendData: theSalt];
+  // generate SHA1 from pass + salt
+  sshaData = [NSMutableData dataWithData: [sshaData asSHA1]];
+  // append salt again
+  [sshaData appendData: theSalt];
+
+  return sshaData;
+}
+
+/**
+ * Hash the data with SSHA256. Uses openssl functions to generate it.
+ *
+ * SSHA256 works following: SSHA256(pass, salt) = SHA256(pass + salt) + saltData
+ *
+ * @param theSalt The salt to be used must not be nil, if empty, one will be generated
+ * @return Binary data from SHA1 hashing. On error the funciton returns nil.
+ */
+
+- (NSData *) asSSHA256UsingSalt: (NSData *) theSalt
+{
+  NSMutableData *sshaData;
+
+  // generate salt, if not available
+  if ([theSalt length] == 0) theSalt = [NSData generateSaltForLength: 8];
+
+  // put the pass and salt together as one data array
+  sshaData = [NSMutableData dataWithData: self];
+  [sshaData appendData: theSalt];
+  // generate SHA1 from pass + salt
+  sshaData = [NSMutableData dataWithData: [sshaData asSHA256]];
+  // append salt again
+  [sshaData appendData: theSalt];
+
+  return sshaData;
+}
+
+/**
+ * Hash the data with SSHA512. Uses openssl functions to generate it.
+ *
+ * SSHA works following: SSHA512(pass, salt) = SHA512(pass + salt) + saltData
+ *
+ * @param theSalt The salt to be used must not be nil, if empty, one will be generated
+ * @return Binary data from SHA512 hashing. On error the funciton returns nil.
+ */
+
+- (NSData *) asSSHA512UsingSalt: (NSData *) theSalt
+{
+  NSMutableData *sshaData;
+
+  // generate salt, if not available
+  if ([theSalt length] == 0) theSalt = [NSData generateSaltForLength: 8];
+
+  // put the pass and salt together as one data array
+  sshaData = [NSMutableData dataWithData: self];
+  [sshaData appendData: theSalt];
+  // generate SHA1 from pass + salt
+  sshaData = [NSMutableData dataWithData: [sshaData asSHA512]];
+  // append salt again
+  [sshaData appendData: theSalt];
+
+  return sshaData;
+}
+
+/**
+ * Hash the data with SMD5. Uses openssl functions to generate it.
+ *
+ * SMD5 works following: SMD5(pass, salt) = MD5(pass + salt) + saltData
+ *
+ * @param theSalt The salt to be used must not be nil, if empty, one will be generated
+ * @return Binary data from SMD5 hashing. On error the funciton returns nil.
+ */
+- (NSData *) asSMD5UsingSalt: (NSData *) theSalt
+{
+  // SMD5 works following: SMD5(pass, salt) = MD5(pass + salt) + salt
+  NSMutableData *smdData;
+
+  // generate salt, if not available
+  if ([theSalt length] == 0) theSalt = [NSData generateSaltForLength: 8];
+
+  // put the pass and salt together as one data array
+  smdData = [NSMutableData dataWithData: self];
+  [smdData appendData: theSalt];
+  // generate SHA1 from pass + salt
+  smdData = [NSMutableData dataWithData: [smdData asMD5]];
+  // append salt again
+  [smdData appendData: theSalt];
+
+  return smdData;
+}
+
+
+/**
+ * Hash the data with CRYPT-MD5 as used in /etc/passwd nowadays. Uses crypt() function to generate it.
+ *
+ *
+ * @param theSalt The salt to be used must not be nil, if empty, one will be generated. It must be printable characters only.
+ * @return Binary data from CRYPT-MD5 hashing. On error the funciton returns nil.
+ */
+- (NSData *) asMD5CryptUsingSalt: (NSData *) theSalt
+{
+  char *buf;
+  NSMutableData *saltData;
+  NSString *cryptString;
+  NSString *saltString;
+
+  if ([theSalt length] == 0)
+    {
+      // make sure these characters are all printable by using base64
+      theSalt = [NSData generateSaltForLength: 8  withBase64: YES];
+    }
+  cryptString = [[NSString alloc] initWithData: self  encoding: NSUTF8StringEncoding];
+
+  NSString * magic = @"$1$";
+  saltData = [NSMutableData dataWithData: [magic dataUsingEncoding: NSUTF8StringEncoding]];
+  [saltData appendData: theSalt];
+  // terminate with "$"
+  [saltData appendData: [@"$" dataUsingEncoding: NSUTF8StringEncoding]];
+
+  saltString = [[NSString alloc] initWithData: saltData  encoding: NSUTF8StringEncoding];
+
+  buf = crypt([cryptString UTF8String], [saltString UTF8String]);
+  [cryptString release];
+  [saltString release];
+  if (!buf)
+    return nil;
+  return [NSData dataWithBytes: buf length: strlen(buf)];
+}
+
+/**
+ * Hash the data using crypt() function.
+ *
+ * @param theSalt The salt to be used must not be nil, if empty, one will be generated
+ * @return Binary data from CRYPT-MD5 hashing. On error the funciton returns nil.
+ */
+- (NSData *) asCryptUsingSalt: (NSData *) theSalt
+{
+  char *buf;
+  NSString *saltString;
+  NSString *cryptString;
+
+  // crypt() works with strings, so convert NSData to strings
+  cryptString = [[NSString alloc] initWithData: self  encoding: NSUTF8StringEncoding];
+
+  if ([theSalt length] == 0) theSalt = [NSData generateSaltForLength: 8 withBase64: YES];
+
+  saltString = [[NSString alloc] initWithData: theSalt  encoding: NSUTF8StringEncoding];
+
+  // The salt is weak here, but who cares anyway, crypt should not
+  // be used anymore
+  buf = crypt([cryptString UTF8String], [saltString UTF8String]);
+  [saltString release];
+  [cryptString release];
+  if (!buf)
+    return nil;
+  return [NSData dataWithBytes: buf length: strlen(buf)];
+}
+
+/**
+ * Get the salt from a password encrypted with a specied scheme
+ *
+ * @param theScheme Needed to get the salt correctly out of the pass
+ * @return The salt, if one was available in the password/scheme, else empty data
+ */
+- (NSData *) extractSalt: (NSString *) theScheme
+{
+  NSRange r;
+  int len;
+  len = [self length];
+  if (len == 0)
+    return [NSData data];
+
+  // for the ssha schemes the salt is appended at the endif
+  // so the range with the salt are bytes after each digest length
+  if ([theScheme caseInsensitiveCompare: @"crypt"] == NSOrderedSame)
+    {
+      // for crypt schemes simply use the whole string
+      // the crypt() function is able to extract it by itself
+      r = NSMakeRange(0, len);
+    }
+  else if ([theScheme caseInsensitiveCompare: @"md5-crypt"] == NSOrderedSame)
+    {
+      // md5 crypt is generated the following "$1$<salt>$<encrypted pass>"
+      NSString *cryptString;
+      NSArray *cryptParts;
+      cryptString = [NSString stringWithUTF8String: [self bytes] ];
+      cryptParts = [cryptString componentsSeparatedByString: @"$"];
+      // correct number of elements (first one is an empty string)
+      if ([cryptParts count] != 4)
+        {
+          return [NSData data];
+        }
+      // second is the identifier of md5-crypt
+      else if( [[cryptParts objectAtIndex: 1] caseInsensitiveCompare: @"1"] != NSOrderedSame )
+        {
+          return [NSData data];
+        }
+       // third is the salt; convert it to NSData
+       return [[cryptParts objectAtIndex: 2] dataUsingEncoding: NSUTF8StringEncoding];
+    }
+  else if ([theScheme caseInsensitiveCompare: @"ssha"] == NSOrderedSame)
+    {
+      r = NSMakeRange(SHA_DIGEST_LENGTH, len - SHA_DIGEST_LENGTH);
+    }
+  else if ([theScheme caseInsensitiveCompare: @"ssha256"] == NSOrderedSame)
+    {
+      r = NSMakeRange(SHA256_DIGEST_LENGTH, len - SHA256_DIGEST_LENGTH);
+    }
+  else if ([theScheme caseInsensitiveCompare: @"ssha512"] == NSOrderedSame)
+    {
+      r = NSMakeRange(SHA512_DIGEST_LENGTH, len - SHA512_DIGEST_LENGTH);
+    }
+  else if ([theScheme caseInsensitiveCompare: @"smd5"] == NSOrderedSame)
+    {
+      r = NSMakeRange(MD5_DIGEST_LENGTH, len - MD5_DIGEST_LENGTH);
+    }
+  else
+    {
+      // return empty string on unknown scheme
+      return [NSData data];
+    }
+
+  return [self subdataWithRange: r];
+}
+
+@end
+
+unsigned charTo4Bits(char c)
+{
+  unsigned bits = 0;
+  if (c > '/' && c < ':')
+    {
+      bits = c - '0';
+    }
+  else if (c > '@' && c < 'G')
+    {
+      bits = (c- 'A') + 10;
+    }
+  else if (c > '`' && c < 'g')
+    {
+      bits = (c- 'a') + 10;
+    }
+  else
+    {
+      bits = 255;
+    }
+  return bits;
+}
diff -Nru sogo-1.3.15a/SoObjects/SOGo/NSString+Crypto.h sogo-1.3.16/SoObjects/SOGo/NSString+Crypto.h
--- sogo-1.3.15a/SoObjects/SOGo/NSString+Crypto.h	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/SoObjects/SOGo/NSString+Crypto.h	2012-06-07 17:40:41.000000000 +0200
@@ -0,0 +1,63 @@
+/* NSString+Crypto.h - this file is part of SOGo
+ *
+ * Copyright (C) 2012 Nicolas Höft
+ * Copyright (C) 2012 Inverse inc.
+ *
+ * Author: Nicolas Höft
+ *         Inverse inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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.
+ */
+
+#ifndef NSSTRING_CRYPTO_H
+#define NSSTRING_CRYPTO_H
+
+#import <Foundation/NSData.h>
+#import <Foundation/NSString.h>
+
+typedef enum {
+  encDefault, //!< default encoding, let the algorithm decide
+  encPlain,   //!< the data is plain text, simply convert to string
+  encHex,     //!< the data is hex encoded
+  encBase64,  //!< base64 encoding
+} keyEncoding;
+
+@class NSObject;
+
+@interface NSString (SOGoCryptoExtension)
+
+
+- (BOOL) isEqualToCrypted: (NSString *) cryptedPassword
+         withDefaultScheme: (NSString *) theScheme;
+
+- (NSString *) asCryptedPassUsingScheme: (NSString *) passwordScheme
+                               withSalt: (NSData *) theSalt
+                               andEncoding: (keyEncoding) encoding;
+
+// this method uses the default encoding (base64, plain, hex)
+// and generates a salt when necessary
+- (NSString *) asCryptedPassUsingScheme: (NSString *) passwordScheme;
+
+- (NSArray *) splitPasswordWithDefaultScheme: (NSString *) defaultScheme;
+
+- (NSString *) asSHA1String;
+- (NSString *) asMD5String;
+
++ (keyEncoding) getDefaultEncodingForScheme: (NSString *) passwordScheme;
+
+@end
+
+#endif /* NSSTRING_CRYPTO_H */
diff -Nru sogo-1.3.15a/SoObjects/SOGo/NSString+Crypto.m sogo-1.3.16/SoObjects/SOGo/NSString+Crypto.m
--- sogo-1.3.15a/SoObjects/SOGo/NSString+Crypto.m	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/SoObjects/SOGo/NSString+Crypto.m	2012-06-07 17:40:41.000000000 +0200
@@ -0,0 +1,304 @@
+/* NSString+Crypto.m - this file is part of SOGo
+ *
+ * Copyright (C) 2012 Nicolas Höft
+ * Copyright (C) 2012 Inverse inc.
+ *
+ * Author: Nicolas Höft
+ *         Inverse inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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.
+ */
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSValue.h>
+
+#import "NSString+Crypto.h"
+#import "NSData+Crypto.h"
+#import <NGExtensions/NGBase64Coding.h>
+
+@implementation NSString (SOGoCryptoExtension)
+
+/**
+ * Extracts the scheme from a string formed "{scheme}pass".
+ *
+ * @return The scheme or an empty string if the string did not contained a scheme in the format above
+ */
+- (NSString *) extractCryptScheme
+{
+  NSRange r;
+  int len;
+  
+  len = [self length];
+  if (len == 0)
+     return @"";
+  if ([self characterAtIndex:0] != '{')
+    return @"";
+  
+  r = [self rangeOfString:@"}" options:(NSLiteralSearch)];
+  if (r.length == 0)
+    return @"";
+  
+  r.length   = (r.location - 1);
+  r.location = 1;
+  return [[self substringWithRange:r] lowercaseString];
+}
+
+
+/**
+ * Split a password of the form {scheme}pass into an array of its components:
+ * {NSString *scheme, NString *pass, NSInteger encoding}, where encoding is
+ * the enum keyEncoding converted to an integer value.
+ *
+ * @param defaultScheme If no scheme is given in cryptedPassword, fall back to this scheme
+ * @see asCryptedPassUsingScheme
+ * @see keyEncoding
+ * @return NSArray with the three elements described above
+ */
+- (NSArray *) splitPasswordWithDefaultScheme: (NSString *) defaultScheme
+{
+  NSString *scheme;
+  NSString *pass;
+  NSArray *schemeComps;
+  keyEncoding encoding;
+  
+  NSRange range;
+  int selflen, len;
+
+  selflen = [self length];
+
+  scheme = [self extractCryptScheme];
+  len = [scheme length];
+  if (len > 0)
+    range = NSMakeRange (len+2, selflen-len-2);
+  else
+    range = NSMakeRange (0, selflen);
+  if (len == 0)
+    scheme = defaultScheme;
+
+  encoding = [NSString getDefaultEncodingForScheme: scheme];
+
+  // get the encoding which may be part of the scheme
+  // e.g. ssha.hex forces a hex encoded ssha scheme
+  // possible is "b64" or "hex"
+  schemeComps = [scheme componentsSeparatedByString: @"."];
+  if ([schemeComps count] == 2)
+    {
+      NSString *stringEncoding;
+      // scheme without encoding string is the first item
+      scheme = [schemeComps objectAtIndex: 0];
+      // encoding string is second item
+      stringEncoding = [schemeComps objectAtIndex: 1];
+      if ([stringEncoding caseInsensitiveCompare: @"hex"] == NSOrderedSame)
+        {
+          encoding = encHex;
+        }
+      else if ([stringEncoding caseInsensitiveCompare: @"b64"] == NSOrderedSame ||
+               [stringEncoding caseInsensitiveCompare: @"base64"] == NSOrderedSame)
+        {
+          encoding = encBase64;
+        }
+    }
+
+  pass = [self substringWithRange: range];
+  return [NSArray arrayWithObjects: scheme, pass, [NSNumber numberWithInt: encoding], nil];
+}
+
+/**
+ * Compare the hex or base64 encoded password with an encrypted password
+ *
+ * @param cryptedPassword The password to compare with, format {scheme}pass , "{scheme}" is optional
+ * @param theScheme If no scheme is given in cryptedPassword, fall back to this scheme
+ * @see asCryptedPassUsingScheme
+ * @return YES if the passwords are identical using this encryption scheme
+ */
+- (BOOL) isEqualToCrypted: (NSString *) cryptedPassword
+         withDefaultScheme: (NSString *) theScheme
+{
+  NSArray *passInfo;
+  NSString *selfCrypted;
+  NSString *pass;
+  NSString *scheme;
+  NSData *salt;
+  NSData *decodedData;
+  NSNumber *encodingNumber;
+  keyEncoding encoding;
+
+  // split scheme and pass
+  passInfo = [cryptedPassword splitPasswordWithDefaultScheme: theScheme];
+
+  scheme   = [passInfo objectAtIndex: 0];
+  pass     = [passInfo objectAtIndex: 1];
+  encodingNumber = [passInfo objectAtIndex: 2];
+  encoding = [encodingNumber intValue];
+
+  if (encoding == encHex)
+    {
+      decodedData = [NSData decodeDataFromHexString: pass];
+      
+      if(decodedData == nil)
+        {
+          decodedData = [NSData data];
+        }
+      else
+       {
+          // decoding was successful, now make sure
+          // that the pass is in lowercase since decodeDataFromHexString uses
+          // lowercase charaters, too
+          pass = [pass lowercaseString];
+       }
+    }
+  else if(encoding == encBase64)
+    {
+      decodedData = [pass dataByDecodingBase64];
+      if(decodedData == nil)
+        {
+          decodedData = [NSData data];
+        }
+    }
+  else
+    {
+      decodedData = [pass dataUsingEncoding: NSUTF8StringEncoding];
+    }
+
+  salt = [decodedData extractSalt: scheme];
+
+  // encrypt self with the salt an compare the results
+  selfCrypted = [self asCryptedPassUsingScheme: scheme
+                           withSalt: salt
+                           andEncoding: encoding];
+  // return always false when there was a problem
+  if (selfCrypted == nil)
+    return NO;
+
+  if ([selfCrypted isEqualToString: pass] == YES)
+    return YES;
+  return NO;
+}
+
+/**
+ * Calls asCryptedPassUsingScheme:withSalt:andEncoding: with an empty salt and uses
+ * the default encoding.
+ *
+ * @param passwordScheme 
+ * @return If successful, the encrypted and encoded NSString of the format {scheme}pass, or nil if the scheme did not exists or an error occured
+ */
+- (NSString *) asCryptedPassUsingScheme: (NSString *) passwordScheme
+{
+  return [self asCryptedPassUsingScheme: passwordScheme
+                               withSalt: [NSData data]
+                            andEncoding: encDefault];
+}
+
+/**
+ * Uses NSData -asCryptedPassUsingScheme to encrypt the string and converts the
+ * binary data back to a readable string using userEncoding
+ *
+ * @param passwordScheme The scheme to use
+ * @param theSalt The binary data of the salt
+ * @param userEncoding The encoding (plain, hex, base64) to be used
+ * @return If successful, the encrypted and encoded NSString of the format {scheme}pass, or nil if the scheme did not exists or an error occured
+ */
+- (NSString *) asCryptedPassUsingScheme: (NSString *) passwordScheme
+                               withSalt: (NSData *) theSalt
+                          andEncoding: (keyEncoding) userEncoding
+{
+  keyEncoding dataEncoding;
+  NSData* cryptedData;
+  // convert NSString to NSData and apply encryption scheme
+  cryptedData = [self dataUsingEncoding: NSUTF8StringEncoding];
+  cryptedData = [cryptedData asCryptedPassUsingScheme: passwordScheme  withSalt: theSalt];
+  // abort on unsupported scheme or error
+  if (cryptedData == nil)
+    return nil;
+
+  // use default encoding scheme, when set to default
+  if (userEncoding == encDefault)
+    dataEncoding = [NSString getDefaultEncodingForScheme: passwordScheme];
+  else
+    dataEncoding = userEncoding;
+
+  if (dataEncoding == encHex)
+    {
+      // hex encoding
+      return [NSData encodeDataAsHexString: cryptedData];
+    }
+  else if(dataEncoding == encBase64)
+    {
+       // base64 encoding
+      NSString *s = [[NSString alloc] initWithData: [cryptedData dataByEncodingBase64WithLineLength: 1024]
+                encoding: NSASCIIStringEncoding];
+      return [s autorelease];
+    }
+
+  // plain string
+  return [[[NSString alloc] initWithData: cryptedData encoding: NSUTF8StringEncoding] autorelease];
+}
+
+/**
+ * Returns the encoding for a specified scheme
+ *
+ * @param passwordScheme The scheme for which to get the encoding.
+ * @see keyEncoding
+ * @return returns the encoding, if unknown returns encPlain
+ */
++ (keyEncoding) getDefaultEncodingForScheme: (NSString *) passwordScheme
+{
+  // in order to keep backwards-compatibility, hex encoding is used for sha1 here
+  if ([passwordScheme caseInsensitiveCompare: @"md5"] == NSOrderedSame ||
+      [passwordScheme caseInsensitiveCompare: @"plain-md5"] == NSOrderedSame ||
+      [passwordScheme caseInsensitiveCompare: @"sha"] == NSOrderedSame ||
+      [passwordScheme caseInsensitiveCompare: @"cram-md5"] == NSOrderedSame)
+    {
+      return encHex;
+    }
+  else if ([passwordScheme caseInsensitiveCompare: @"smd5"] == NSOrderedSame ||
+           [passwordScheme caseInsensitiveCompare: @"ldap-md5"] == NSOrderedSame ||
+           [passwordScheme caseInsensitiveCompare: @"ssha"] == NSOrderedSame ||
+           [passwordScheme caseInsensitiveCompare: @"sha256"] == NSOrderedSame ||
+           [passwordScheme caseInsensitiveCompare: @"ssha256"] == NSOrderedSame ||
+           [passwordScheme caseInsensitiveCompare: @"sha512"] == NSOrderedSame ||
+           [passwordScheme caseInsensitiveCompare: @"ssha512"] == NSOrderedSame)
+    {
+      return encBase64;
+    }
+  return encPlain;
+}
+
+/**
+ * Encrypts the data with SHA1 scheme and returns the hex-encoded data
+ *
+ * @return If successful, sha1 encrypted and with hex encoded string
+ */
+- (NSString *) asSHA1String;
+{
+  NSData *cryptData;
+  cryptData = [self dataUsingEncoding: NSUTF8StringEncoding];
+  return [NSData encodeDataAsHexString: [cryptData asSHA1] ];
+}
+
+/**
+ * Encrypts the data with Plain MD5 scheme and returns the hex-encoded data
+ *
+ * @return If successful, MD5 encrypted and with hex encoded string
+ */
+- (NSString *) asMD5String;
+{
+  NSData *cryptData;
+  cryptData = [self dataUsingEncoding: NSUTF8StringEncoding];
+  return [NSData encodeDataAsHexString: [cryptData asMD5] ];
+}
+
+@end
diff -Nru sogo-1.3.15a/SoObjects/SOGo/NSString+Utilities.h sogo-1.3.16/SoObjects/SOGo/NSString+Utilities.h
--- sogo-1.3.15a/SoObjects/SOGo/NSString+Utilities.h	2012-05-18 17:27:10.000000000 +0200
+++ sogo-1.3.16/SoObjects/SOGo/NSString+Utilities.h	2012-06-07 17:40:41.000000000 +0200
@@ -66,10 +66,6 @@
 
 - (id) objectFromJSONString;
 
-- (NSString *) asCryptStringUsingSalt: (NSString *) theSalt;
-- (NSString *) asMD5String;
-- (NSString *) asSHA1String;
-
 - (NSString *) asSafeSQLString;
 
 - (NSUInteger) countOccurrencesOfString: (NSString *) substring;
diff -Nru sogo-1.3.15a/SoObjects/SOGo/NSString+Utilities.m sogo-1.3.16/SoObjects/SOGo/NSString+Utilities.m
--- sogo-1.3.15a/SoObjects/SOGo/NSString+Utilities.m	2012-05-18 17:27:10.000000000 +0200
+++ sogo-1.3.16/SoObjects/SOGo/NSString+Utilities.m	2012-06-07 17:40:41.000000000 +0200
@@ -21,10 +21,6 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#ifndef __OpenBSD__ 
-#include <crypt.h>
-#endif
-
 #import <Foundation/NSArray.h>
 #import <Foundation/NSCharacterSet.h>
 #import <Foundation/NSData.h>
@@ -45,12 +41,6 @@
 
 #import "NSString+Utilities.h"
 
-#define _XOPEN_SOURCE 1
-#include <unistd.h>
-#include <openssl/evp.h>
-#include <openssl/md5.h>
-#include <openssl/sha.h>
-
 static NSMutableCharacterSet *urlNonEndingChars = nil;
 static NSMutableCharacterSet *urlAfterEndingChars = nil;
 static NSMutableCharacterSet *urlStartChars = nil;
@@ -225,13 +215,13 @@
     {
       rangePtr->location += offset;
       urlText = [selfCopy substringFromRange: *rangePtr];
-      if ([urlText hasPrefix: prefix]) prefix = @"";
       newUrlText = [NSString stringWithFormat: @"<a href=\"%@%@\">%@</a>",
-			     prefix, urlText, urlText];
+                          ([urlText hasPrefix: prefix]? @"" : prefix),
+                             urlText, urlText];
       [selfCopy replaceCharactersInRange: *rangePtr
-		withString: newUrlText];
+                              withString: newUrlText];
       offset += ([newUrlText length] - [urlText length]);
-
+      
       // Add range for further substitutions
       currentUrlRange = NSMakeRange (rangePtr->location, [newUrlText length]);
       [ranges addNonNSObject: &currentUrlRange
@@ -250,12 +240,12 @@
   selfCopy = [NSMutableString stringWithString: self];
   [self _handleURLs: selfCopy
 	textToMatch: @"://"
-	prefix: @""
-	inRanges: ranges];
+             prefix: @""
+           inRanges: ranges];
   [self _handleURLs: selfCopy
 	textToMatch: @"@"
-	prefix: @"mailto:";
-	inRanges: ranges];
+             prefix: @"mailto:";
+           inRanges: ranges];
   [ranges freeNonNSObjects];
 
   return selfCopy;
@@ -471,7 +461,8 @@
 
 - (int) timeValue
 {
-  int i, time;
+  int 		time;
+  NSInteger 	i;
 
   if ([self length] > 0)
     {
@@ -534,48 +525,6 @@
   return object;
 }
 
-- (NSString *) asCryptStringUsingSalt: (NSString *) theSalt
-{
-  char *buf;
-  
-  // The salt is weak here, but who cares anyway, crypt should not
-  // be used anymore
-  buf = crypt([self UTF8String], [theSalt UTF8String]);
-  return [NSString stringWithUTF8String: buf];
-}
-
-- (NSString *) asMD5String
-{
-  unsigned char md[MD5_DIGEST_LENGTH];
-  char buf[80];
-  int i;
-  
-  memset(md, 0, MD5_DIGEST_LENGTH);
-  memset(buf, 0, 80);
-  
-  EVP_Digest((const void *) [self UTF8String], strlen([self UTF8String]), md, NULL, EVP_md5(), NULL);
-  for (i = 0; i < MD5_DIGEST_LENGTH; i++)
-    sprintf(&(buf[i*2]), "%02x", md[i]);
-  
-  return [NSString stringWithUTF8String: buf];
-}
-
-- (NSString *) asSHA1String
-{
-  unsigned char sha[SHA_DIGEST_LENGTH];
-  char buf[80];
-  int i;
-  
-  memset(sha, 0, SHA_DIGEST_LENGTH);
-  memset(buf, 0, 80);
-  
-  SHA1((const void *)[self UTF8String], strlen([self UTF8String]), sha);
-  for (i = 0; i < SHA_DIGEST_LENGTH; i++)
-    sprintf(&(buf[i*2]), "%02x", sha[i]);
-  
-  return [NSString stringWithUTF8String: buf];
-}
-
 - (NSString *) asSafeSQLString
 {
   return [[self stringByReplacingString: @"\\" withString: @"\\\\"]
diff -Nru sogo-1.3.15a/SoObjects/SOGo/SOGoGroup.h sogo-1.3.16/SoObjects/SOGo/SOGoGroup.h
--- sogo-1.3.15a/SoObjects/SOGo/SOGoGroup.h	2012-05-18 17:27:10.000000000 +0200
+++ sogo-1.3.16/SoObjects/SOGo/SOGoGroup.h	2012-06-07 17:40:41.000000000 +0200
@@ -1,6 +1,6 @@
 /* SOGoGroup.h - this file is part of SOGo
  *
- * Copyright (C) 2009-2010 Inverse inc.
+ * Copyright (C) 2009-2012 Inverse inc.
  *
  * Author: Ludovic Marcotte <lmarcotte@inverse.ca>
  *
diff -Nru sogo-1.3.15a/SoObjects/SOGo/SOGoGroup.m sogo-1.3.16/SoObjects/SOGo/SOGoGroup.m
--- sogo-1.3.15a/SoObjects/SOGo/SOGoGroup.m	2012-05-18 17:27:10.000000000 +0200
+++ sogo-1.3.16/SoObjects/SOGo/SOGoGroup.m	2012-06-07 17:40:41.000000000 +0200
@@ -1,6 +1,6 @@
 /* SOGoGroup.m - this file is part of SOGo
  *
- * Copyright (C) 2009-2011 Inverse inc.
+ * Copyright (C) 2009-2012 Inverse inc.
  *
  * Author: Ludovic Marcotte <lmarcotte@inverse.ca>
  *
@@ -57,6 +57,7 @@
 #include "SOGoGroup.h"
 
 #import <Foundation/NSArray.h>
+#import <Foundation/NSDictionary.h>
 #import <Foundation/NSString.h>
 
 #include "SOGoCache.h"
@@ -163,15 +164,26 @@
   if (entry)
     {
       NSArray *classes;
-      
+
       // We check to see if it's a group
-      classes = [[entry attributeWithName: @"objectClass"] allStringValues];
+      classes = [[entry asDictionary] objectForKey: @"objectclass"];
+
+      if (classes)
+	{
+	  int i, c;
+	  
+	  classes = [NSMutableArray arrayWithArray: classes];
+	  c = [classes count];
+	  for (i = 0; i < c; i++)
+	    [(id)classes replaceObjectAtIndex: i
+				   withObject: [[classes objectAtIndex: i] lowercaseString]];
+	}
 
       // Found a group, let's return it.
       if ([classes containsObject: @"group"] ||
-	  [classes containsObject: @"groupOfNames"] ||
-	  [classes containsObject: @"groupOfUniqueNames"] ||
-	  [classes containsObject: @"posixGroup"])
+	  [classes containsObject: @"groupofnames"] ||
+	  [classes containsObject: @"groupofuniquenames"] ||
+	  [classes containsObject: @"posixgroup"])
 	{
 	  o = [[self alloc] initWithIdentifier: theValue
 			                domain: domain
@@ -192,9 +204,10 @@
 {
   NSMutableArray *dns, *uids, *logins;
   NSString *dn, *login;
+  SOGoUserManager *um;
+  NSDictionary *d;
   SOGoUser *user;
   NSArray *o;
-  SOGoUserManager *um;
   int i, c;
 
   if (!_members)
@@ -206,15 +219,16 @@
 
       // We check if it's a static group  
       // Fetch "members" - we get DNs
-      o = [[_entry attributeWithName: @"member"] allStringValues];
+      d = [_entry asDictionary];
+      o = [d objectForKey: @"member"];
       if (o) [dns addObjectsFromArray: o];
 
       // Fetch "uniqueMembers" - we get DNs
-      o = [[_entry attributeWithName: @"uniqueMember"] allStringValues];
+      o = [d objectForKey: @"uniquemember"];
       if (o) [dns addObjectsFromArray: o];
   
       // Fetch "memberUid" - we get UID (like login names)
-      o = [[_entry attributeWithName: @"memberUid"] allStringValues];
+      o = [d objectForKey: @"memberuid"];
       if (o) [uids addObjectsFromArray: o];
 
       c = [dns count] + [uids count];
diff -Nru sogo-1.3.15a/SoObjects/SOGo/SOGoUserManager.m sogo-1.3.16/SoObjects/SOGo/SOGoUserManager.m
--- sogo-1.3.15a/SoObjects/SOGo/SOGoUserManager.m	2012-05-18 17:27:10.000000000 +0200
+++ sogo-1.3.16/SoObjects/SOGo/SOGoUserManager.m	2012-06-07 17:40:41.000000000 +0200
@@ -33,6 +33,7 @@
 
 #import "NSArray+Utilities.h"
 #import "NSString+Utilities.h"
+#import "NSString+Crypto.h"
 #import "NSObject+Utilities.h"
 #import "SOGoDomainDefaults.h"
 #import "SOGoSource.h"
diff -Nru sogo-1.3.15a/SoObjects/SOGo/SQLSource.h sogo-1.3.16/SoObjects/SOGo/SQLSource.h
--- sogo-1.3.15a/SoObjects/SOGo/SQLSource.h	2012-05-18 17:27:10.000000000 +0200
+++ sogo-1.3.16/SoObjects/SOGo/SQLSource.h	2012-06-07 17:40:41.000000000 +0200
@@ -45,6 +45,7 @@
   NSString *_imapHostField;
   NSString *_userPasswordAlgorithm;
   NSURL *_viewURL;
+  BOOL _prependPasswordScheme;
 
   /* resources handling */
   NSString *_kindField;
diff -Nru sogo-1.3.15a/SoObjects/SOGo/SQLSource.m sogo-1.3.16/SoObjects/SOGo/SQLSource.m
--- sogo-1.3.15a/SoObjects/SOGo/SQLSource.m	2012-05-18 17:27:10.000000000 +0200
+++ sogo-1.3.16/SoObjects/SOGo/SQLSource.m	2012-06-07 17:40:41.000000000 +0200
@@ -39,6 +39,7 @@
 
 #import "SOGoConstants.h"
 #import "NSString+Utilities.h"
+#import "NSString+Crypto.h"
 
 #import "SQLSource.h"
 
@@ -47,7 +48,10 @@
  *
  * c_uid      - will be used for authentication - it's a username or username@domain.tld)
  * c_name     - which can be identical to c_uid - will be used to uniquely identify entries)
- * c_password - password of the user, plain-text, md5 or sha encoded for now
+ * c_password - password of the user, can be encoded in {scheme}pass format, or when stored without
+ *              scheme it uses the scheme set in userPasswordAlgorithm.
+ *              Possible algorithms are:  plain, md5, crypt-md5, sha, ssha (including 256/512 variants),
+ *              cram-md5, smd5, crypt, crypt-md5
  * c_cn       - the user's common name
  * mail       - the user's mail address
  *
@@ -63,8 +67,12 @@
  *    canAuthenticate = YES;
  *    isAddressBook = YES;
  *    userPasswordAlgorithm = md5;
+ *    prependPasswordScheme = YES;
  *  }
  *
+ * If prependPasswordScheme is set to YES, the generated passwords will have the format {scheme}password.
+ * If it is NO (the default), the password will be written to database without encryption scheme.
+ *
  */
 
 @implementation SQLSource
@@ -126,6 +134,10 @@
   ASSIGN(_kindField, [udSource objectForKey: @"KindFieldName"]);
   ASSIGN(_multipleBookingsField, [udSource objectForKey: @"MultipleBookingsFieldName"]);
   ASSIGN(_domainField, [udSource objectForKey: @"DomainFieldName"]);
+  if ([udSource objectForKey: @"prependPasswordScheme"])
+    _prependPasswordScheme = [[udSource objectForKey: @"prependPasswordScheme"] boolValue];
+  else
+    _prependPasswordScheme = NO;
   
   if (!_userPasswordAlgorithm)
     _userPasswordAlgorithm = @"none";
@@ -157,28 +169,8 @@
   if (!plainPassword || !encryptedPassword)
     return NO;
 
-  if ([_userPasswordAlgorithm caseInsensitiveCompare: @"none"] == NSOrderedSame)
-    {
-      return [plainPassword isEqualToString: encryptedPassword];
-    }
-  else if ([_userPasswordAlgorithm caseInsensitiveCompare: @"crypt"] == NSOrderedSame)
-    {
-      return [[plainPassword asCryptStringUsingSalt: encryptedPassword] isEqualToString: encryptedPassword];
-    }
-  else if ([_userPasswordAlgorithm caseInsensitiveCompare: @"md5"] == NSOrderedSame)
-    {
-      return [[plainPassword asMD5String] isEqualToString: encryptedPassword];
-    }
-  else if ([_userPasswordAlgorithm caseInsensitiveCompare: @"sha"] == NSOrderedSame)
-    {
-
-      return [[plainPassword asSHA1String] isEqualToString: encryptedPassword];
-    }
-
-
-  [self errorWithFormat: @"Unsupported user-password algorithm: %@", _userPasswordAlgorithm];
-
-  return NO;
+  return [plainPassword isEqualToCrypted: encryptedPassword
+                       withDefaultScheme: _userPasswordAlgorithm];
 }
 
 /**
@@ -189,26 +181,20 @@
  */
 - (NSString *) _encryptPassword: (NSString *) plainPassword
 {
-  if ([_userPasswordAlgorithm caseInsensitiveCompare: @"none"] == NSOrderedSame)
-    {
-      return plainPassword;
-    }
-  else if ([_userPasswordAlgorithm caseInsensitiveCompare: @"crypt"] == NSOrderedSame)
-    {
-      return [plainPassword asCryptStringUsingSalt: [plainPassword asMD5String]];
-    }
-  else if ([_userPasswordAlgorithm caseInsensitiveCompare: @"md5"] == NSOrderedSame)
-    {
-      return [plainPassword asMD5String];
-    }
-  else if ([_userPasswordAlgorithm caseInsensitiveCompare: @"sha"] == NSOrderedSame)
-    {
-      return [plainPassword asSHA1String];
-    }
-  
-  [self errorWithFormat: @"Unsupported user-password algorithm: %@", _userPasswordAlgorithm];
+  NSString *pass;
+  NSString* result;
   
-  return plainPassword;
+  pass = [plainPassword asCryptedPassUsingScheme: _userPasswordAlgorithm];
+
+  if (pass == nil)
+    [self errorWithFormat: @"Unsupported user-password algorithm: %@", _userPasswordAlgorithm];
+
+  if (_prependPasswordScheme)
+    result = [NSString stringWithFormat: @"{%@}%@", _userPasswordAlgorithm, pass];
+  else
+    result = pass;
+
+  return result;
 }
 
 //
diff -Nru sogo-1.3.15a/UI/Contacts/English.lproj/Localizable.strings sogo-1.3.16/UI/Contacts/English.lproj/Localizable.strings
--- sogo-1.3.15a/UI/Contacts/English.lproj/Localizable.strings	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/Contacts/English.lproj/Localizable.strings	2012-06-07 17:40:42.000000000 +0200
@@ -198,6 +198,7 @@
 "Import Cards" = "Import Cards";
 "Select a vCard or LDIF file." = "Select a vCard or LDIF file.";
 "Upload" = "Upload";
+"Uploading" = "Uploading";
 "Done" = "Done";
 "An error occured while importing contacts." = "An error occured while importing contacts.";
 "No card was imported." = "No card was imported.";
diff -Nru sogo-1.3.15a/UI/MailPartViewers/UIxMailPartAlternativeViewer.m sogo-1.3.16/UI/MailPartViewers/UIxMailPartAlternativeViewer.m
--- sogo-1.3.15a/UI/MailPartViewers/UIxMailPartAlternativeViewer.m	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/MailPartViewers/UIxMailPartAlternativeViewer.m	2012-06-07 17:40:45.000000000 +0200
@@ -43,7 +43,7 @@
 @interface UIxMailPartAlternativeViewer : UIxMailPartViewer
 {
   id           childInfo;
-  unsigned int childIndex;
+  NSUInteger   childIndex;
 }
 
 @end
@@ -70,7 +70,7 @@
 - (NSArray *) childPartTypes
 {
   NSMutableArray *types;
-  unsigned i, count;
+  NSUInteger i, count;
   NSArray  *childParts;
 
   childParts = [[self bodyInfo] valueForKey:@"parts"];
@@ -89,10 +89,10 @@
   return types;
 }
 
-- (unsigned int) _preferredTypesPart: (NSArray *) types
+- (NSUInteger) _preferredTypesPart: (NSArray *) types
 {
-  unsigned int count, max;
-  unsigned int part;
+  NSUInteger count, max;
+  NSUInteger part;
   const NSString *priorities[] = { @"multipart/related", @"multipart/mixed",
 				   @"text/calendar", @"text/html",
 				   @"text/plain" };
@@ -113,7 +113,7 @@
 - (int) _selectPartIndexFromTypes: (NSArray *) _types
 {
   /* returns the index of the selected part or NSNotFound */
-  unsigned count, max, part;
+  NSUInteger count, max, part;
 
   part = [self _preferredTypesPart: _types];
   if (part == NSNotFound)
@@ -136,7 +136,7 @@
 
 - (void) selectChildInfo
 {
-  unsigned idx;
+  NSUInteger idx;
 
   [childInfo release]; childInfo = nil;
   childIndex = 0;
@@ -164,7 +164,7 @@
   return childInfo;
 }
 
-- (unsigned int) childIndex
+- (NSUInteger) childIndex
 {
   if (!childIndex)
     [self selectChildInfo];
@@ -174,11 +174,8 @@
 
 - (NSString *) childPartName
 {
-  char buf[8];
-
-  sprintf (buf, "%d", [self childIndex] + 1);
-
-  return [NSString stringWithCString:buf];
+  return [NSString stringWithFormat: @"%u",
+                   (unsigned int) ([self childIndex] + 1)];
 }
 
 - (id) childPartPath
diff -Nru sogo-1.3.15a/UI/MailPartViewers/UIxMailPartMessageViewer.m sogo-1.3.16/UI/MailPartViewers/UIxMailPartMessageViewer.m
--- sogo-1.3.15a/UI/MailPartViewers/UIxMailPartMessageViewer.m	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/MailPartViewers/UIxMailPartMessageViewer.m	2012-06-07 17:40:45.000000000 +0200
@@ -165,7 +165,7 @@
   subject = [baseSubject decodedHeader];
 
   if (![subject length])
-    subject = [self labelForKey: @"Untitled"];
+    subject = @"";
 
   return subject;
 }
diff -Nru sogo-1.3.15a/UI/MailerUI/Dutch.lproj/Localizable.strings sogo-1.3.16/UI/MailerUI/Dutch.lproj/Localizable.strings
--- sogo-1.3.15a/UI/MailerUI/Dutch.lproj/Localizable.strings	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/MailerUI/Dutch.lproj/Localizable.strings	2012-06-07 17:40:45.000000000 +0200
@@ -283,9 +283,9 @@
 = "De berichten konden niet naar de vuilnisbak worden verplaatst. Wilt u ze direct verwijderen?";
 
 /* Message editing */
-"error_validationfailed" = "Validering mislukt!";
 "error_missingsubject" = "U heeft geen onderwerp opgegeven!";
 "error_missingrecipients" = "U heeft geen ontvanger opgegeven!";
+"Send Anyway" = "Toch verzenden";
 
 /* Message sending */
 "cannot send message: (smtp) all recipients discarded" = "Kan bericht niet sturen: alle ontvangers zijn ongeldig.";
diff -Nru sogo-1.3.15a/UI/MailerUI/English.lproj/Localizable.strings sogo-1.3.16/UI/MailerUI/English.lproj/Localizable.strings
--- sogo-1.3.15a/UI/MailerUI/English.lproj/Localizable.strings	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/MailerUI/English.lproj/Localizable.strings	2012-06-07 17:40:45.000000000 +0200
@@ -283,9 +283,9 @@
 = "The messages could not be moved to the trash folder. Would you like to delete them immediately?";
 
 /* Message editing */
-"error_validationfailed" = "Validation failed";
-"error_missingsubject" = "Subject is missing";
-"error_missingrecipients" = "No recipients specified";
+"error_missingsubject" = "The message has no subject. Are you sure you want to send it?";
+"error_missingrecipients" = "Please specify at least one recipient.";
+"Send Anyway" = "Send Anyway";
 
 /* Message sending */
 "cannot send message: (smtp) all recipients discarded" = "Cannot send message: all recipients are invalid.";
diff -Nru sogo-1.3.15a/UI/MailerUI/French.lproj/Localizable.strings sogo-1.3.16/UI/MailerUI/French.lproj/Localizable.strings
--- sogo-1.3.15a/UI/MailerUI/French.lproj/Localizable.strings	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/MailerUI/French.lproj/Localizable.strings	2012-06-07 17:40:45.000000000 +0200
@@ -107,8 +107,6 @@
 "cc"            = "Copie à";
 "bcc"           = "Copie cachée à";
 
-"Addressbook"   = "Adresses";
-
 "Edit Draft..." = "Modifier le brouillon...";
 "Load Images" = "Télécharger les images";
 
@@ -285,9 +283,9 @@
 = "Les messages ne peuvent être déplacés dans la corbeille. Voulez-vous les supprimer immédiatement?";
 
 /* Message editing */
-"error_validationfailed" = "Message invalide";
-"error_missingsubject" = "- le sujet est manquant";
-"error_missingrecipients" = "- aucun destinataire spécifié";
+"error_missingsubject" = "Le message n'as pas de sujet. Êtes-vous certain de vouloir l'envoyer?";
+"error_missingrecipients" = "Veuillez spécifier au moins un destinataire.";
+"Send Anyway" = "Envoyer sans sujet";
 
 /* Message sending */
 "cannot send message: (smtp) all recipients discarded" = "Le message n'a pas pu être envoyé car aucune adresse n'est valide.";
diff -Nru sogo-1.3.15a/UI/MailerUI/German.lproj/Localizable.strings sogo-1.3.16/UI/MailerUI/German.lproj/Localizable.strings
--- sogo-1.3.15a/UI/MailerUI/German.lproj/Localizable.strings	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/MailerUI/German.lproj/Localizable.strings	2012-06-07 17:40:45.000000000 +0200
@@ -283,9 +283,9 @@
 = "Die Nachricht(en) können nicht in den Papierkorb verschoben werden. Wollen Sie diese endgültig löschen?";
 
 /* Message editing */
-"error_validationfailed" = "Prüfung ist fehlgeschlagen!";
 "error_missingsubject" = "Der Betreff fehlt";
 "error_missingrecipients" = "Der Empfänger fehlt";
+"Send Anyway" = "Trotzdem versenden";
 
 /* Message sending */
 "cannot send message: (smtp) all recipients discarded" = "Kann Nachricht nicht versenden: Alle Empfänger sind ungültig.";
diff -Nru sogo-1.3.15a/UI/MailerUI/UIxMailEditor.m sogo-1.3.16/UI/MailerUI/UIxMailEditor.m
--- sogo-1.3.15a/UI/MailerUI/UIxMailEditor.m	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/MailerUI/UIxMailEditor.m	2012-06-07 17:40:45.000000000 +0200
@@ -394,7 +394,7 @@
 {
   if (![_info isNotNull]) return;
   [self debugWithFormat:@"loading info ..."];
-  [self takeValuesFromDictionary:_info];
+  [self setValuesForKeysWithDictionary:_info];
 }
 
 - (NSDictionary *) storeInfo
@@ -422,8 +422,14 @@
 
   folderContainer = (SOGoContactFolders *) [[[self clientObject] lookupUserFolder] privateContacts: @"Contacts"
                                                                                            inContext: nil];
+  
   folder = [folderContainer lookupPersonalFolder: @"personal" ignoringRights: YES];
 
+  // If the folder doesn't exist anymore or if the database is down, we
+  // return an empty array.
+  if ([folder isKindOfClass: [NSException class]])
+      return [NSArray array];
+
   contactInfos = [folder lookupContactsWithFilter: nil
 				       onCriteria: nil
 					   sortBy: @"c_cn"
@@ -653,10 +659,7 @@
 
   if (![self hasOneOrMoreRecipients])
     error = [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
-			 reason: @"Please select a recipient!"];
-  else if ([[self subject] length] == 0)
-    error = [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
-			 reason: @"Please set a subject!"];
+                                          reason: [self labelForKey: @"error_missingrecipients"]];
   else
     error = nil;
   
diff -Nru sogo-1.3.15a/UI/MailerUI/UIxMailListActions.m sogo-1.3.16/UI/MailerUI/UIxMailListActions.m
--- sogo-1.3.15a/UI/MailerUI/UIxMailListActions.m	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/MailerUI/UIxMailListActions.m	2012-06-07 17:40:45.000000000 +0200
@@ -192,7 +192,7 @@
   baseSubject = [[message valueForKey: @"envelope"] subject];
   subject = [baseSubject decodedHeader];
   if (![subject length])
-    subject = [self labelForKey: @"Untitled"];
+    subject = @"";
 
   return [subject stringByEscapingHTMLString];
 }
diff -Nru sogo-1.3.15a/UI/MailerUI/UIxMailMainFrame.m sogo-1.3.16/UI/MailerUI/UIxMailMainFrame.m
--- sogo-1.3.15a/UI/MailerUI/UIxMailMainFrame.m	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/MailerUI/UIxMailMainFrame.m	2012-06-07 17:40:45.000000000 +0200
@@ -125,8 +125,8 @@
     // TODO: this is ugly, create reusable link facility in SOPE
     // TODO: remove 'search' and 'filterpopup', preserve sorting
     NSMutableString *ms;
-    NSArray  *qp;
-    unsigned i, count;
+    NSArray    *qp;
+    NSUInteger i, count;
     
     qp    = [[u substringFromIndex:(r.location + r.length)] 
 	        componentsSeparatedByString:@"&"];
@@ -193,8 +193,8 @@
   SOGoMailAccounts *co;
   SOGoContactFolders *folders;
   SOGoParentFolder *folder;
-  WORequest *request;
-  int i, count;
+  WORequest  *request;
+  NSUInteger i, count;
 
   parameters = nil;
   co = [self clientObject];
@@ -549,7 +549,7 @@
   NSArray *available;
   NSDictionary *metaData;
   SOGoUserDefaults *ud;
-  unsigned int i;
+  NSUInteger i;
 
   if (!columnsOrder)
     {
@@ -636,8 +636,13 @@
   NSMutableArray *folders;
   NSMutableString *path;
   SOGoUserDefaults *ud;
-  NSString *s;
-  int i, j, k;
+  NSString   *s;
+  NSUInteger i, j, k;
+
+  // If Sieve scripts aren't enabled, there's no need in considering
+  // what's potentially in the database regarding "fileinto" scripts.
+  if (![[[context activeUser] domainDefaults] sieveScriptsEnabled])
+    return [[NSArray array] jsonRepresentation];
 
   ud = [[context activeUser] userDefaults];
   folders = [NSMutableArray array];
diff -Nru sogo-1.3.15a/UI/MailerUI/UIxMailView.m sogo-1.3.16/UI/MailerUI/UIxMailView.m
--- sogo-1.3.15a/UI/MailerUI/UIxMailView.m	2012-05-18 17:27:11.000000000 +0200
+++ sogo-1.3.16/UI/MailerUI/UIxMailView.m	2012-06-07 17:40:45.000000000 +0200
@@ -96,8 +96,6 @@
   NSString *subject;
 
   subject = [[self clientObject] decodedSubject];
-  if (![subject length])
-    subject = [self labelForKey: @"Untitled"];
 
   return subject;
 }
diff -Nru sogo-1.3.15a/UI/Scheduler/Dutch.lproj/Localizable.strings sogo-1.3.16/UI/Scheduler/Dutch.lproj/Localizable.strings
--- sogo-1.3.15a/UI/Scheduler/Dutch.lproj/Localizable.strings	2012-05-18 17:27:14.000000000 +0200
+++ sogo-1.3.16/UI/Scheduler/Dutch.lproj/Localizable.strings	2012-06-07 17:40:45.000000000 +0200
@@ -420,7 +420,7 @@
 
 /* transparency */
 
-"Show Time as Free" = "Toon tijd als vrij:";
+"Show Time as Free" = "Toon tijd als vrij";
 
 /* validation errors */
 
diff -Nru sogo-1.3.15a/UI/Scheduler/English.lproj/Localizable.strings sogo-1.3.16/UI/Scheduler/English.lproj/Localizable.strings
--- sogo-1.3.15a/UI/Scheduler/English.lproj/Localizable.strings	2012-05-18 17:27:14.000000000 +0200
+++ sogo-1.3.16/UI/Scheduler/English.lproj/Localizable.strings	2012-06-07 17:40:45.000000000 +0200
@@ -110,6 +110,7 @@
 "Import Events" = "Import Events";
 "Select an iCalendar file (.ics)." = "Select an iCalendar file (.ics).";
 "Upload" = "Upload";
+"Uploading" = "Uploading";
 "Publish Calendar..." = "Publish Calendar...";
 "Reload Remote Calendars" = "Reload Remote Calendars";
 "Properties" = "Properties";
diff -Nru sogo-1.3.15a/UI/Scheduler/UIxAppointmentEditor.m sogo-1.3.16/UI/Scheduler/UIxAppointmentEditor.m
--- sogo-1.3.15a/UI/Scheduler/UIxAppointmentEditor.m	2012-05-18 17:27:15.000000000 +0200
+++ sogo-1.3.16/UI/Scheduler/UIxAppointmentEditor.m	2012-06-07 17:40:53.000000000 +0200
@@ -513,7 +513,7 @@
 		       [dateFormatter formattedTime: eventStartDate], @"startTime",
 		       [dateFormatter formattedDate: eventEndDate], @"endDate",
 		       [dateFormatter formattedTime: eventEndDate], @"endTime",
-		       ([event hasRecurrenceRules] ? @"1": @"0"), @"isRecurring",
+                     //([event hasRecurrenceRules] ? @"1": @"0"), @"isRecurring",
 		       ([event isAllDay] ? @"1": @"0"), @"isAllDay",
 		       [event summary], @"summary",
 		       [event location], @"location",
diff -Nru sogo-1.3.15a/UI/Scheduler/UIxCalView.m sogo-1.3.16/UI/Scheduler/UIxCalView.m
--- sogo-1.3.15a/UI/Scheduler/UIxCalView.m	2012-05-18 17:27:15.000000000 +0200
+++ sogo-1.3.16/UI/Scheduler/UIxCalView.m	2012-06-07 17:40:53.000000000 +0200
@@ -118,7 +118,7 @@
 - (NSArray *) filterAppointments:(NSArray *) _apts
 {
   NSMutableArray *filtered;
-  unsigned i, count, p, pCount;
+  NSUInteger i, count, p, pCount;
   NSString *email, *partmailsString, *state, *pEmail;
   NSDictionary *info, *primaryIdentity;
   NSArray *partmails, *partstates;
@@ -370,7 +370,7 @@
 {
   NSArray        *apts;
   NSMutableArray *filtered;
-  unsigned       i, count;
+  NSUInteger     i, count;
 
   if (allDayApts)
     return allDayApts;
@@ -532,7 +532,8 @@
   NSString *uidsString, *loc, *prevMethod, *userFolderID;
   id <WOActionResults> r;
   BOOL useGroups;
-  unsigned index;
+  NSUInteger index;
+
 
   uidsString = [self queryParameterForKey: @"userUIDString"];
   uidsString = [uidsString stringByTrimmingSpaces];
diff -Nru sogo-1.3.15a/UI/Scheduler/UIxComponentEditor.m sogo-1.3.16/UI/Scheduler/UIxComponentEditor.m
--- sogo-1.3.15a/UI/Scheduler/UIxComponentEditor.m	2012-05-18 17:27:15.000000000 +0200
+++ sogo-1.3.16/UI/Scheduler/UIxComponentEditor.m	2012-06-07 17:40:53.000000000 +0200
@@ -525,7 +525,7 @@
   iCalTrigger *aTrigger;
   NSString *duration, *quantity;
   unichar c;
-  unsigned int i;
+  NSUInteger i;
 
   if ([component hasAlarms])
     {
@@ -1289,7 +1289,7 @@
   NSString *currentOwner;
   SOGoAppointmentFolder *currentCalendar;
   SOGoUser *currentUser;
-  unsigned i;
+  NSUInteger i;
 
   calendars = [self calendarList];
   owners = [NSMutableArray arrayWithCapacity: [calendars count]];
@@ -1562,7 +1562,7 @@
 {
   NSString *cycleRep;
   NSArray *cycles;
-  unsigned i, count;
+  NSUInteger i, count;
 
   if (!_rrule)
     return [[self cycles] objectAtIndex:0];
@@ -1721,7 +1721,7 @@
 //   s = [self queryParameterForKey:_qp];
 //   if(s && [s length] > 0) {
 //     NSArray *es;
-//     unsigned i, count;
+//     NSUInteger i, count;
     
 //     es = [s componentsSeparatedByString: @","];
 //     count = [es count];
@@ -1766,7 +1766,7 @@
 - (void) _handleAttendeesEdition
 {
   NSMutableArray *newAttendees;
-  unsigned int count, max;
+  NSUInteger count, max;
   NSString *currentEmail;
   iCalPerson *currentAttendee;
   NSString *json, *role, *partstat;
@@ -2189,7 +2189,7 @@
       iCalTrigger *aTrigger;
       iCalAlarm *anAlarm;
       NSString *aValue;
-      unsigned int index;
+      NSUInteger index;
 
       anAlarm = [iCalAlarm new];
 
diff -Nru sogo-1.3.15a/UI/WebServerResources/ContactsUI.js sogo-1.3.16/UI/WebServerResources/ContactsUI.js
--- sogo-1.3.15a/UI/WebServerResources/ContactsUI.js	2012-05-18 17:27:15.000000000 +0200
+++ sogo-1.3.16/UI/WebServerResources/ContactsUI.js	2012-06-07 17:40:55.000000000 +0200
@@ -12,25 +12,6 @@
     deleteContactsRequestCount: null
 };
 
-function validateEditorInput(sender) {
-    var errortext = "";
-    var field;
-  
-    field = document.pageform.subject;
-    if (field.value == "")
-        errortext = errortext + labels.error_missingsubject + "\n";
-
-    if (!hasRecipients())
-        errortext = errortext + labels.error_missingrecipients + "\n";
-  
-    if (errortext.length > 0) {
-        alert(labels.error_validationfailed + ":\n"
-              + errortext);
-        return false;
-    }
-    return true;
-}
-
 function openContactsFolder(contactsFolder, reload, idx) {
     if ((contactsFolder && contactsFolder != Contact.currentAddressBook)
         || reload) {
@@ -799,13 +780,21 @@
 }
 function validateUploadForm () {
     rc = false;
-    if ($("contactsFile").value.length)
+    if ($("contactsFile").value.length) {
+      var btn = jQuery('#uploadSubmit');
+      jQuery('#uploadCancel').fadeOut('fast');
+      btn.addClass("disabled");
+      btn.children('span').text(_('Uploading'));
       rc = true;
+    }
     return rc;
 }
 function uploadCompleted(response) {
     data = response.evalJSON(true);
-
+    jQuery('#uploadCancel').show();
+    var btn = jQuery('#uploadSubmit');
+    btn.removeClass("disabled");
+    btn.children('span').text(_('Upload'));
     var div = $("uploadResults");
     if (data.imported <= 0)
         $("uploadResultsContent").update(_("An error occured while importing contacts."));
diff -Nru sogo-1.3.15a/UI/WebServerResources/SchedulerUI.js sogo-1.3.16/UI/WebServerResources/SchedulerUI.js
--- sogo-1.3.15a/UI/WebServerResources/SchedulerUI.js	2012-05-18 17:27:15.000000000 +0200
+++ sogo-1.3.16/UI/WebServerResources/SchedulerUI.js	2012-06-07 17:40:55.000000000 +0200
@@ -2849,13 +2849,21 @@
 }
 function validateUploadForm() {
     rc = false;
-    if ($("calendarFile").value.length)
+    if ($("calendarFile").value.length) {
+      var btn = jQuery('#uploadSubmit');
+      jQuery('#uploadCancel').fadeOut('fast');
+      btn.addClass("disabled");
+      btn.children('span').text(_('Uploading'));
       rc = true;
+    }
     return rc;
 }
 function uploadCompleted(response) {
     data = response.evalJSON(true);
-
+    jQuery('#uploadCancel').show();
+    var btn = jQuery('#uploadSubmit');
+    btn.removeClass("disabled");
+    btn.children('span').text(_('Upload'));
     var div = $("uploadResults");
     if (data.imported < 0)
         $("uploadResultsContent").update(_("An error occurred while importing calendar."));
diff -Nru sogo-1.3.15a/UI/WebServerResources/UIxFilterEditor.js sogo-1.3.16/UI/WebServerResources/UIxFilterEditor.js
--- sogo-1.3.15a/UI/WebServerResources/UIxFilterEditor.js	2012-05-18 17:27:15.000000000 +0200
+++ sogo-1.3.16/UI/WebServerResources/UIxFilterEditor.js	2012-06-07 17:40:55.000000000 +0200
@@ -786,10 +786,20 @@
 function savePreferences(event) {
     var valid = true;
 
-    var rules = $$("DIV#filterRules DIV.rule");
-    if (rules.length == 0) {
-        onRuleAddClick(event);
-        valid = false;
+    var container = $('filterRulesContainer');
+    if (container.visible()) {
+        var rules = container.select("DIV#filterRules DIV.rule");
+        if (rules.length == 0) {
+            onRuleAddClick(event);
+            valid = false;
+        }
+        else {
+            var inputs = $$("DIV#filterRules input");
+            inputs.each(function(input) {
+                    if (input.hasClassName("_invalid"))
+                        valid = false;
+                });
+        }
     }
 
     var actions = $$("DIV#filterActions DIV.action");
@@ -799,14 +809,6 @@
     }
 
     if (valid) {
-        var inputs = $$("DIV#filterRules input");
-        inputs.each(function(input) {
-                if (input.hasClassName("_invalid"))
-                    valid = false;
-            });
-    }
-
-    if (valid) {
         if (window.opener) {
             window.opener.updateFilterFromEditor(filterId, Object.toJSON(filter));
         }
diff -Nru sogo-1.3.15a/UI/WebServerResources/UIxMailEditor.css sogo-1.3.16/UI/WebServerResources/UIxMailEditor.css
--- sogo-1.3.15a/UI/WebServerResources/UIxMailEditor.css	2012-05-18 17:27:15.000000000 +0200
+++ sogo-1.3.16/UI/WebServerResources/UIxMailEditor.css	2012-06-07 17:40:55.000000000 +0200
@@ -237,7 +237,7 @@
 
 DIV.contactSelection
 {
-  z-index: 10;
+  z-index: 1;
   background: inherit;
   position: absolute;
   bottom: 0em;
diff -Nru sogo-1.3.15a/UI/WebServerResources/UIxMailEditor.js sogo-1.3.16/UI/WebServerResources/UIxMailEditor.js
--- sogo-1.3.15a/UI/WebServerResources/UIxMailEditor.js	2012-05-18 17:27:15.000000000 +0200
+++ sogo-1.3.16/UI/WebServerResources/UIxMailEditor.js	2012-06-07 17:40:55.000000000 +0200
@@ -107,51 +107,45 @@
 
 /* mail editor */
 
-function validateEditorInput() {
-    var errortext = "";
-    var field;
-   
-    field = document.pageform.subject;
-    if (field.value == "")
-        errortext = errortext + _("error_missingsubject") + "\n";
-
-    if (!hasRecipients())
-        errortext = errortext + _("error_missingrecipients") + "\n";
-   
-    if (errortext.length > 0) {
-        alert(_("error_validationfailed") + ":\n" + errortext);
-        return false;
+function onValidate(onSuccess) {
+    if (document.pageform.action != "send") {
+        
+        if (!hasRecipients()) {
+            showAlertDialog(_("error_missingrecipients"));
+        }
+        else if (document.pageform.subject.value == "") {
+            showConfirmDialog(_("Warning"), _("error_missingsubject"), onValidateDone.bind(this, onSuccess), null, _("Send anyway"), _("Cancel"));
+        }
+        else {
+            onValidateDone(onSuccess);
+        }
     }
-
-    return true;
 }
 
-function onValidate(event) {
-    var rc = false;
-
-    if (document.pageform.action != "send"
-        && validateEditorInput()) {
-        var input = currentAttachmentInput();
-        if (input)
-            input.parentNode.removeChild(input);
-
-        var toolbar = document.getElementById("toolbar");
-        if (!document.busyAnim)
-            document.busyAnim = startAnimation(toolbar);
-  
-        var lastRow = $("lastRow");
-        lastRow.down("select").name = "popup_last";
+function onValidateDone(onSuccess) {
+    var input = currentAttachmentInput();
+    if (input)
+        input.parentNode.removeChild(input);
+
+    var toolbar = document.getElementById("toolbar");
+    if (!document.busyAnim)
+        document.busyAnim = startAnimation(toolbar);
     
-        window.shouldPreserve = true;
-
-        document.pageform.action = "send";
-
-        AIM.submit($(document.pageform), {'onComplete' : onPostComplete});
+    var lastRow = $("lastRow");
+    lastRow.down("select").name = "popup_last";
+    
+    window.shouldPreserve = true;
+    
+    document.pageform.action = "send";
+    
+    AIM.submit($(document.pageform), {'onComplete' : onPostComplete});
+    
+    if (typeof onSuccess == 'function')
+        onSuccess();
 
-        rc = true;
-    }
+    disposeDialog();
 
-    return rc;
+    return true;
 }
 
 function onPostComplete(response) {
@@ -184,9 +178,9 @@
 }
 
 function clickedEditorSend() {
-    if (onValidate()) {
-        document.pageform.submit();
-    }
+    onValidate(function() {
+            document.pageform.submit();
+        });
 
     return false;
 }
diff -Nru sogo-1.3.15a/UI/WebServerResources/generic.js sogo-1.3.16/UI/WebServerResources/generic.js
--- sogo-1.3.15a/UI/WebServerResources/generic.js	2012-05-18 17:27:17.000000000 +0200
+++ sogo-1.3.16/UI/WebServerResources/generic.js	2012-06-07 17:40:57.000000000 +0200
@@ -47,9 +47,17 @@
 // Email validation regexp
 var emailRE = /^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i;
 
+
+/* This function enables the execution of a wrapper function just before the
+ user callback is executed. The wrapper in question executes "preventDefault"
+ to the event parameter if and only when "this" is a link. The goal of this
+ operation is to prevent links with attached even handlers to be followed,
+ including those with an href set to "#". */
 function clickEventWrapper(functionRef) {
     function button_clickEventWrapper(event) {
-        preventDefault(event);
+        if (this.tagName == "A") {
+            preventDefault(event);
+        }
         return functionRef.apply(this, [event]);
     }
 
diff -Nru sogo-1.3.15a/Version sogo-1.3.16/Version
--- sogo-1.3.15a/Version	2012-05-18 17:27:17.000000000 +0200
+++ sogo-1.3.16/Version	2012-06-07 17:40:57.000000000 +0200
@@ -4,4 +4,4 @@
 
 MAJOR_VERSION=1
 MINOR_VERSION=3
-SUBMINOR_VERSION=15
+SUBMINOR_VERSION=16
diff -Nru sogo-1.3.15a/debian/changelog sogo-1.3.16/debian/changelog
--- sogo-1.3.15a/debian/changelog	2012-07-06 02:30:44.000000000 +0200
+++ sogo-1.3.16/debian/changelog	2012-07-06 02:32:39.000000000 +0200
@@ -1,3 +1,15 @@
+sogo (1.3.16-1) unstable; urgency=low
+
+  * New upstream release. (Closes: #677119)
+    - 0004-Add-support-for-GnuTLS.patch: Updated to new hashes in 1.3.16.
+    - 0007-GNUstep-1.24-fix.patch: Removed, was backported from upstream.
+  * Do not assume deluser is available in postrm. (Closes: #678099)
+  * Suggest postgresql or mysql-server. (Closes: #678047)
+  * Build with hardening
+    - 0007-Compile-daemon-as-PIE.patch: Compile the daemon as a PIE.
+
+ -- Jeroen Dekkers <jeroen@dekkers.ch>  Sat, 30 Jun 2012 02:55:17 +0200
+
 sogo (1.3.15a-2) unstable; urgency=low
 
   * 0007-GNUstep-1.24-fix.patch:
diff -Nru sogo-1.3.15a/debian/control sogo-1.3.16/debian/control
--- sogo-1.3.15a/debian/control	2012-07-06 02:30:44.000000000 +0200
+++ sogo-1.3.16/debian/control	2012-07-06 02:32:39.000000000 +0200
@@ -11,6 +11,7 @@
 Package: sogo
 Architecture: any
 Depends: ${shlibs:Depends}, ${misc:Depends}, tmpreaper, sogo-common (= ${source:Version}), adduser, zip
+Suggests: postgresql | mysql-server
 Description: Scalable groupware server
  SOGo is a groupware server built around OpenGroupware.org (OGo) and
  the SOPE application server with focus on scalability. It has many
diff -Nru sogo-1.3.15a/debian/copyright sogo-1.3.16/debian/copyright
--- sogo-1.3.15a/debian/copyright	2012-07-06 02:30:44.000000000 +0200
+++ sogo-1.3.16/debian/copyright	2012-07-06 02:32:39.000000000 +0200
@@ -15,6 +15,10 @@
 	   2004-2005 OpenGroupware.org
 License: LGPL-2+
 
+Files: SoObjects/SOGo/NSData+Crypto.m
+Copyright: 2001, 2005 Niels Möller 
+License: LGPL-2+
+
 Files: UI/WebServerResources/dtree.*
 Copyright: 2002-2003 Geir Landrö
 License: 
diff -Nru sogo-1.3.15a/debian/patches/0004-Add-support-for-GnuTLS.patch sogo-1.3.16/debian/patches/0004-Add-support-for-GnuTLS.patch
--- sogo-1.3.15a/debian/patches/0004-Add-support-for-GnuTLS.patch	2012-07-06 02:30:44.000000000 +0200
+++ sogo-1.3.16/debian/patches/0004-Add-support-for-GnuTLS.patch	2012-07-06 02:32:39.000000000 +0200
@@ -1,18 +1,20 @@
 From: Jeroen Dekkers <jeroen@dekkers.ch>
-Date: Sat, 24 Mar 2012 15:39:02 +0100
+Date: Sat, 30 Jun 2012 01:55:46 +0200
 Subject: Add support for GnuTLS
 
 ---
- SoObjects/SOGo/GNUmakefile.preamble          |   10 +++-
- SoObjects/SOGo/NSString+Utilities.m          |   42 +++++++++++++++++
- Tests/Unit/GNUmakefile                       |    1 +
- Tests/Unit/TestNSString+MD5SHA1.m            |   64 ++++++++++++++++++++++++++
- UI/MailPartViewers/GNUmakefile.preamble      |    4 ++
- UI/MailPartViewers/UIxMailPartSignedViewer.m |   14 ++++++
- configure                                    |   36 +++++++++++----
- maintenance/dummytool.c                      |    7 +++
- 8 files changed, 168 insertions(+), 10 deletions(-)
- create mode 100644 Tests/Unit/TestNSString+MD5SHA1.m
+ SoObjects/SOGo/GNUmakefile.preamble          |   10 +-
+ SoObjects/SOGo/NSData+Crypto.m               |  216 +++++++++++++++++++++++++-
+ Tests/Unit/GNUmakefile                       |    2 +
+ Tests/Unit/TestNSData+Crypto.m               |  101 ++++++++++++
+ Tests/Unit/TestNSString+Crypto.m             |   64 ++++++++
+ UI/MailPartViewers/GNUmakefile.preamble      |    4 +
+ UI/MailPartViewers/UIxMailPartSignedViewer.m |   14 ++
+ configure                                    |   36 +++--
+ maintenance/dummytool.c                      |    7 +
+ 9 files changed, 441 insertions(+), 13 deletions(-)
+ create mode 100644 Tests/Unit/TestNSData+Crypto.m
+ create mode 100644 Tests/Unit/TestNSString+Crypto.m
  create mode 100644 UI/MailPartViewers/GNUmakefile.preamble
  create mode 100644 maintenance/dummytool.c
 
@@ -37,114 +39,442 @@
  
  ifeq ($(findstring openbsd, $(GNUSTEP_HOST_OS)), openbsd)
  SOGo_LIBRARIES_DEPEND_UPON += -lcrypto
-diff --git a/SoObjects/SOGo/NSString+Utilities.m b/SoObjects/SOGo/NSString+Utilities.m
-index 9cfe278..914d76b 100644
---- a/SoObjects/SOGo/NSString+Utilities.m
-+++ b/SoObjects/SOGo/NSString+Utilities.m
-@@ -1,6 +1,7 @@
- /* NSString+Utilities.m - this file is part of SOGo
+diff --git a/SoObjects/SOGo/NSData+Crypto.m b/SoObjects/SOGo/NSData+Crypto.m
+index c50ad96..e42ee3e 100644
+--- a/SoObjects/SOGo/NSData+Crypto.m
++++ b/SoObjects/SOGo/NSData+Crypto.m
+@@ -2,6 +2,7 @@
   *
-  * Copyright (C) 2006-2011 Inverse inc.
-+ * Copyright (C) 2012 Jeroen Dekkers <jeroen@dekkers.ch>
+  * Copyright (C) 2012 Nicolas Höft
+  * Copyright (C) 2012 Inverse inc.
++ * Copyright (C) 2012 Jeroen Dekkers
   *
-  * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
-  *         Ludovic Marcotte <lmarcotte@inverse.ca>
-@@ -47,9 +48,16 @@
+  * Author: Nicolas Höft
+  *         Inverse inc.
+@@ -33,15 +34,30 @@
  
  #define _XOPEN_SOURCE 1
  #include <unistd.h>
++
 +#ifdef HAVE_GNUTLS
++#include <stdint.h>
 +#include <gnutls/gnutls.h>
 +#include <gnutls/crypto.h>
 +#define MD5_DIGEST_LENGTH 16
 +#define SHA_DIGEST_LENGTH 20
++#define SHA256_DIGEST_LENGTH 32
++#define SHA512_DIGEST_LENGTH 64
 +#else
  #include <openssl/evp.h>
  #include <openssl/md5.h>
  #include <openssl/sha.h>
 +#endif
  
- static NSMutableCharacterSet *urlNonEndingChars = nil;
- static NSMutableCharacterSet *urlAfterEndingChars = nil;
-@@ -549,11 +557,28 @@ static int cssEscapingCount;
-   unsigned char md[MD5_DIGEST_LENGTH];
-   char buf[80];
-   int i;
+ #import <Foundation/NSArray.h>
+ #import <NGExtensions/NGBase64Coding.h>
+ #import "NSData+Crypto.h"
+ 
+-unsigned charTo4Bits(char c);
++static unsigned charTo4Bits(char c);
 +#ifdef HAVE_GNUTLS
-+  static BOOL didGlobalInit = NO;
++static BOOL check_gnutls_init();
++static void _nettle_md5_compress(uint32_t *digest, const uint8_t *input);
 +#endif
-   
-   memset(md, 0, MD5_DIGEST_LENGTH);
-   memset(buf, 0, 80);
-   
+ 
+ 
+ @implementation NSData (SOGoCryptoExtension)
+@@ -228,7 +244,13 @@ unsigned charTo4Bits(char c);
+   unsigned char md5[MD5_DIGEST_LENGTH];
+   memset(md5, 0, MD5_DIGEST_LENGTH);
+ 
 +#ifdef HAVE_GNUTLS
-+  if (!didGlobalInit) {
-+    /* Global system initialization*/
-+    if (gnutls_global_init()) {
-+      [self release];
-+      return nil;
-+    }
-+
-+    didGlobalInit = YES;
-+  }
-+
-+  gnutls_hash_fast (GNUTLS_DIG_MD5, (const void *)[self UTF8String], strlen([self UTF8String]), md);
++  if (!check_gnutls_init())
++    return nil;
++  gnutls_hash_fast (GNUTLS_DIG_MD5, [self bytes], [self length], md5);
 +#else
-   EVP_Digest((const void *) [self UTF8String], strlen([self UTF8String]), md, NULL, EVP_md5(), NULL);
+   MD5([self bytes], [self length], md5);
 +#endif
-   for (i = 0; i < MD5_DIGEST_LENGTH; i++)
-     sprintf(&(buf[i*2]), "%02x", md[i]);
-   
-@@ -565,11 +590,28 @@ static int cssEscapingCount;
-   unsigned char sha[SHA_DIGEST_LENGTH];
-   char buf[80];
-   int i;
+ 
+   return [NSData dataWithBytes: md5  length: MD5_DIGEST_LENGTH];
+ }
+@@ -247,8 +269,12 @@ unsigned charTo4Bits(char c);
+  */
+ - (NSData *) asCramMD5
+ {
+-  
++#ifdef HAVE_GNUTLS
++  const uint32_t init_digest[4] = {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
++  uint32_t digest[4];
++#else
+   MD5_CTX ctx;
++#endif
+   unsigned char inner[64];
+   unsigned char outer[64];
+   unsigned char result[32];
+@@ -286,6 +312,27 @@ unsigned charTo4Bits(char c);
+     *p = (c) >> 24 & 0xff; p++; \
+ }
+ 
 +#ifdef HAVE_GNUTLS
-+  static BOOL didGlobalInit = NO;
++  // generate first set of context bytes from outer data
++  memcpy(digest, init_digest, sizeof(digest));
++  _nettle_md5_compress(digest, outer);
++
++  r = result;
++  // convert this to correct binary data according to RFC 1321
++  CDPUT(r, digest[0]);
++  CDPUT(r, digest[1]);
++  CDPUT(r, digest[2]);
++  CDPUT(r, digest[3]);
++
++  // second set with inner data is appended to result string
++  memcpy(digest, init_digest, sizeof(digest));
++  _nettle_md5_compress(digest, inner);
++  // convert this to correct binary data
++  CDPUT(r, digest[0]);
++  CDPUT(r, digest[1]);
++  CDPUT(r, digest[2]);
++  CDPUT(r, digest[3]);
++#else
+   // generate first set of context bytes from outer data
+   MD5_Init(&ctx);
+   MD5_Transform(&ctx, outer);
+@@ -304,6 +351,7 @@ unsigned charTo4Bits(char c);
+   CDPUT(r, ctx.B);
+   CDPUT(r, ctx.C);
+   CDPUT(r, ctx.D);
 +#endif
-   
+ 
+   return [NSData dataWithBytes: result length: 32];
+ }
+@@ -318,7 +366,13 @@ unsigned charTo4Bits(char c);
+   unsigned char sha[SHA_DIGEST_LENGTH];
    memset(sha, 0, SHA_DIGEST_LENGTH);
-   memset(buf, 0, 80);
-   
+ 
 +#ifdef HAVE_GNUTLS
++  if (!check_gnutls_init())
++    return nil;
++  gnutls_hash_fast (GNUTLS_DIG_SHA1, [self bytes], [self length], sha);
++#else
+   SHA1([self bytes], [self length], sha);
++#endif
+ 
+   return [NSData dataWithBytes: sha  length: SHA_DIGEST_LENGTH];
+ }
+@@ -333,7 +387,13 @@ unsigned charTo4Bits(char c);
+   unsigned char sha[SHA256_DIGEST_LENGTH];
+   memset(sha, 0, SHA256_DIGEST_LENGTH);
+ 
++#ifdef HAVE_GNUTLS
++  if (!check_gnutls_init())
++    return nil;
++  gnutls_hash_fast (GNUTLS_DIG_SHA256, [self bytes], [self length], sha);
++#else
+   SHA256([self bytes], [self length], sha);
++#endif
+ 
+   return [NSData dataWithBytes: sha  length: SHA256_DIGEST_LENGTH];
+ }
+@@ -348,7 +408,13 @@ unsigned charTo4Bits(char c);
+   unsigned char sha[SHA512_DIGEST_LENGTH];
+   memset(sha, 0, SHA512_DIGEST_LENGTH);
+ 
++#ifdef HAVE_GNUTLS
++  if (!check_gnutls_init())
++    return nil;
++  gnutls_hash_fast (GNUTLS_DIG_SHA512, [self bytes], [self length], sha);
++#else
+   SHA512([self bytes], [self length], sha);
++#endif
+ 
+   return [NSData dataWithBytes: sha  length: SHA512_DIGEST_LENGTH];
+ }
+@@ -597,7 +663,7 @@ unsigned charTo4Bits(char c);
+ 
+ @end
+ 
+-unsigned charTo4Bits(char c)
++static unsigned charTo4Bits(char c)
+ {
+   unsigned bits = 0;
+   if (c > '/' && c < ':')
+@@ -618,3 +684,147 @@ unsigned charTo4Bits(char c)
+     }
+   return bits;
+ }
++
++#ifdef HAVE_GNUTLS
++static BOOL didGlobalInit = NO;
++
++static BOOL check_gnutls_init() {
 +  if (!didGlobalInit) {
 +    /* Global system initialization*/
 +    if (gnutls_global_init()) {
-+      [self release];
-+      return nil;
++      return NO;
 +    }
 +
 +    didGlobalInit = YES;
 +  }
 +
-+  gnutls_hash_fast (GNUTLS_DIG_SHA1, (const void *)[self UTF8String], strlen([self UTF8String]), sha);
-+#else
-   SHA1((const void *)[self UTF8String], strlen([self UTF8String]), sha);
++  return YES;
++}
++
++/* nettle, low-level cryptographics library
++ *
++ * Copyright (C) 2001, 2005 Niels Möller
++ *
++ * The nettle library is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as published by
++ * the Free Software Foundation; either version 2.1 of the License, or (at your
++ * option) any later version.
++ *
++ * The nettle library 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 Lesser General Public
++ * License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * along with the nettle library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
++ * MA 02111-1307, USA.
++ */
++
++/* Based on public domain code hacked by Colin Plumb, Andrew Kuchling, and
++ * Niels Möller. */
++
++#define LE_READ_UINT32(p)			\
++(  (((uint32_t) (p)[3]) << 24)			\
++ | (((uint32_t) (p)[2]) << 16)			\
++ | (((uint32_t) (p)[1]) << 8)			\
++ |  ((uint32_t) (p)[0]))
++
++/* MD5 functions */
++#define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
++#define F2(x, y, z) F1((z), (x), (y))
++#define F3(x, y, z) ((x) ^ (y) ^ (z))
++#define F4(x, y, z) ((y) ^ ((x) | ~(z)))
++
++#define ROUND(f, w, x, y, z, data, s) \
++( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
++
++static void
++_nettle_md5_compress(uint32_t *digest, const uint8_t *input)
++{
++  uint32_t data[MD5_DIGEST_LENGTH];
++  uint32_t a, b, c, d;
++  unsigned i;
++
++  for (i = 0; i < MD5_DIGEST_LENGTH; i++, input += 4)
++    data[i] = LE_READ_UINT32(input);
++
++  a = digest[0];
++  b = digest[1];
++  c = digest[2];
++  d = digest[3];
++
++  ROUND(F1, a, b, c, d, data[ 0] + 0xd76aa478, 7);
++  ROUND(F1, d, a, b, c, data[ 1] + 0xe8c7b756, 12);
++  ROUND(F1, c, d, a, b, data[ 2] + 0x242070db, 17);
++  ROUND(F1, b, c, d, a, data[ 3] + 0xc1bdceee, 22);
++  ROUND(F1, a, b, c, d, data[ 4] + 0xf57c0faf, 7);
++  ROUND(F1, d, a, b, c, data[ 5] + 0x4787c62a, 12);
++  ROUND(F1, c, d, a, b, data[ 6] + 0xa8304613, 17);
++  ROUND(F1, b, c, d, a, data[ 7] + 0xfd469501, 22);
++  ROUND(F1, a, b, c, d, data[ 8] + 0x698098d8, 7);
++  ROUND(F1, d, a, b, c, data[ 9] + 0x8b44f7af, 12);
++  ROUND(F1, c, d, a, b, data[10] + 0xffff5bb1, 17);
++  ROUND(F1, b, c, d, a, data[11] + 0x895cd7be, 22);
++  ROUND(F1, a, b, c, d, data[12] + 0x6b901122, 7);
++  ROUND(F1, d, a, b, c, data[13] + 0xfd987193, 12);
++  ROUND(F1, c, d, a, b, data[14] + 0xa679438e, 17);
++  ROUND(F1, b, c, d, a, data[15] + 0x49b40821, 22);
++
++  ROUND(F2, a, b, c, d, data[ 1] + 0xf61e2562, 5);
++  ROUND(F2, d, a, b, c, data[ 6] + 0xc040b340, 9);
++  ROUND(F2, c, d, a, b, data[11] + 0x265e5a51, 14);
++  ROUND(F2, b, c, d, a, data[ 0] + 0xe9b6c7aa, 20);
++  ROUND(F2, a, b, c, d, data[ 5] + 0xd62f105d, 5);
++  ROUND(F2, d, a, b, c, data[10] + 0x02441453, 9);
++  ROUND(F2, c, d, a, b, data[15] + 0xd8a1e681, 14);
++  ROUND(F2, b, c, d, a, data[ 4] + 0xe7d3fbc8, 20);
++  ROUND(F2, a, b, c, d, data[ 9] + 0x21e1cde6, 5);
++  ROUND(F2, d, a, b, c, data[14] + 0xc33707d6, 9);
++  ROUND(F2, c, d, a, b, data[ 3] + 0xf4d50d87, 14);
++  ROUND(F2, b, c, d, a, data[ 8] + 0x455a14ed, 20);
++  ROUND(F2, a, b, c, d, data[13] + 0xa9e3e905, 5);
++  ROUND(F2, d, a, b, c, data[ 2] + 0xfcefa3f8, 9);
++  ROUND(F2, c, d, a, b, data[ 7] + 0x676f02d9, 14);
++  ROUND(F2, b, c, d, a, data[12] + 0x8d2a4c8a, 20);
++
++  ROUND(F3, a, b, c, d, data[ 5] + 0xfffa3942, 4);
++  ROUND(F3, d, a, b, c, data[ 8] + 0x8771f681, 11);
++  ROUND(F3, c, d, a, b, data[11] + 0x6d9d6122, 16);
++  ROUND(F3, b, c, d, a, data[14] + 0xfde5380c, 23);
++  ROUND(F3, a, b, c, d, data[ 1] + 0xa4beea44, 4);
++  ROUND(F3, d, a, b, c, data[ 4] + 0x4bdecfa9, 11);
++  ROUND(F3, c, d, a, b, data[ 7] + 0xf6bb4b60, 16);
++  ROUND(F3, b, c, d, a, data[10] + 0xbebfbc70, 23);
++  ROUND(F3, a, b, c, d, data[13] + 0x289b7ec6, 4);
++  ROUND(F3, d, a, b, c, data[ 0] + 0xeaa127fa, 11);
++  ROUND(F3, c, d, a, b, data[ 3] + 0xd4ef3085, 16);
++  ROUND(F3, b, c, d, a, data[ 6] + 0x04881d05, 23);
++  ROUND(F3, a, b, c, d, data[ 9] + 0xd9d4d039, 4);
++  ROUND(F3, d, a, b, c, data[12] + 0xe6db99e5, 11);
++  ROUND(F3, c, d, a, b, data[15] + 0x1fa27cf8, 16);
++  ROUND(F3, b, c, d, a, data[ 2] + 0xc4ac5665, 23);
++
++  ROUND(F4, a, b, c, d, data[ 0] + 0xf4292244, 6);
++  ROUND(F4, d, a, b, c, data[ 7] + 0x432aff97, 10);
++  ROUND(F4, c, d, a, b, data[14] + 0xab9423a7, 15);
++  ROUND(F4, b, c, d, a, data[ 5] + 0xfc93a039, 21);
++  ROUND(F4, a, b, c, d, data[12] + 0x655b59c3, 6);
++  ROUND(F4, d, a, b, c, data[ 3] + 0x8f0ccc92, 10);
++  ROUND(F4, c, d, a, b, data[10] + 0xffeff47d, 15);
++  ROUND(F4, b, c, d, a, data[ 1] + 0x85845dd1, 21);
++  ROUND(F4, a, b, c, d, data[ 8] + 0x6fa87e4f, 6);
++  ROUND(F4, d, a, b, c, data[15] + 0xfe2ce6e0, 10);
++  ROUND(F4, c, d, a, b, data[ 6] + 0xa3014314, 15);
++  ROUND(F4, b, c, d, a, data[13] + 0x4e0811a1, 21);
++  ROUND(F4, a, b, c, d, data[ 4] + 0xf7537e82, 6);
++  ROUND(F4, d, a, b, c, data[11] + 0xbd3af235, 10);
++  ROUND(F4, c, d, a, b, data[ 2] + 0x2ad7d2bb, 15);
++  ROUND(F4, b, c, d, a, data[ 9] + 0xeb86d391, 21);
++
++  digest[0] += a;
++  digest[1] += b;
++  digest[2] += c;
++  digest[3] += d;
++}
 +#endif
-   for (i = 0; i < SHA_DIGEST_LENGTH; i++)
-     sprintf(&(buf[i*2]), "%02x", sha[i]);
-   
 diff --git a/Tests/Unit/GNUmakefile b/Tests/Unit/GNUmakefile
-index 6c54a19..01770c1 100644
+index 6c54a19..c95bd73 100644
 --- a/Tests/Unit/GNUmakefile
 +++ b/Tests/Unit/GNUmakefile
-@@ -22,6 +22,7 @@ $(TEST_TOOL)_OBJC_FILES += \
+@@ -22,6 +22,8 @@ $(TEST_TOOL)_OBJC_FILES += \
  	TestSBJsonParser.m \
  	\
  	TestNGMimeAddressHeaderFieldGenerator.m \
-+	TestNSString+MD5SHA1.m \
++	TestNSData+Crypto.m \
++	TestNSString+Crypto.m \
  	TestNSString+URLEscaping.m \
  	TestNSString+Utilities.m
  
-diff --git a/Tests/Unit/TestNSString+MD5SHA1.m b/Tests/Unit/TestNSString+MD5SHA1.m
+diff --git a/Tests/Unit/TestNSData+Crypto.m b/Tests/Unit/TestNSData+Crypto.m
+new file mode 100644
+index 0000000..6039a9a
+--- /dev/null
++++ b/Tests/Unit/TestNSData+Crypto.m
+@@ -0,0 +1,101 @@
++/* TestNSString+MD5SHA1.m - this file is part of SOGo
++ *
++ * Copyright (C) 2011, 2012 Jeroen Dekkers
++ *
++ * Author: Jeroen Dekkers <jeroen@dekkers.ch>
++ *
++ * 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 2, 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.
++ */
++
++#import <Foundation/NSString.h>
++#import <Foundation/NSData.h>
++#import "SOGo/NSData+Crypto.h"
++
++#import "SOGoTest.h"
++
++@interface TestNSString_plus_Crypto : SOGoTest
++@end
++
++@implementation TestNSString_plus_Crypto
++
++- (void) test_stringCrypto
++{
++  const char *inStrings[] = { "SOGoSOGoSOGoSOGo", "éléphant", "2š", NULL };
++  const char **inString;
++  NSString *MD5Strings[] = { @"d3e8072c49511f099d254cc740c7e12a", @"bc6a1535589d6c3cf7999ac37018c11e", @"886ae9b58817fb8a63902feefcd18812" };
++  NSString *CramMD5Strings[] = { @"807cf6d4995482060b2e9b1bc3fe1507a42c51dc97d86302b460f7878f0551e2", @"72a6cb4f15711350c3e3d83a9cb631eb0dcc06e56776bed15766e65e0fdb7694",
++				 @"14bef22dd8c749f6ff3ebbfa51261291e3c1dc42e3dc13ae3771d01de8e53ccd" };
++  NSString *SHA1Strings[] = { @"b7d891e0f3b42898fa66627b5cfa3d80501bae46", @"99a02f8802f8ea7e3ad91c4cc4d3ef5a7257c88f", @"32b89f3a9e6078db554cdd39f8571c09de7e8b21" };
++  NSString *SHA256Strings[] = { @"3d5c087342ad6208e7f4bc353c5e739dcd14137f6e4159779347fea2e7f562bf", @"c941ae685f62cbe7bb47d0791af7154788fd9e873e5c57fd2449d1454ed5b16f",
++				@"f89a911feceaf3d9c28f4e431edff50c265933102476b1814f83704a7bc46890" };
++  NSString *SHA512Strings[] = { @"e003b24f05d1b007e5f5a87f726668cb47301d1366cd8d8632646483b1e570335feae34e1e88213a53bab78a876eb805317f290fbf71a1ac79d1275d4a24dee7",
++				@"c6f2bb64ee795ad613b4521cd65618d2a036ae6423513a22eddc1bb8a88e5486add61fc1f3a0fc592ce9c24598a23b4ec854f96ccdf73808f701dced2a9b0d64",
++				@"49d72f3626d6a56483b3cb4a6da336c423825dbe92d5e225ea2fd69fca1b28d8bceb1544b85847c4fac5c5e0c378b4384f2ac7c230c73dd389061d1b0198c14c" };
++  NSString **MD5String;
++  NSString **CramMD5String;
++  NSString **SHA1String;
++  NSString **SHA256String;
++  NSString **SHA512String;
++  NSData *result;
++  NSString *error;
++
++  inString = inStrings;
++  CramMD5String = CramMD5Strings;
++  MD5String = MD5Strings;
++  SHA1String = SHA1Strings;
++  SHA256String = SHA256Strings;
++  SHA512String = SHA512Strings;
++  while (*inString)
++    {
++      result = [[[NSString stringWithUTF8String: *inString] dataUsingEncoding: NSUTF8StringEncoding] asMD5];
++      error = [NSString stringWithFormat:
++                          @"string '%s' wrong MD5: '%@' (expected '%@')",
++                        *inString, result, *MD5String];
++      testWithMessage([[NSData encodeDataAsHexString: result] isEqualToString: *MD5String], error);
++
++      result = [[[NSString stringWithUTF8String: *inString] dataUsingEncoding: NSUTF8StringEncoding] asCramMD5];
++      error = [NSString stringWithFormat:
++                          @"string '%s' wrong CramMD5: '%@' (expected '%@')",
++                        *inString, result, *CramMD5String];
++      testWithMessage([[NSData encodeDataAsHexString: result] isEqualToString: *CramMD5String], error);
++
++      result = [[[NSString stringWithUTF8String: *inString] dataUsingEncoding: NSUTF8StringEncoding] asSHA1];
++      error = [NSString stringWithFormat:
++                          @"string '%s' wrong SHA1: '%@' (expected '%@')",
++                        *inString, result, *SHA1String];
++      testWithMessage([[NSData encodeDataAsHexString: result] isEqualToString: *SHA1String], error);
++
++      result = [[[NSString stringWithUTF8String: *inString] dataUsingEncoding: NSUTF8StringEncoding] asSHA256];
++      error = [NSString stringWithFormat:
++                          @"string '%s' wrong SHA256: '%@' (expected '%@')",
++                        *inString, result, *SHA256String];
++      testWithMessage([[NSData encodeDataAsHexString: result] isEqualToString: *SHA256String], error);
++
++      result = [[[NSString stringWithUTF8String: *inString] dataUsingEncoding: NSUTF8StringEncoding] asSHA512];
++      error = [NSString stringWithFormat:
++                          @"string '%s' wrong SHA512: '%@' (expected '%@')",
++                        *inString, result, *SHA512String];
++      testWithMessage([[NSData encodeDataAsHexString: result] isEqualToString: *SHA512String], error);
++      inString++;
++      MD5String++;
++      CramMD5String++;
++      SHA1String++;
++      SHA256String++;
++      SHA512String++;
++    }
++}
++
++@end
+diff --git a/Tests/Unit/TestNSString+Crypto.m b/Tests/Unit/TestNSString+Crypto.m
 new file mode 100644
-index 0000000..bfc186e
+index 0000000..f0a08c5
 --- /dev/null
-+++ b/Tests/Unit/TestNSString+MD5SHA1.m
++++ b/Tests/Unit/TestNSString+Crypto.m
 @@ -0,0 +1,64 @@
 +/* TestNSString+MD5SHA1.m - this file is part of SOGo
 + *
-+ * Copyright (C) 2011 Jeroen Dekkers
++ * Copyright (C) 2011, 2012 Jeroen Dekkers
 + *
 + * Author: Jeroen Dekkers <jeroen@dekkers.ch>
 + *
@@ -165,16 +495,16 @@
 + */
 +
 +#import <Foundation/NSString.h>
-+#import "SOGo/NSString+Utilities.h"
++#import "SOGo/NSString+Crypto.h"
 +
 +#import "SOGoTest.h"
 +
-+@interface TestNSString_plus_MD5SHA1 : SOGoTest
++@interface TestNSData_plus_Crypto : SOGoTest
 +@end
 +
-+@implementation TestNSString_plus_MD5SHA1
++@implementation TestNSData_plus_Crypto
 +
-+- (void) test_stringMD5SHA1
++- (void) test_dataCrypto
 +{
 +  const char *inStrings[] = { "SOGoSOGoSOGoSOGo", "éléphant", "2š", NULL };
 +  const char **inString;
@@ -217,7 +547,7 @@
 +BUNDLE_LIBS += -lcrypto
 +endif
 diff --git a/UI/MailPartViewers/UIxMailPartSignedViewer.m b/UI/MailPartViewers/UIxMailPartSignedViewer.m
-index 77aad8b..f1278c7 100644
+index 77aad8b..e707c4a 100644
 --- a/UI/MailPartViewers/UIxMailPartSignedViewer.m
 +++ b/UI/MailPartViewers/UIxMailPartSignedViewer.m
 @@ -22,10 +22,12 @@
@@ -253,7 +583,7 @@
 +
 +- (NSString *) validationMessage
 +{
-+  return @"Signature verification not implemented when using GnuTLS";
++  return @"Signature verification is not implemented when using GnuTLS";
 +}
 +#endif
  
diff -Nru sogo-1.3.15a/debian/patches/0006-Put-private-libraries-in-usr-lib-sogo.patch sogo-1.3.16/debian/patches/0006-Put-private-libraries-in-usr-lib-sogo.patch
--- sogo-1.3.15a/debian/patches/0006-Put-private-libraries-in-usr-lib-sogo.patch	2012-07-06 02:30:44.000000000 +0200
+++ sogo-1.3.16/debian/patches/0006-Put-private-libraries-in-usr-lib-sogo.patch	2012-07-06 02:32:39.000000000 +0200
@@ -132,7 +132,7 @@
  else
  include $(GNUSTEP_MAKEFILES)/framework.make
 diff --git a/SoObjects/SOGo/GNUmakefile b/SoObjects/SOGo/GNUmakefile
-index c099e3c..2ce8740 100644
+index da52efc..c4b0e25 100644
 --- a/SoObjects/SOGo/GNUmakefile
 +++ b/SoObjects/SOGo/GNUmakefile
 @@ -11,6 +11,8 @@ SOGo_INSTALL_DIR = $(DESTDIR)$(GNUSTEP_$(GNUSTEP_INSTALLATION_DOMAIN)_FRAMEWORKS
@@ -144,7 +144,7 @@
  SOGo_HEADER_FILES = \
  	SOGoBuild.h \
  	SOGoProductLoader.h		\
-@@ -161,6 +163,7 @@ ADDITIONAL_LDFLAGS += -lmemcached
+@@ -165,6 +167,7 @@ ADDITIONAL_LDFLAGS += -lmemcached
  ifneq ($(FHS_INSTALL_ROOT),)
  GNUSTEP_HEADERS=$(DESTDIR)$(FHS_INSTALL_ROOT)/include
  endif
@@ -179,10 +179,10 @@
  	-L../../SOPE/GDLContentStore/$(GNUSTEP_OBJ_DIR)/ -lGDLContentStore \
  	-L../../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ -lNGCards \
 diff --git a/Tests/Unit/GNUmakefile b/Tests/Unit/GNUmakefile
-index 01770c1..42df04c 100644
+index c95bd73..df22fe7 100644
 --- a/Tests/Unit/GNUmakefile
 +++ b/Tests/Unit/GNUmakefile
-@@ -32,9 +32,9 @@ $(TEST_TOOL)_CPPFLAGS += \
+@@ -33,9 +33,9 @@ $(TEST_TOOL)_CPPFLAGS += \
  	-Wall -D_GNU_SOURCE -I../../SOPE/ -I../../SoObjects/ -I../../UI/
  
  ADDITIONAL_LIB_DIRS += \
diff -Nru sogo-1.3.15a/debian/patches/0007-Compile-daemon-as-PIE.patch sogo-1.3.16/debian/patches/0007-Compile-daemon-as-PIE.patch
--- sogo-1.3.15a/debian/patches/0007-Compile-daemon-as-PIE.patch	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian/patches/0007-Compile-daemon-as-PIE.patch	2012-07-06 02:32:39.000000000 +0200
@@ -0,0 +1,24 @@
+From: Jeroen Dekkers <jeroen@dekkers.ch>
+Date: Sat, 30 Jun 2012 02:49:20 +0200
+Subject: Compile daemon as PIE
+
+---
+ Main/GNUmakefile |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Main/GNUmakefile b/Main/GNUmakefile
+index 4b61d72..835ef23 100644
+--- a/Main/GNUmakefile
++++ b/Main/GNUmakefile
+@@ -4,9 +4,10 @@ include ../config.make
+ include $(GNUSTEP_MAKEFILES)/common.make
+ include ../Version
+ 
++ADDITIONAL_OBJCFLAGS += -fPIE
+ ADDITIONAL_INCLUDE_DIRS += 
+ ADDITIONAL_LIB_DIRS += -L../SOPE/GDLContentStore/obj/
+-ADDITIONAL_LDFLAGS += -Wl,--no-as-needed -Wl,--rpath,/usr/lib/sogo
++ADDITIONAL_LDFLAGS += -Wl,--no-as-needed -Wl,--rpath,/usr/lib/sogo -fPIE -pie
+ 
+ SOGOD     = sogod
+ TOOL_NAME = $(SOGOD)
diff -Nru sogo-1.3.15a/debian/patches/0007-GNUstep-1.24-fix.patch sogo-1.3.16/debian/patches/0007-GNUstep-1.24-fix.patch
--- sogo-1.3.15a/debian/patches/0007-GNUstep-1.24-fix.patch	2012-07-06 02:30:44.000000000 +0200
+++ sogo-1.3.16/debian/patches/0007-GNUstep-1.24-fix.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,322 +0,0 @@
-From: Ludovic Marcotte <lmarcotte@inverse.ca>
-Date: Tue, 29 May 2012 18:56:15 +0000
-Subject: GNUstep 1.24 fix
-
-Origin: upstream, http://mtn.inverse.ca/revision/diff/1e79eab4c546452715e5171f1c326b7d36f1c195/with/99dc7d9dce88b8a323b1e7aab60de99ed2bfda60
----
- SOPE/NGCards/CardGroup.m                          |    6 +++---
- SoObjects/Mailer/SOGoMailObject+Draft.m           |    8 ++++----
- SoObjects/SOGo/NSString+Utilities.m               |    3 ++-
- UI/MailPartViewers/UIxMailPartAlternativeViewer.m |   18 +++++++++---------
- UI/MailerUI/UIxMailEditor.m                       |    2 +-
- UI/MailerUI/UIxMailMainFrame.m                    |   14 +++++++-------
- UI/Scheduler/UIxCalView.m                         |    7 ++++---
- UI/Scheduler/UIxComponentEditor.m                 |   12 ++++++------
- 8 files changed, 36 insertions(+), 34 deletions(-)
-
-diff --git a/SOPE/NGCards/CardGroup.m b/SOPE/NGCards/CardGroup.m
-index d19b1a3..7022571 100644
---- a/SOPE/NGCards/CardGroup.m
-+++ b/SOPE/NGCards/CardGroup.m
-@@ -354,7 +354,7 @@ static NGCardsSaxHandler *sax = nil;
- 
- - (void) setChildrenAsCopy: (NSMutableArray *) someChildren
- {
--  unsigned int count, max;
-+  NSUInteger count, max;
- 
-   ASSIGN (children, someChildren);
- 
-@@ -399,7 +399,7 @@ static NGCardsSaxHandler *sax = nil;
- - (NSString *) description
- {
-   NSMutableString *str;
--  unsigned int count, max;
-+  NSUInteger count, max;
- 
-   str = [NSMutableString stringWithCapacity:64];
-   [str appendFormat:@"<%p[%@]:%@",
-@@ -421,7 +421,7 @@ static NGCardsSaxHandler *sax = nil;
- - (void) replaceThisElement: (CardElement *) oldElement
-                 withThisOne: (CardElement *) newElement
- {
--  unsigned int index;
-+  NSUInteger index;
- 
-   index = [children indexOfObject: oldElement];
-   if (index != NSNotFound)
-diff --git a/SoObjects/Mailer/SOGoMailObject+Draft.m b/SoObjects/Mailer/SOGoMailObject+Draft.m
-index b0aec21..4aa6de2 100644
---- a/SoObjects/Mailer/SOGoMailObject+Draft.m
-+++ b/SoObjects/Mailer/SOGoMailObject+Draft.m
-@@ -53,7 +53,7 @@
-     nil
-   };
-   BOOL hasPrefix;
--  unsigned int i;
-+  NSUInteger i;
-   NSString *subject, *newSubject;
- 
-   hasPrefix = NO;
-@@ -99,7 +99,7 @@
-   NSDictionary *parts;
-   NSString *rawPart, *content, *contentKey;
-   SOGoUserDefaults *ud;
--  int index;
-+  NSUInteger index;
-   BOOL htmlComposition, htmlContent;
- 
-   content = @"";
-@@ -189,7 +189,7 @@
-   static NSString *sescape[] = { 
-     @"/", @"..", @"~", @"\"", @"'", @" ", @".", nil 
-   };
--  unsigned int count, length;
-+  NSUInteger count, length;
- 
-   subject = [self decodedSubject];
-   length = [subject length];
-@@ -298,7 +298,7 @@
-   NSString *newPath;
-   NSArray *subparts;
-   NSString *type;
--  unsigned int i;
-+  NSUInteger i;
- 
-   type = [[part objectForKey: @"type"] lowercaseString];
-   if ([type isEqualToString: @"multipart"])
-diff --git a/SoObjects/SOGo/NSString+Utilities.m b/SoObjects/SOGo/NSString+Utilities.m
-index 914d76b..c1e9e03 100644
---- a/SoObjects/SOGo/NSString+Utilities.m
-+++ b/SoObjects/SOGo/NSString+Utilities.m
-@@ -479,7 +479,8 @@ static int cssEscapingCount;
- 
- - (int) timeValue
- {
--  int i, time;
-+  int 		time;
-+  NSInteger 	i;
- 
-   if ([self length] > 0)
-     {
-diff --git a/UI/MailPartViewers/UIxMailPartAlternativeViewer.m b/UI/MailPartViewers/UIxMailPartAlternativeViewer.m
-index 9174a20..16e15d2 100644
---- a/UI/MailPartViewers/UIxMailPartAlternativeViewer.m
-+++ b/UI/MailPartViewers/UIxMailPartAlternativeViewer.m
-@@ -43,7 +43,7 @@
- @interface UIxMailPartAlternativeViewer : UIxMailPartViewer
- {
-   id           childInfo;
--  unsigned int childIndex;
-+  NSUInteger   childIndex;
- }
- 
- @end
-@@ -70,7 +70,7 @@
- - (NSArray *) childPartTypes
- {
-   NSMutableArray *types;
--  unsigned i, count;
-+  NSUInteger i, count;
-   NSArray  *childParts;
- 
-   childParts = [[self bodyInfo] valueForKey:@"parts"];
-@@ -89,10 +89,10 @@
-   return types;
- }
- 
--- (unsigned int) _preferredTypesPart: (NSArray *) types
-+- (NSUInteger) _preferredTypesPart: (NSArray *) types
- {
--  unsigned int count, max;
--  unsigned int part;
-+  NSUInteger count, max;
-+  NSUInteger part;
-   const NSString *priorities[] = { @"multipart/related", @"multipart/mixed",
- 				   @"text/calendar", @"text/html",
- 				   @"text/plain" };
-@@ -113,7 +113,7 @@
- - (int) _selectPartIndexFromTypes: (NSArray *) _types
- {
-   /* returns the index of the selected part or NSNotFound */
--  unsigned count, max, part;
-+  NSUInteger count, max, part;
- 
-   part = [self _preferredTypesPart: _types];
-   if (part == NSNotFound)
-@@ -136,7 +136,7 @@
- 
- - (void) selectChildInfo
- {
--  unsigned idx;
-+  NSUInteger idx;
- 
-   [childInfo release]; childInfo = nil;
-   childIndex = 0;
-@@ -164,7 +164,7 @@
-   return childInfo;
- }
- 
--- (unsigned int) childIndex
-+- (NSUInteger) childIndex
- {
-   if (!childIndex)
-     [self selectChildInfo];
-@@ -176,7 +176,7 @@
- {
-   char buf[8];
- 
--  sprintf (buf, "%d", [self childIndex] + 1);
-+  sprintf (buf, "%"PRIuPTR"", [self childIndex] + 1);
- 
-   return [NSString stringWithCString:buf];
- }
-diff --git a/UI/MailerUI/UIxMailEditor.m b/UI/MailerUI/UIxMailEditor.m
-index aa32a7a..9d15dfa 100644
---- a/UI/MailerUI/UIxMailEditor.m
-+++ b/UI/MailerUI/UIxMailEditor.m
-@@ -394,7 +394,7 @@ static NSArray *infoKeys = nil;
- {
-   if (![_info isNotNull]) return;
-   [self debugWithFormat:@"loading info ..."];
--  [self takeValuesFromDictionary:_info];
-+  [self setValuesForKeysWithDictionary:_info];
- }
- 
- - (NSDictionary *) storeInfo
-diff --git a/UI/MailerUI/UIxMailMainFrame.m b/UI/MailerUI/UIxMailMainFrame.m
-index 0d12165..8db3cf6 100644
---- a/UI/MailerUI/UIxMailMainFrame.m
-+++ b/UI/MailerUI/UIxMailMainFrame.m
-@@ -125,8 +125,8 @@
-     // TODO: this is ugly, create reusable link facility in SOPE
-     // TODO: remove 'search' and 'filterpopup', preserve sorting
-     NSMutableString *ms;
--    NSArray  *qp;
--    unsigned i, count;
-+    NSArray    *qp;
-+    NSUInteger i, count;
-     
-     qp    = [[u substringFromIndex:(r.location + r.length)] 
- 	        componentsSeparatedByString:@"&"];
-@@ -193,8 +193,8 @@
-   SOGoMailAccounts *co;
-   SOGoContactFolders *folders;
-   SOGoParentFolder *folder;
--  WORequest *request;
--  int i, count;
-+  WORequest  *request;
-+  NSUInteger i, count;
- 
-   parameters = nil;
-   co = [self clientObject];
-@@ -549,7 +549,7 @@
-   NSArray *available;
-   NSDictionary *metaData;
-   SOGoUserDefaults *ud;
--  unsigned int i;
-+  NSUInteger i;
- 
-   if (!columnsOrder)
-     {
-@@ -636,8 +636,8 @@
-   NSMutableArray *folders;
-   NSMutableString *path;
-   SOGoUserDefaults *ud;
--  NSString *s;
--  int i, j, k;
-+  NSString   *s;
-+  NSUInteger i, j, k;
- 
-   ud = [[context activeUser] userDefaults];
-   folders = [NSMutableArray array];
-diff --git a/UI/Scheduler/UIxCalView.m b/UI/Scheduler/UIxCalView.m
-index 5b594db..2ed982b 100644
---- a/UI/Scheduler/UIxCalView.m
-+++ b/UI/Scheduler/UIxCalView.m
-@@ -118,7 +118,7 @@
- - (NSArray *) filterAppointments:(NSArray *) _apts
- {
-   NSMutableArray *filtered;
--  unsigned i, count, p, pCount;
-+  NSUInteger i, count, p, pCount;
-   NSString *email, *partmailsString, *state, *pEmail;
-   NSDictionary *info, *primaryIdentity;
-   NSArray *partmails, *partstates;
-@@ -370,7 +370,7 @@
- {
-   NSArray        *apts;
-   NSMutableArray *filtered;
--  unsigned       i, count;
-+  NSUInteger     i, count;
- 
-   if (allDayApts)
-     return allDayApts;
-@@ -532,7 +532,8 @@
-   NSString *uidsString, *loc, *prevMethod, *userFolderID;
-   id <WOActionResults> r;
-   BOOL useGroups;
--  unsigned index;
-+  NSUInteger index;
-+
- 
-   uidsString = [self queryParameterForKey: @"userUIDString"];
-   uidsString = [uidsString stringByTrimmingSpaces];
-diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m
-index e2186e1..3813f96 100644
---- a/UI/Scheduler/UIxComponentEditor.m
-+++ b/UI/Scheduler/UIxComponentEditor.m
-@@ -525,7 +525,7 @@ iRANGE(2);
-   iCalTrigger *aTrigger;
-   NSString *duration, *quantity;
-   unichar c;
--  unsigned int i;
-+  NSUInteger i;
- 
-   if ([component hasAlarms])
-     {
-@@ -1289,7 +1289,7 @@ iRANGE(2);
-   NSString *currentOwner;
-   SOGoAppointmentFolder *currentCalendar;
-   SOGoUser *currentUser;
--  unsigned i;
-+  NSUInteger i;
- 
-   calendars = [self calendarList];
-   owners = [NSMutableArray arrayWithCapacity: [calendars count]];
-@@ -1562,7 +1562,7 @@ RANGE(2);
- {
-   NSString *cycleRep;
-   NSArray *cycles;
--  unsigned i, count;
-+  NSUInteger i, count;
- 
-   if (!_rrule)
-     return [[self cycles] objectAtIndex:0];
-@@ -1721,7 +1721,7 @@ RANGE(2);
- //   s = [self queryParameterForKey:_qp];
- //   if(s && [s length] > 0) {
- //     NSArray *es;
--//     unsigned i, count;
-+//     NSUInteger i, count;
-     
- //     es = [s componentsSeparatedByString: @","];
- //     count = [es count];
-@@ -1766,7 +1766,7 @@ RANGE(2);
- - (void) _handleAttendeesEdition
- {
-   NSMutableArray *newAttendees;
--  unsigned int count, max;
-+  NSUInteger count, max;
-   NSString *currentEmail;
-   iCalPerson *currentAttendee;
-   NSString *json, *role, *partstat;
-@@ -2189,7 +2189,7 @@ RANGE(2);
-       iCalTrigger *aTrigger;
-       iCalAlarm *anAlarm;
-       NSString *aValue;
--      unsigned int index;
-+      NSUInteger index;
- 
-       anAlarm = [iCalAlarm new];
- 
diff -Nru sogo-1.3.15a/debian/patches/series sogo-1.3.16/debian/patches/series
--- sogo-1.3.15a/debian/patches/series	2012-07-06 02:30:44.000000000 +0200
+++ sogo-1.3.16/debian/patches/series	2012-07-06 02:32:39.000000000 +0200
@@ -4,4 +4,4 @@
 0004-Add-support-for-GnuTLS.patch
 0005-Set-SOGoMailSpoolPath-to-var-spool-sogo-by-default.patch
 0006-Put-private-libraries-in-usr-lib-sogo.patch
-0007-GNUstep-1.24-fix.patch
+0007-Compile-daemon-as-PIE.patch
diff -Nru sogo-1.3.15a/debian/rules sogo-1.3.16/debian/rules
--- sogo-1.3.15a/debian/rules	2012-07-06 02:30:44.000000000 +0200
+++ sogo-1.3.16/debian/rules	2012-07-06 02:32:39.000000000 +0200
@@ -1,6 +1,7 @@
 #!/usr/bin/make -f
 # -*- makefile -*-
 export DH_VERBOSE=1
+export DEB_BUILD_MAINT_OPTIONS=hardening=+bindnow
 
 %:
 	dh $@ --parallel
@@ -9,6 +10,9 @@
 	dh_auto_clean
 	rm -f config.make
 
+override_dh_auto_build:
+	dh_auto_build -- OBJCFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" messages=yes
+
 override_dh_auto_configure:
 	./configure
 
diff -Nru sogo-1.3.15a/debian/sogo.postrm sogo-1.3.16/debian/sogo.postrm
--- sogo-1.3.15a/debian/sogo.postrm	2012-07-06 02:30:44.000000000 +0200
+++ sogo-1.3.16/debian/sogo.postrm	2012-07-06 02:32:39.000000000 +0200
@@ -16,7 +16,7 @@
 
 case "$1" in
     purge)
-	deluser --system sogo
+	deluser --system sogo || true
         rm -rf /var/spool/sogo
         rm -rf /var/log/sogo
         rm -rf /var/run/sogo
diff -Nru sogo-1.3.15a/debian-multiarch/changelog sogo-1.3.16/debian-multiarch/changelog
--- sogo-1.3.15a/debian-multiarch/changelog	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/changelog	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,48 @@
+sogo (1.3.5) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Inverse Support <support@inverse.ca>  Wed, 25 January 2011 12:00:00 -0500
+
+sogo (1.2.2) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Inverse Support <support@inverse.ca>  Tue, 04 May 2010 16:45:59 -0400
+
+sogo (1.2.1) unstable; urgency=low
+
+  * New upstream release.
+  * SOGo-debian.conf installed as /etc/apache2/conf.d/
+  * SOGo.conf removed from documentation examples.
+
+ -- Inverse Support <support@inverse.ca>  Wed, 17 Feb 2010 11:06:41 -0500
+
+sogo (1.2.0) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Inverse Support <support@inverse.ca>  Tue, 26 Jan 2010 08:34:20 -0500
+
+sogo (1.1.0) unstable; urgency=low
+
+  * New release
+  * Install a default Apache 2 configuration file.
+  * Added a dependency on sope4.9-libxmlsaxdriver, sope4.9-db-connector
+
+ -- Inverse Support <support@inverse.ca>  Wed, 28 Oct 2009 17:06:03 -0400
+
+sogo (1.0.4) unstable; urgency=low
+
+  * New release
+  * debian/control:
+    - bumped standards-version
+    - updated dependencies
+
+ -- Inverse Support <support@inverse.ca>  Tue, 11 Aug 2009 18:22:41 -0400
+
+sogo (1.0.3) UNRELEASED; urgency=low
+
+  * Initial package
+
+ -- Cyril Robert <crobert@inverse.ca>  Tue, 23 Dec 2008 00:49:45 +0100
diff -Nru sogo-1.3.15a/debian-multiarch/compat sogo-1.3.16/debian-multiarch/compat
--- sogo-1.3.15a/debian-multiarch/compat	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/compat	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1 @@
+8
diff -Nru sogo-1.3.15a/debian-multiarch/control sogo-1.3.16/debian-multiarch/control
--- sogo-1.3.15a/debian-multiarch/control	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/control	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,61 @@
+Source: sogo
+Priority: optional
+Maintainer: Inverse Support <support@inverse.ca>
+Build-Depends: debhelper (>= 8.0.0), gobjc | objc-compiler, libgnustep-base-dev, libsope-appserver4.9-dev, libsope-core4.9-dev, libsope-gdl1-4.9-dev, libsope-ldap4.9-dev, libsope-mime4.9-dev, libsope-xml4.9-dev, libmemcached-dev, libxml2-dev, libsbjson-dev, libssl-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev, libmapi-dev, libmapistore-dev, libmapiproxy-dev
+Section: web
+Standards-Version: 3.9.2
+
+Package: sogo
+Pre-Depends: ${misc:Pre-Depends}
+Multi-Arch: same
+Section: web
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, tmpreaper, sope4.9-libxmlsaxdriver, sope4.9-db-connector, gnustep-make, libcurl3
+Suggests: nginx
+Description: a modern and scalable groupware
+ SOGo is a groupware server built around OpenGroupware.org (OGo) and
+ the SOPE application server with focus on scalability.
+ The Inverse edition of this project has many feature enhancements:
+  * CalDAV and GroupDAV compliance
+  * full handling of vCard as well as vCalendar/iCalendar formats
+  * support for folder sharing and ACLs
+ .
+ The Web interface has been rewritten in an AJAX fashion to provide a faster
+ UI for the users, consistency in look and feel with the Mozilla applications,
+ and to reduce the load of the transactions on the server.
+
+Package: sogo-dev
+Section: devel
+Architecture: any
+Depends: sogo (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Replaces: sogo (<< ${binary:Version})
+Description: a modern and scalable groupware - development files
+ SOGo is a groupware server built around OpenGroupware.org (OGo) and
+ the SOPE application server with focus on scalability.
+ .
+ This package contains the development files for developing SOGo modules.
+
+Package: sogo-openchange
+Pre-Depends: ${misc:Pre-Depends}
+Multi-Arch: same
+Section: net
+Priority: extra
+Architecture: any
+Depends: sogo (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Description: a modern and scalable groupware - OpenChange backend
+ SOGo is a groupware server built around OpenGroupware.org (OGo) and
+ the SOPE application server with focus on scalability.
+ .
+ This package contains the backend plugin for using SOGo as a backend
+ to OpenChange.
+
+Package: sogo-dbg
+Section: debug
+Priority: extra
+Architecture: any
+Depends: sogo (= ${binary:Version}), ${misc:Depends}
+Description: a modern and scalable groupware - debugging symbols
+ SOGo is a groupware server built around OpenGroupware.org (OGo) and
+ the SOPE application server with focus on scalability.
+ .
+ This package contains the debugging symbols for SOGo.
diff -Nru sogo-1.3.15a/debian-multiarch/copyright sogo-1.3.16/debian-multiarch/copyright
--- sogo-1.3.15a/debian-multiarch/copyright	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/copyright	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,31 @@
+This package was debianized by Inverse <support@inverse.ca> on
+Mon, 27 Jul 2009 10:57:51 -0400.
+
+It was downloaded from http://www.sogo.nu/downloads/backend.html
+
+Upstream Authors:
+
+    Inverse inc. <support@inverse.ca>
+
+Copyright:
+
+    Copyright (C) 2006-2010 Inverse inc.
+
+License:
+
+    This program 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 2 of the License, or
+    (at your option) any later version.
+
+    This program 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; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+The Debian packaging is (c) 2009, Inverse <support@inverse.ca> and
+is licensed under the GPL, see `/usr/share/common-licenses/GPL-2'.
diff -Nru sogo-1.3.15a/debian-multiarch/rules sogo-1.3.16/debian-multiarch/rules
--- sogo-1.3.15a/debian-multiarch/rules	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/rules	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,115 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+export DH_VERBOSE=1
+# export DH_OPTIONS="-p sogo"
+
+DESTDIR=$(CURDIR)/debian/tmp
+DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
+
+include /etc/GNUstep/GNUstep.conf
+include /usr/share/GNUstep/Makefiles/common.make
+
+config.make: configure
+	dh_testdir
+	./configure --prefix=$(GNUSTEP_SYSTEM_ROOT)
+
+#Architecture
+build: build-arch
+
+build-arch: build-arch-stamp
+build-arch-stamp:  config.make 
+#	 Add here commands to compile the arch part of the package.
+	$(MAKE)
+	if pkg-config --atleast-version=1.0 libmapi; \
+	then (cd OpenChange; $(MAKE));  \
+	fi
+	touch $@
+
+clean: 
+	dh_testdir
+	dh_testroot
+	rm -f build-arch-stamp
+	( cd Tests/Integration; make clean )
+	rm -f Tests/Integration/config.py
+	-find Tests -name "*.pyc" -exec rm -f {} \;
+	if [ -f config.make ]; \
+	then \
+	  if pkg-config --atleast-version=1.0 libmapi; \
+	  then \
+	    (cd OpenChange; make clean); \
+	  fi; \
+	  make clean; \
+	fi
+	-rm -f OpenChange/MAPIStorePropertySelectors.*
+	-find OpenChange -type d -name "unrtf-*" -exec rm -rf {} \;
+	-rm -f OpenChange/unrtf*-stamp
+	-rm -f config.make
+	dh_clean 
+
+install: install-arch
+	dh_testdir
+	dh_testroot
+#	dh_prep -i
+#	dh_installdirs -i
+#	dh_install -i
+
+install-arch: build-arch
+	dh_testdir
+	dh_testroot
+	dh_prep
+#	dh_installdirs -s
+
+	$(MAKE) DESTDIR=$(DESTDIR) GNUSTEP_INSTALLATION_DOMAIN=SYSTEM install
+	if pkg-config --atleast-version=1.0 libmapi; \
+	then \
+	  (cd OpenChange; \
+	   $(MAKE) \
+	       DESTDIR=$(DESTDIR) \
+	       GNUSTEP_INSTALLATION_DOMAIN=SYSTEM \
+	     install); \
+	  rm -f $(DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/mapistore_backends/libMAPIStoreSOGo.so.1; \
+	  rm -f $(DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/mapistore_backends/libMAPIStoreSOGo.so; \
+	  mv -f $(DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/mapistore_backends/libMAPIStoreSOGo.so.1.0.0 \
+	           $(DESTDIR)/usr/lib/$(DEB_HOST_MULTIARCH)/mapistore_backends/SOGo.so; \
+	fi
+
+	mkdir -p debian/tmp/etc/default
+	cp Scripts/sogo-default debian/tmp/etc/default/sogo
+	mkdir -p debian/tmp/usr/share/lintian/overrides
+	cp debian/sogo.overrides debian/tmp/usr/share/lintian/overrides/sogo
+	mkdir -p debian/tmp/etc/apache2/conf.d
+	cp Apache/SOGo.conf debian/tmp/etc/apache2/conf.d/SOGo.conf
+	install -D -m 644 Scripts/sogo.cron debian/tmp/etc/cron.d/sogo
+
+# Build architecture dependant packages using the common target.
+binary-arch: build-arch install-arch
+	dh_testdir
+	dh_testroot
+	dh_installinit -R
+	dh_installlogrotate
+	dh_installcron
+	dh_installchangelogs ChangeLog
+	dh_installdocs
+#	dh_installexamples
+	dh_installman
+	dh_install
+	dh_link
+	dh_strip --dbg-package=sogo-dbg
+#	workaround for http://sourceware.org/bugzilla/show_bug.cgi?id=9538
+#	to let gdb find the symbols for libSOGo
+	( cd debian/sogo-dbg/usr/lib/debug/usr/lib/; \
+	  ln -s GNUstep/Frameworks/SOGo.framework/Versions/*/libSOGo* ./ )
+	dh_compress
+	dh_fixperms
+	dh_makeshlibs -X/usr/lib/$(DEB_HOST_MULTIARCH)/mapistore_backends
+	dh_shlibdeps
+	dh_installdeb
+	dh_gencontrol
+	dh_md5sums
+	dh_builddeb
+
+binary-indep: build install
+# We have nothing to do by default.
+
+binary: binary-arch binary-indep
+.PHONY: build clean binary-arch binary install install-arch
diff -Nru sogo-1.3.15a/debian-multiarch/sogo-dev.install sogo-1.3.16/debian-multiarch/sogo-dev.install
--- sogo-1.3.15a/debian-multiarch/sogo-dev.install	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo-dev.install	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,2 @@
+usr/include/GNUstep/*
+usr/lib/lib*.so
diff -Nru sogo-1.3.15a/debian-multiarch/sogo-openchange.install sogo-1.3.16/debian-multiarch/sogo-openchange.install
--- sogo-1.3.15a/debian-multiarch/sogo-openchange.install	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo-openchange.install	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,2 @@
+usr/lib/*/mapistore_backends/*
+usr/lib/GNUstep/SOGo/SOGoBackend.MAPIStore
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.cron.daily sogo-1.3.16/debian-multiarch/sogo.cron.daily
--- sogo-1.3.15a/debian-multiarch/sogo.cron.daily	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.cron.daily	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+SOGOSPOOL=/var/spool/sogo
+
+/usr/sbin/tmpreaper 24 "$SOGOSPOOL"
+find "$SOGOSPOOL" -mindepth 1 -type d -empty -exec /bin/rmdir -p {} \; 2> /dev/null
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.dirs sogo-1.3.16/debian-multiarch/sogo.dirs
--- sogo-1.3.15a/debian-multiarch/sogo.dirs	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.dirs	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,3 @@
+etc
+var
+usr
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.docs sogo-1.3.16/debian-multiarch/sogo.docs
--- sogo-1.3.15a/debian-multiarch/sogo.docs	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.docs	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,10 @@
+NEWS
+TODO
+Scripts/sql-update-1.2.2_to_1.3.0.sh
+Scripts/sql-update-1.2.2_to_1.3.0-mysql.sh
+Scripts/sql-update-1.3.3_to_1.3.4.sh
+Scripts/sql-update-1.3.3_to_1.3.4-mysql.sh
+Scripts/sql-update-1.3.11_to_1.3.12.sh
+Scripts/sql-update-1.3.11_to_1.3.12-mysql.sh
+Scripts/sogo-backup.sh
+Scripts/updates.php
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.init sogo-1.3.16/debian-multiarch/sogo.init
--- sogo-1.3.15a/debian-multiarch/sogo.init	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.init	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,100 @@
+#!/bin/bash
+### BEGIN INIT INFO
+# Provides:          sogo
+# Required-Start:    $remote_fs $network
+# Required-Stop:     $remote_fs $network
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: SOGo server
+### END INIT INFO
+
+# SOGo init script for Debian GNU/Linux
+#
+# Copyright (C) 2007-2010 Inverse inc.
+#
+# Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+#         Ludovic Marcotte <ludovic@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 2, 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.
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+
+NAME=sogo
+DAEMON=/usr/sbin/sogod
+DESC="SOGo"
+
+USER=$NAME
+PREFORK=1
+
+PIDFILE=/var/run/$NAME/$NAME.pid
+LOGFILE=/var/log/$NAME/$NAME.log
+
+if [ -f /etc/default/$NAME ]; then
+    . /etc/default/$NAME
+fi
+
+. /lib/lsb/init-functions
+
+if [ ! -x $DAEMON ]; then
+    log_failure_msg "$DAEMON is not executable."
+    exit 1
+fi
+
+set -e
+
+. /usr/share/GNUstep/Makefiles/GNUstep.sh
+
+DAEMON_OPTS="-WOWorkersCount $PREFORK -WOPidFile $PIDFILE -WOLogFile $LOGFILE"
+
+case "$1" in
+  start)
+	log_daemon_msg "Starting $DESC" "$NAME"
+
+        # Ensure directory's existence and permissions
+        install -o $USER -g adm -m 755 -d /var/run/$NAME
+        install -o $USER -g adm -m 750 -d /var/spool/$NAME
+        install -o $USER -g adm -m 750 -d /var/log/$NAME
+
+	if ! start-stop-daemon -c $USER --quiet --start --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS 
+	then
+	    log_progress_msg "already running"
+        fi
+	log_end_msg 0
+	;;
+  stop)
+	log_daemon_msg "Stopping $DESC" "$NAME"
+	start-stop-daemon --stop --pidfile $PIDFILE --retry=TERM/20/KILL/5 --oknodo
+	log_end_msg 0
+	;;
+  restart|force-reload)
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	start-stop-daemon --stop --pidfile $PIDFILE --retry=TERM/20/KILL/5 --oknodo
+        # Ensure directory's existence and permissions
+        install -o $USER -g adm -m 755 -d /var/run/$NAME
+        install -o $USER -g adm -m 750 -d /var/spool/$NAME
+        install -o $USER -g adm -m 750 -d /var/log/$NAME
+	start-stop-daemon -c $USER --quiet --start --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS 
+	log_end_msg 0
+	;;
+  status)
+	status_of_proc -p $PIDFILE "$DAEMON" $NAME && exit 0 || exit $?
+	;;
+  *)
+	echo "Usage: $NAME {start|stop|restart|status}" >&2
+	exit 1
+	;;
+esac
+
+exit 0
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.install sogo-1.3.16/debian-multiarch/sogo.install
--- sogo-1.3.15a/debian-multiarch/sogo.install	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.install	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,15 @@
+etc/default/sogo
+etc/apache2/conf.d/SOGo.conf
+etc/cron.d/sogo
+usr/sbin/*
+usr/lib/GNUstep/Frameworks/*
+usr/lib/GNUstep/Libraries/*
+usr/lib/GNUstep/OCSTypeModels/*
+usr/lib/GNUstep/SaxDrivers-4.9/*
+usr/lib/GNUstep/SaxMappings/*
+usr/lib/GNUstep/WOxElemBuilders-4.9/*
+usr/lib/GNUstep/SOGo/*.SOGo
+usr/lib/GNUstep/SOGo/Templates
+usr/lib/GNUstep/SOGo/WebServerResources
+usr/lib/lib*.so.*
+usr/share/lintian/*
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.logrotate sogo-1.3.16/debian-multiarch/sogo.logrotate
--- sogo-1.3.15a/debian-multiarch/sogo.logrotate	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.logrotate	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,13 @@
+/var/log/sogo/*.log {
+	daily
+	missingok
+	rotate 7
+	compress
+	delaycompress
+	notifempty
+	create 640 sogo sogo
+	sharedscripts
+	postrotate
+		/etc/init.d/sogo restart > /dev/null 2>&1
+	endscript
+}
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.overrides sogo-1.3.16/debian-multiarch/sogo.overrides
--- sogo-1.3.15a/debian-multiarch/sogo.overrides	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.overrides	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,4 @@
+sogo: embedded-javascript-library usr/lib/GNUstep/SOGo/WebServerResources/prototype.js
+sogo: extra-license-file usr/lib/GNUstep/SOGo/WebServerResources/scriptaculous/MIT-LICENSE
+sogo: embedded-javascript-library usr/lib/GNUstep/SOGo/WebServerResources/scriptaculous/scriptaculous.js
+sogo: package-name-doesnt-match-sonames libGDLContentStore4.9 libNGCards4.9 libOGoContentStore0.9 libSOGoUI1.0
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.postinst sogo-1.3.16/debian-multiarch/sogo.postinst
--- sogo-1.3.15a/debian-multiarch/sogo.postinst	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.postinst	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+set -e
+
+# summary of how this script can be called:
+#        * <postinst> `configure' <most-recently-configured-version>
+#        * <old-postinst> `abort-upgrade' <new version>
+#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+#          <new-version>
+#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+#          <failed-install-package> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+#
+
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+case "$1" in
+    configure)
+	  # update timestamp on imgs,css,js to let apache know the files changed
+	  find /usr/lib/GNUstep/SOGo/WebServerResources  -exec touch {} \;
+        ;;
+
+    abort-upgrade|abort-remove|abort-deconfigure)
+        ;;
+
+    *)
+        echo "postinst called with unknown argument \`$1'" >&2
+        exit 0
+    ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.postrm sogo-1.3.16/debian-multiarch/sogo.postrm
--- sogo-1.3.15a/debian-multiarch/sogo.postrm	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.postrm	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+set -e
+
+# summary of how this script can be called:
+#        * <postrm> `remove'
+#        * <postrm> `purge'
+#        * <old-postrm> `upgrade' <new-version>
+#        * <new-postrm> `failed-upgrade' <old-version>
+#        * <new-postrm> `abort-install'
+#        * <new-postrm> `abort-install' <old-version>
+#        * <new-postrm> `abort-upgrade' <old-version>
+#        * <disappearer's-postrm> `disappear' <r>overwrit>r> <new-version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+case "$1" in
+    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+        if test "x$1" == "xpurge"
+        then
+            userdel -r sogo || true
+            rm -rf /var/spool/sogo
+            rm -rf /var/log/sogo
+            rm -rf /var/run/sogo
+        fi
+        ;;
+
+    *)
+        echo "postrm called with unknown argument \`$1'" >&2
+        exit 0
+esac
+
+#DEBHELPER#
+
+exit 0
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.preinst sogo-1.3.16/debian-multiarch/sogo.preinst
--- sogo-1.3.15a/debian-multiarch/sogo.preinst	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.preinst	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+set -e
+
+# summary of how this script can be called:
+#        * <new-preinst> `install'
+#        * <new-preinst> `install' <old-version>
+#        * <new-preinst> `upgrade' <old-version>
+#        * <old-preinst> `abort-upgrade' <new-version>
+#
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+if test "x$1" == "xinstall" && test -z "$2"
+then
+  if ! id sogo 1> /dev/null 2>&1; then
+    groupadd -f -K GID_MIN=100 -K GID_MAX=500 sogo
+    useradd -d /home/sogo -g sogo -m -K UID_MIN=100 -K UID_MAX=500 -K PASS_MAX_DAYS=-1 -s /bin/bash sogo
+  fi
+
+  for dir in run spool log
+  do
+    if ! test -d /var/$dir/sogo
+    then
+      install -m 750 -o sogo -g sogo -d /var/$dir/sogo
+    fi
+  done
+fi
+
+#DEBHELPER#
+
+exit 0
diff -Nru sogo-1.3.15a/debian-multiarch/sogo.prerm sogo-1.3.16/debian-multiarch/sogo.prerm
--- sogo-1.3.15a/debian-multiarch/sogo.prerm	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/sogo.prerm	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+set -e
+
+# summary of how this script can be called:
+#        * <prerm> `remove'
+#        * <old-prerm> `upgrade' <new-version>
+#        * <new-prerm> `failed-upgrade' <old-version>
+#        * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+#        * <deconfigured's-prerm> `deconfigure' `in-favour'
+#          <package-being-installed> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see /usr/share/doc/packaging-manual/
+
+#DEBHELPER#
+
+exit 0
diff -Nru sogo-1.3.15a/debian-multiarch/source/format sogo-1.3.16/debian-multiarch/source/format
--- sogo-1.3.15a/debian-multiarch/source/format	1970-01-01 01:00:00.000000000 +0100
+++ sogo-1.3.16/debian-multiarch/source/format	2012-06-07 17:40:57.000000000 +0200
@@ -0,0 +1 @@
+3.0 (quilt)
diff -Nru sogo-1.3.15a/sogo.spec sogo-1.3.16/sogo.spec
--- sogo-1.3.15a/sogo.spec	2012-05-18 17:27:17.000000000 +0200
+++ sogo-1.3.16/sogo.spec	2012-06-07 17:40:57.000000000 +0200
@@ -292,6 +292,7 @@
 # update timestamp on imgs,css,js to let apache know the files changed
 find %{_libdir}/GNUstep/SOGo/WebServerResources  -exec touch {} \;
 /sbin/chkconfig --add sogod
+/etc/init.d/sogod condrestart  >&/dev/null
 
 %preun
 if [ "$1" == "0" ]
@@ -311,6 +312,9 @@
 
 # ********************************* changelog *************************
 %changelog
+* Fri May 24 2012 Jean Raby <jraby@inverse.ca>
+- %post: restart sogo if it was running before rpm install
+
 * Fri Mar 16 2012 Jean Raby <jraby@inverse.ca>
 - %post: update timestamp on imgs,css,js to let apache know the files changed
 

Reply to: