Hello community,

here is the log from the commit of package kopano for openSUSE:Factory checked 
in at 2018-08-07 09:43:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kopano (Old)
 and      /work/SRC/openSUSE:Factory/.kopano.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kopano"

Tue Aug  7 09:43:38 2018 rev:15 rq:627701 version:8.6.6.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/kopano/kopano.changes    2018-07-12 
09:21:42.202631556 +0200
+++ /work/SRC/openSUSE:Factory/.kopano.new/kopano.changes       2018-08-07 
09:43:40.525372392 +0200
@@ -1,0 +2,11 @@
+Mon Aug  6 13:33:37 UTC 2018 - [email protected]
+
+- Update to new upstream release 8.6.6
+  * ical: handle double quotes in Content-Type header
+  * server: repair broken timing log messages for ldapplugin
+  * php7-ext: cure stack corruption in mapi_vcftomapi
+  * gateway: avoid uncaught exception when client disconnects midway
+  * dagent: avoid always running into K-2383
+  * server: avoid SSL crash near ERR_clear_error on shutdown
+
+-------------------------------------------------------------------

Old:
----
  kopanocore-8.6.2.25.tar.xz

New:
----
  kopanocore-8.6.6.1.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kopano.spec ++++++
--- /var/tmp/diff_new_pack.maPQpa/_old  2018-08-07 09:43:41.685374410 +0200
+++ /var/tmp/diff_new_pack.maPQpa/_new  2018-08-07 09:43:41.689374417 +0200
@@ -17,10 +17,10 @@
 #
 
 
-%define version_unconverted 8.6.2.25
+%define version_unconverted 8.6.6.1
 
 Name:           kopano
-Version:        8.6.2.25
+Version:        8.6.6.1
 Release:        0
 Summary:        Groupware server suite
 License:        AGPL-3.0-only

++++++ PKGBUILD ++++++
--- /var/tmp/diff_new_pack.maPQpa/_old  2018-08-07 09:43:41.717374466 +0200
+++ /var/tmp/diff_new_pack.maPQpa/_new  2018-08-07 09:43:41.717374466 +0200
@@ -1,5 +1,5 @@
 pkgname=kopano
-pkgver=8.6.2.25
+pkgver=8.6.6.1
 pkgrel=0
 pkgdesc='Kopano'
 arch=('x86_64')

++++++ _service ++++++
--- /var/tmp/diff_new_pack.maPQpa/_old  2018-08-07 09:43:41.737374501 +0200
+++ /var/tmp/diff_new_pack.maPQpa/_new  2018-08-07 09:43:41.737374501 +0200
@@ -3,8 +3,8 @@
                <param name="scm">git</param>
                <param 
name="url">https://stash.kopano.io/scm/kc/kopanocore.git</param>
                <param name="revision">kc-8.6.x</param>
-               <param name="parent-tag">kopanocore-8.6.2</param>
-               <param name="versionformat">8.6.2.@TAG_OFFSET@</param>
+               <param name="parent-tag">kopanocore-8.6.6</param>
+               <param name="versionformat">8.6.6.@TAG_OFFSET@</param>
 
                <!-- Regex used to rewrite the version which is applied after
                     versionformat [kopanocore-8.5.80] and after the implicit

++++++ debian.changelog ++++++
--- /var/tmp/diff_new_pack.maPQpa/_old  2018-08-07 09:43:41.753374528 +0200
+++ /var/tmp/diff_new_pack.maPQpa/_new  2018-08-07 09:43:41.757374536 +0200
@@ -1,4 +1,4 @@
-kopano (8.6.2.25-0) unstable; urgency=low
+kopano (8.6.6.1-0) unstable; urgency=low
 
   * Current release.
 

++++++ debian.kopano-dagent.init ++++++
--- /var/tmp/diff_new_pack.maPQpa/_old  2018-08-07 09:43:41.913374807 +0200
+++ /var/tmp/diff_new_pack.maPQpa/_new  2018-08-07 09:43:41.917374814 +0200
@@ -46,7 +46,7 @@
        install -dm0775 -o kopano -g kopano /var/run/kopano
        export LC_ALL=$KOPANO_LOCALE
        export LANG=$KOPANO_LOCALE
-       start-stop-daemon --start $QUIETDAEMON --pidfile $PIDFILE --exec 
$DAGENT -- $DAGENT_OPTS
+       start-stop-daemon --start $QUIETDAEMON --pidfile $PIDFILE --exec 
$DAGENT -- -l $DAGENT_OPTS
        log_end_msg $?
        unset LC_ALL LANG
        ;;

++++++ debian.kopano-spamd.install ++++++
--- /var/tmp/diff_new_pack.maPQpa/_old  2018-08-07 09:43:42.169375252 +0200
+++ /var/tmp/diff_new_pack.maPQpa/_new  2018-08-07 09:43:42.169375252 +0200
@@ -1,6 +1,7 @@
 lib/systemd/system/kopano-spamd.service
 usr/sbin/kopano-spamd
 usr/lib/python*/*/kopano_spamd/
+usr/share/doc/kopano/example-config/spamd.cfg
 usr/share/man/man5/kopano-spamd.*
 usr/share/man/man8/kopano-spamd.*
 

++++++ debian.kopano-utils.install ++++++
--- /var/tmp/diff_new_pack.maPQpa/_old  2018-08-07 09:43:42.213375329 +0200
+++ /var/tmp/diff_new_pack.maPQpa/_new  2018-08-07 09:43:42.213375329 +0200
@@ -14,6 +14,7 @@
 usr/sbin/kopano-srvadm
 usr/sbin/kopano-storeadm
 usr/libexec/kopano/mapitime
+usr/libexec/kopano/kscriptrun
 usr/lib/python*/*/kopano_cli/
 usr/share/man/man8/kopano-admin.8
 usr/share/man/man8/kopano-dbadm.8

++++++ debian.php7-mapi.postinst ++++++
--- /var/tmp/diff_new_pack.maPQpa/_old  2018-08-07 09:43:42.365375593 +0200
+++ /var/tmp/diff_new_pack.maPQpa/_new  2018-08-07 09:43:42.365375593 +0200
@@ -2,7 +2,9 @@
 
 set -e
 
-if [ -d /etc/php/7.0 ]; then
+if [ -d /etc/php/7.2 ]; then
+       BASE="/etc/php/7.2"
+elif [ -d /etc/php/7.0 ]; then
        BASE="/etc/php/7.0"
 else
        BASE="/etc/php5"

++++++ kopano.dsc ++++++
--- /var/tmp/diff_new_pack.maPQpa/_old  2018-08-07 09:43:42.433375711 +0200
+++ /var/tmp/diff_new_pack.maPQpa/_new  2018-08-07 09:43:42.437375719 +0200
@@ -1,7 +1,7 @@
 Format: 1.0
 Source: kopano
 Architecture: any all
-Version: 8.6.2.25-0
+Version: 8.6.6.1-0
 DEBTRANSFORM-RELEASE: 1
 Maintainer: Kopano Development <[email protected]>
 Homepage: https://kopano.com

++++++ kopanocore-8.6.2.25.tar.xz -> kopanocore-8.6.6.1.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/ECtools/backup/kopano_backup/__init__.py 
new/kopanocore-8.6.6.1/ECtools/backup/kopano_backup/__init__.py
--- old/kopanocore-8.6.2.25/ECtools/backup/kopano_backup/__init__.py    
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/ECtools/backup/kopano_backup/__init__.py     
2018-08-03 09:36:26.000000000 +0200
@@ -37,7 +37,7 @@
 )
 
 from MAPI.Tags import (
-    PR_EC_BACKUP_SOURCE_KEY, PR_EC_OUTOFOFFICE,
+    PR_EC_BACKUP_SOURCE_KEY, PR_EC_OUTOFOFFICE, PR_ENTRYID,
     PR_EC_OUTOFOFFICE_SUBJECT, PR_EC_OUTOFOFFICE_MSG, PR_EC_OUTOFOFFICE_FROM,
     PR_EC_OUTOFOFFICE_UNTIL, IID_IExchangeModifyTable, PR_CONTAINER_CLASS_W,
     PR_SOURCE_KEY, PR_ACL_TABLE, PR_STORE_RECORD_KEY, PR_RULES_DATA,
@@ -528,18 +528,23 @@
                     self.log.debug('purging folder')
                     shutil.rmtree(fpath)
                     stats['folders'] += 1
+
             else: # check all items for deletion
                 with closing(dbopen(fpath+'/items')) as db_items:
                     with closing(dbopen(fpath+'/index')) as db_index:
+                        delete_items = []
                         for item, idx in db_index.items():
                             d = pickle_loads(idx)
                             backup_deleted = d.get(b'backup_deleted')
                             if backup_deleted and (self.timestamp - 
backup_deleted).days >= self.options.purge:
-                                self.log.debug('purging item: %s', item)
-                                stats['items'] += 1
-                                if item in db_items:
-                                    del db_items[item]
-                                del db_index[item]
+                                delete_items.append(item)
+
+                        for item in delete_items:
+                            stats['items'] += 1
+                            self.log.debug('purging item: %s', item)
+                            del db_index[item]
+                            if item in db_items:
+                                del db_items[item]
 
         self.log.info('purged %d folders and %d items', stats['folders'], 
stats['items'])
 
@@ -660,45 +665,68 @@
                 folder.container_class = container_class
 
         # load existing sourcekeys in folder, to check for duplicates
-        existing = set()
+        existing = {}
         table = folder.mapiobj.GetContentsTable(0)
-        table.SetColumns([PR_SOURCE_KEY, PR_EC_BACKUP_SOURCE_KEY], 0)
+        table.SetColumns([PR_SOURCE_KEY, PR_EC_BACKUP_SOURCE_KEY, PR_ENTRYID], 
0)
         for row in table.QueryRows(-1, 0):
             if PROP_TYPE(row[1].ulPropTag) != PT_ERROR:
-                existing.add(_hex(row[1].Value))
+                existing[_hex(row[1].Value)] = _hex(row[2].Value)
             else:
-                existing.add(_hex(row[0].Value))
-
-        # load entry from 'index', so we don't have to unpickle everything
-        with closing(dbopen(data_path+'/index')) as db:
-            index = dict((a, pickle_loads(b)) for (a,b) in db.iteritems())
+                existing[_hex(row[0].Value)] = _hex(row[2].Value)
 
         # now dive into 'items', and restore desired items
-        with closing(dbopen(data_path+'/items')) as db:
+        with closing(dbopen(data_path+'/items')) as db_items:
+          with closing(dbopen(data_path+'/index')) as db_index:
+            index = dict((a, pickle_loads(b)) for (a,b) in 
db_index.iteritems())
+
             # determine sourcekey(s) to restore
-            sourcekeys = db.keys()
+            sourcekeys = db_index.keys()
             if self.options.sourcekeys:
                 sourcekeys = [sk for sk in self.options.sourcekeys if 
sk.encode('ascii') in sourcekeys]
             elif sys.hexversion >= 0x03000000:
                 sourcekeys = [sk.decode('ascii') for sk in sourcekeys]
 
+            # restore/delete each item
             for sourcekey2 in sourcekeys:
                 sourcekey2a = sourcekey2.encode('ascii')
                 with log_exc(self.log, stats):
-                    # date check against 'index'
-                    last_modified = index[sourcekey2a][b'last_modified']
-                    if ((self.options.period_begin and last_modified < 
self.options.period_begin) or
-                        (self.options.period_end and last_modified >= 
self.options.period_end) or
-                        (index[sourcekey2a].get(b'backup_deleted') and 
self.options.deletes in (None, 'no'))):
+
+                    # differential delete
+                    if index[sourcekey2a].get(b'backup_deleted') and 
self.options.differential:
+                        if self.options.deletes == 'no':
+                            self.log.warning('skipping deleted item with 
sourcekey %s', sourcekey2)
+                            continue
+                        if sourcekey2a not in existing:
+                            self.log.warning('item with sourcekey %s already 
deleted', sourcekey2)
+                            continue
+
+                        # delete item
+                        self.log.debug('deleting item with sourcekey %s', 
sourcekey2)
+                        item = folder.item(entryid=existing[sourcekey2a])
+                        folder.delete(item)
+                        continue
+
+                    # regular delete
+                    if(sourcekey2a not in db_items or \
+                       (index[sourcekey2a].get(b'backup_deleted') and 
self.options.deletes in (None, 'no'))
+                    ):
                         continue
 
-                    # check for duplicates
+                    # date range check
+                    last_modified = index[sourcekey2a].get(b'last_modified')
+                    if(last_modified and \
+                       ((self.options.period_begin and last_modified < 
self.options.period_begin) or \
+                         (self.options.period_end and last_modified >= 
self.options.period_end))
+                    ):
+                         continue
+
+                    # restore item
                     if sourcekey2a in existing or 
index[sourcekey2a][b'orig_sourcekey'] in existing:
                         self.log.warning('skipping duplicate item with 
sourcekey %s', sourcekey2)
                     else:
-                        # actually restore item
                         self.log.debug('restoring item with sourcekey %s', 
sourcekey2)
-                        item = 
folder.create_item(loads=zlib.decompress(db[sourcekey2a]), attachments=not 
self.options.skip_attachments)
+                        data = zlib.decompress(db_items[sourcekey2a])
+                        item = folder.create_item(loads=data, attachments=not 
self.options.skip_attachments)
 
                         # store original sourcekey or it is lost
                         try:
@@ -951,7 +979,7 @@
     parser.add_option('', '--index', dest='index', action='store_true', 
help='list items for PATH')
     parser.add_option('', '--sourcekey', dest='sourcekeys', action='append', 
help='restore specific sourcekey', metavar='SOURCEKEY')
     parser.add_option('', '--recursive', dest='recursive', 
action='store_true', help='backup/restore folders recursively')
-    parser.add_option('', '--differential', dest='differential', 
action='store_true', help='create differential backup')
+    parser.add_option('', '--differential', dest='differential', 
action='store_true', help='create/restore differential backup')
     parser.add_option('', '--merge', dest='merge', action='store_true', 
help='merge differential backups')
 
     # parse and check command-line options
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/ECtools/cli/kopano_cli/__init__.py 
new/kopanocore-8.6.6.1/ECtools/cli/kopano_cli/__init__.py
--- old/kopanocore-8.6.2.25/ECtools/cli/kopano_cli/__init__.py  2018-07-02 
15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/ECtools/cli/kopano_cli/__init__.py   2018-08-03 
09:36:26.000000000 +0200
@@ -222,6 +222,12 @@
     print(fmt.format('NA Equipment', stats['usercnt_equipment']))
     print(fmt.format('Total', 
int(stats['usercnt_active'])+int(stats['usercnt_nonactive'])))
 
+def quota_str(limit): # TODO in pyko?
+    if not limit:
+        return 'unlimited'
+    else:
+        return '%d MB' % (float(limit) / 2**20)
+
 def user_details(user):
     fmt = '{:<30}{:<}'
     print(fmt.format('Name:', _encode(user.name)))
@@ -257,9 +263,9 @@
 
     print('Current user store quota settings:')
     print(fmt.format('    Quota overrides:', yesno(not 
user.quota.use_default)))
-    print(fmt.format('    Warning level:', str(user.quota.warning_limit or 
'unlimited')))
-    print(fmt.format('    Soft level:', str(user.quota.soft_limit or 
'unlimited')))
-    print(fmt.format('    Hard level:', str(user.quota.hard_limit or 
'unlimited')))
+    print(fmt.format('    Warning level:', 
quota_str(user.quota.warning_limit)))
+    print(fmt.format('    Soft level:', quota_str(user.quota.soft_limit)))
+    print(fmt.format('    Hard level:', quota_str(user.quota.hard_limit)))
 
     list_groups('Groups', user.groups())
     list_permissions(user.store)
@@ -304,11 +310,11 @@
     if options.quota_override is not None:
         user.quota.use_default = not options.quota_override
     if options.quota_warn is not None:
-        user.quota.warning_limit = options.quota_warn
+        user.quota.warning_limit = options.quota_warn * (2**20) # TODO make 
pyko accept '2 GB' etc?
     if options.quota_soft is not None:
-        user.quota.soft_limit = options.quota_soft
+        user.quota.soft_limit = options.quota_soft * (2**20)
     if options.quota_hard is not None:
-        user.quota.hard_limit = options.quota_hard
+        user.quota.hard_limit = options.quota_hard * (2**20)
 
 def delegation_options(user, options, server):
     for delegation in options.add_delegation:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/RELNOTES.txt 
new/kopanocore-8.6.6.1/RELNOTES.txt
--- old/kopanocore-8.6.2.25/RELNOTES.txt        2018-07-02 15:42:42.000000000 
+0200
+++ new/kopanocore-8.6.6.1/RELNOTES.txt 2018-08-03 09:36:26.000000000 +0200
@@ -1,8 +1,36 @@
-8.6.3
-=====
+8.6.6 (2018-07-31)
+==================
+Fixes:
+* server: avoid SSL crash near ERR_clear_error on shutdown [KC-1132]
+* ical: recognize quotes in Content-Type charset [KC-1198]
+
+
+8.6.5 (2018-07-23)
+==================
+Fixes:
+* kopano-mr-accept.py: preserve categories when processing MR [KC-1195]
+* config: update server.cfg comment for owner_auto_full_access [KC-1190]
+* php7-ext: cure stack corruption in mapi_vcftomapi [KC-1218]
+* gateway: avoid uncaught exception when client disconnects midway [KS-41342]
+* dagent: avoid always running into K-2383 [KC-1219]
+
+
+8.6.4 (2018-07-17)
+==================
+Fixes:
+* build: fix expansion of @PKGLIBEXECDIR@ [KC-1217]
+* backup: fix differential deletes [KC-1207]
+* installer: use pidfile in all cases for RH6 init script
+* backup: don't delete while looping
+* common: kopano_dcgettext_wide needs additional UTF-8 hint [KC-1196]
+
+
+8.6.3 (2018-07-06)
+==================
 Fixes:
 * ical: hopefully cure uncaught exception on OpenBSD
 * ical: handle double quotes in Content-Type header [KC-1198]
+* server: repair broken timing log messages for ldapplugin [KS-41082]
 Enhancements:
 * client: now emits warnings about own incomplete PR_RULES_DATA processing
 * inetmapi: now emits a warning when runtime vmime is too old [KC-1124]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/caldav/Http.cpp 
new/kopanocore-8.6.6.1/caldav/Http.cpp
--- old/kopanocore-8.6.2.25/caldav/Http.cpp     2018-07-02 15:42:42.000000000 
+0200
+++ new/kopanocore-8.6.6.1/caldav/Http.cpp      2018-08-03 09:36:26.000000000 
+0200
@@ -196,10 +196,17 @@
                }
                if (strncasecmp(in, "charset=", 8) == 0) {
                        in += 8;
-                       cset = in;
-                       while (!isspace(*in) && *in != ';' && *in != '\0')
-                               ++in;   /* skip value */
-                       cset_end = in;
+                       if (*in == '"') {
+                               cset = ++in;
+                               while (*in != '\0' && *in != '"')
+                                       ++in;
+                               cset_end = in;
+                       } else {
+                               cset = in;
+                               while (!isspace(*in) && *in != ';' && *in != 
'\0')
+                                       ++in;   /* skip value */
+                               cset_end = in;
+                       }
                        continue;
                        /* continue parsing for more charset= values */
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/common/ECGetText.cpp 
new/kopanocore-8.6.6.1/common/ECGetText.cpp
--- old/kopanocore-8.6.2.25/common/ECGetText.cpp        2018-07-02 
15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/common/ECGetText.cpp 2018-08-03 09:36:26.000000000 
+0200
@@ -65,8 +65,7 @@
                        scoped_lock l_cache(m_hCacheLock);
                        auto insResult = m_cache.emplace(lpsz, L"");
                        if (insResult.second == true)   // successful insert, 
so not found in cache
-                               
insResult.first->second.assign(m_converter.convert_to<std::wstring>(lpsz));
-                       
+                               
insResult.first->second.assign(m_converter.convert_to<std::wstring>(lpsz, 
strlen(lpsz), "UTF-8"));
                        const wchar_t *lpszW = insResult.first->second.c_str();
                        return lpszW;
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/configure.ac 
new/kopanocore-8.6.6.1/configure.ac
--- old/kopanocore-8.6.2.25/configure.ac        2018-07-02 15:42:42.000000000 
+0200
+++ new/kopanocore-8.6.6.1/configure.ac 2018-08-03 09:36:26.000000000 +0200
@@ -1,5 +1,5 @@
 AC_PREREQ(2.60)
-AC_INIT([kopano], [8.6.2], [[email protected]])
+AC_INIT([kopano], [8.6.6], [[email protected]])
 
 dnl ABI tags are used to prevent inadvertent mixing of wildly different
 dnl versions of KC components without knowing it.
@@ -174,8 +174,6 @@
   AS_HELP_STRING([--with-userscript-prefix=PATH], [path to install the 
userscripts in (default SYSCONFDIR/kopano/userscripts)]),
   [USERSCRIPTDIR=${withval}],[USERSCRIPTDIR='/etc/kopano/userscripts'])
 AC_SUBST(USERSCRIPTDIR)
-AS_IF([echo "$USERSCRIPTDIR" | grep -q '\$'],
-       [AC_MSG_ERROR([Variable expansion unfortunately not supported for 
--with-userscript-prefix])])
 
 # quota warning templates location
 AC_ARG_WITH(quotatemplate-prefix,
@@ -213,8 +211,6 @@
                AS_IF([test -z "$tmpfilesdir"], 
[tmpfilesdir='${prefix}/lib/tmpfiles.d'])
        ])
 AC_SUBST([tmpfilesdir])
-PKGLIBEXECDIR="$libexecdir/kopano"
-AC_SUBST([PKGLIBEXECDIR])
 
 dnl Not all files will be installed to ${prefix}, so we need to cheat a bit
 dnl to make "distcheck" succeed.
@@ -729,17 +725,11 @@
                installer/Makefile
                installer/linux/Makefile
                installer/userscripts/Makefile
-               installer/userscripts/createcompany
                installer/userscripts/createcompany.d/Makefile
-               installer/userscripts/creategroup
                installer/userscripts/creategroup.d/Makefile
-               installer/userscripts/createuser
                installer/userscripts/createuser.d/Makefile
-               installer/userscripts/deletecompany
                installer/userscripts/deletecompany.d/Makefile
-               installer/userscripts/deletegroup
                installer/userscripts/deletegroup.d/Makefile
-               installer/userscripts/deleteuser
                installer/userscripts/deleteuser.d/Makefile
                installer/quotamail/Makefile
                installer/searchscripts/Makefile
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/doc/kopano-server.cfg.5 
new/kopanocore-8.6.6.1/doc/kopano-server.cfg.5
--- old/kopanocore-8.6.2.25/doc/kopano-server.cfg.5     2018-07-02 
15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/doc/kopano-server.cfg.5      2018-08-03 
09:36:26.000000000 +0200
@@ -358,6 +358,9 @@
 .PP
 The location where attachments are stored. This can be in the MySQL database, 
or as separate files. The drawback of \*(Aqdatabase\*(Aq is that the large data 
of attachment will push useful data from the MySQL cache. The drawback of 
separate files is that a mysqldump is not enough for a full disaster recovery.
 .PP
+Possible values: \fBdatabase\fP, \fBfiles\fP, and, if built with libs3/AWS
+support, \fBs3\fP.
+.PP
 Default:
 \fIfiles\fR
 .SS attachment_path
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/gateway/Gateway.cpp 
new/kopanocore-8.6.6.1/gateway/Gateway.cpp
--- old/kopanocore-8.6.2.25/gateway/Gateway.cpp 2018-07-02 15:42:42.000000000 
+0200
+++ new/kopanocore-8.6.6.1/gateway/Gateway.cpp  2018-08-03 09:36:26.000000000 
+0200
@@ -231,7 +231,10 @@
                        // we asked the client for more data, do not parse the 
buffer, but send it "to the previous command"
                        // that last part is currently only 
HrCmdAuthenticate(), so no difficulties here.
                        // also, PLAIN is the only supported auth method.
-                       client->HrProcessContinue(inBuffer);
+                       try {
+                               client->HrProcessContinue(inBuffer);
+                       } catch (const KMAPIError &e) {
+                       }
                        // no matter what happens, we continue handling the 
connection.
                        continue;
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/inetmapi/VMIMEToMAPI.cpp 
new/kopanocore-8.6.6.1/inetmapi/VMIMEToMAPI.cpp
--- old/kopanocore-8.6.2.25/inetmapi/VMIMEToMAPI.cpp    2018-07-02 
15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/inetmapi/VMIMEToMAPI.cpp     2018-08-03 
09:36:26.000000000 +0200
@@ -2769,10 +2769,17 @@
                }
                if (strncasecmp(in, "charset=", 8) == 0) {
                        in += 8;
-                       cset = in;
-                       while (!isspace(*in) && *in != ';' && *in != '\0')
-                               ++in;   /* skip value */
-                       cset_end = in;
+                       if (*in == '"') {
+                               cset = ++in;
+                               while (*in != '\0' && *in != '"')
+                                       ++in;
+                               cset_end = in;
+                       } else {
+                               cset = in;
+                               while (!isspace(*in) && *in != ';' && *in != 
'\0')
+                                       ++in;   /* skip value */
+                               cset_end = in;
+                       }
                        continue;
                        /* continue parsing for more charset= values */
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/installer/linux/kopano-dagent.init.rhel 
new/kopanocore-8.6.6.1/installer/linux/kopano-dagent.init.rhel
--- old/kopanocore-8.6.2.25/installer/linux/kopano-dagent.init.rhel     
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/linux/kopano-dagent.init.rhel      
2018-08-03 09:36:26.000000000 +0200
@@ -49,7 +49,7 @@
        if [ -f /opt/rh/rh-php56/enable ]; then
                . /opt/rh/rh-php56/enable
        fi
-       daemon $DAGENTPROGRAM $DAGENTCONFIG_OPT
+       daemon --pidfile="$pidfile" $DAGENTPROGRAM $DAGENTCONFIG_OPT
        RETVAL=$?
        unset LC_ALL LANG
        echo
@@ -60,7 +60,7 @@
 
 stop() {
        echo -n $"Stopping $dagent: "
-       killproc $DAGENTPROGRAM
+       killproc -p "$pidfile" $DAGENTPROGRAM
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && rm -f $lockfile $pidfile
@@ -91,7 +91,7 @@
                stop
                ;;
     status)
-               status $dagent
+               status -p "$pidfile" $dagent
                RETVAL=$?
                ;;
     restart|force-reload)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/installer/linux/kopano-gateway.init.rhel 
new/kopanocore-8.6.6.1/installer/linux/kopano-gateway.init.rhel
--- old/kopanocore-8.6.2.25/installer/linux/kopano-gateway.init.rhel    
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/linux/kopano-gateway.init.rhel     
2018-08-03 09:36:26.000000000 +0200
@@ -45,7 +45,7 @@
        # Start in background, always succeeds
        echo -n $"Starting $gateway: "
        install -dm0775 -o kopano -g kopano /var/run/kopano
-       daemon $GATEWAYPROGRAM $GATEWAYCONFIG_OPT
+       daemon --pidfile="$pidfile" $GATEWAYPROGRAM $GATEWAYCONFIG_OPT
        RETVAL=$?
        unset LC_ALL LANG
        echo
@@ -56,7 +56,7 @@
 
 stop() {
        echo -n $"Stopping $gateway: "
-       killproc $GATEWAYPROGRAM
+       killproc -p "$pidfile" $GATEWAYPROGRAM
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && rm -f $lockfile $pidfile
@@ -71,7 +71,7 @@
 
 reload() {
        echo -n $"Restarting $gateway: "
-       killproc $GATEWAYPROGRAM -SIGHUP
+       killproc -p "$pidfile" $GATEWAYPROGRAM -SIGHUP
        RETVAL=$?
        echo
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/installer/linux/kopano-ical.init.rhel 
new/kopanocore-8.6.6.1/installer/linux/kopano-ical.init.rhel
--- old/kopanocore-8.6.2.25/installer/linux/kopano-ical.init.rhel       
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/linux/kopano-ical.init.rhel        
2018-08-03 09:36:26.000000000 +0200
@@ -45,7 +45,7 @@
        # Start in background, always succeeds
        echo -n $"Starting $ical: "
        install -dm0775 -o kopano -g kopano /var/run/kopano
-       daemon $ICALPROGRAM $ICALCONFIG_OPT
+       daemon --pidfile="$pidfile" $ICALPROGRAM $ICALCONFIG_OPT
        RETVAL=$?
        unset LC_ALL LANG
        echo
@@ -56,7 +56,7 @@
 
 stop() {
        echo -n $"Stopping $ical: "
-       killproc $ICALPROGRAM
+       killproc -p "$pidfile" $ICALPROGRAM
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && rm -f $lockfile $pidfile
@@ -71,7 +71,7 @@
 
 reload() {
        echo -n $"Restarting $ical: "
-       killproc $ICALPROGRAM -SIGHUP
+       killproc -p "$pidfile" $ICALPROGRAM -SIGHUP
        RETVAL=$?
        echo
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/installer/linux/kopano-monitor.init.rhel 
new/kopanocore-8.6.6.1/installer/linux/kopano-monitor.init.rhel
--- old/kopanocore-8.6.2.25/installer/linux/kopano-monitor.init.rhel    
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/linux/kopano-monitor.init.rhel     
2018-08-03 09:36:26.000000000 +0200
@@ -45,7 +45,7 @@
        # Start in background, always succeeds
        echo -n $"Starting $monitor: "
        install -dm0775 -o kopano -g kopano /var/run/kopano
-       daemon $MONITORPROGRAM $MONITORCONFIG_OPT
+       daemon --pidfile="$pidfile" $MONITORPROGRAM $MONITORCONFIG_OPT
        RETVAL=$?
        unset LC_ALL LANG
        echo
@@ -56,7 +56,7 @@
 
 stop() {
        echo -n $"Stopping $monitor: "
-       killproc $MONITORPROGRAM
+       killproc -p "$pidfile" $MONITORPROGRAM
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && rm -f $lockfile $pidfile
@@ -71,7 +71,7 @@
 
 reload() {
        echo -n $"Restarting $monitor: "
-       killproc $MONITORPROGRAM -SIGHUP
+       killproc -p "$pidfile" $MONITORPROGRAM -SIGHUP
        RETVAL=$?
        echo
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/installer/linux/kopano-presence.init.rhel 
new/kopanocore-8.6.6.1/installer/linux/kopano-presence.init.rhel
--- old/kopanocore-8.6.2.25/installer/linux/kopano-presence.init.rhel   
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/linux/kopano-presence.init.rhel    
2018-08-03 09:36:26.000000000 +0200
@@ -45,7 +45,7 @@
        # Start in background, always succeeds
        echo -n $"Starting $presence: "
        install -dm0775 -o kopano -g kopano /var/run/kopano
-       daemon $PRESENCEPROGRAM $PRESENCECONFIG_OPT >/dev/null 2>&1
+       daemon --pidfile="$pidfile" $PRESENCEPROGRAM $PRESENCECONFIG_OPT 
>/dev/null 2>&1
        RETVAL=$?
        unset LC_ALL LANG
        echo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/installer/linux/kopano-search.init.rhel 
new/kopanocore-8.6.6.1/installer/linux/kopano-search.init.rhel
--- old/kopanocore-8.6.2.25/installer/linux/kopano-search.init.rhel     
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/linux/kopano-search.init.rhel      
2018-08-03 09:36:26.000000000 +0200
@@ -45,7 +45,7 @@
        # Start in background, always succeeds
        echo -n $"Starting $search: "
        install -dm0775 -o kopano -g kopano /var/run/kopano
-       daemon $SEARCHPROGRAM $SEARCHCONFIG_OPT >/dev/null 2>&1
+       daemon --pidfile="$pidfile" $SEARCHPROGRAM $SEARCHCONFIG_OPT >/dev/null 
2>&1
        RETVAL=$?
        unset LC_ALL LANG
        echo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/installer/linux/kopano-server.init.rhel 
new/kopanocore-8.6.6.1/installer/linux/kopano-server.init.rhel
--- old/kopanocore-8.6.2.25/installer/linux/kopano-server.init.rhel     
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/linux/kopano-server.init.rhel      
2018-08-03 09:36:26.000000000 +0200
@@ -46,7 +46,7 @@
        # Start in background, always succeeds
        echo -n $"Starting $server: "
        install -dm0775 -o kopano -g kopano /var/run/kopano
-       daemon $SERVERPROGRAM $SERVERCONFIG_OPT
+       daemon --pidfile="$pidfile" $SERVERPROGRAM $SERVERCONFIG_OPT
        RETVAL=$?
        unset LC_ALL LANG
        echo
@@ -111,7 +111,7 @@
 
 reload() {
        echo -n $"Restarting $server: "
-       killproc $SERVERPROGRAM -SIGHUP
+       killproc -p "$pidfile" $SERVERPROGRAM -SIGHUP
        RETVAL=$?
        echo
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/installer/linux/kopano-spamd.init.rhel 
new/kopanocore-8.6.6.1/installer/linux/kopano-spamd.init.rhel
--- old/kopanocore-8.6.2.25/installer/linux/kopano-spamd.init.rhel      
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/linux/kopano-spamd.init.rhel       
2018-08-03 09:36:26.000000000 +0200
@@ -44,7 +44,7 @@
        install -dm0775 -o kopano -g kopano /var/run/kopano
        export LC_ALL=$KOPANO_LOCALE
        export LANG=$KOPANO_LOCALE
-       daemon $SPAMDPROGRAM $SPAMDCONFIG_OPT >/dev/null 2>&1
+       daemon --pidfile="$pidfile" $SPAMDPROGRAM $SPAMDCONFIG_OPT >/dev/null 
2>&1
        RETVAL=$?
        unset LC_ALL LANG
        echo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/installer/linux/kopano-spooler.init.rhel 
new/kopanocore-8.6.6.1/installer/linux/kopano-spooler.init.rhel
--- old/kopanocore-8.6.2.25/installer/linux/kopano-spooler.init.rhel    
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/linux/kopano-spooler.init.rhel     
2018-08-03 09:36:26.000000000 +0200
@@ -45,7 +45,7 @@
        # Start in background, always succeeds
        echo -n $"Starting $spooler: "
        install -dm0775 -o kopano -g kopano /var/run/kopano
-       daemon $SPOOLERPROGRAM $SPOOLERCONFIG_OPT
+       daemon --pidfile="$pidfile" $SPOOLERPROGRAM $SPOOLERCONFIG_OPT
        RETVAL=$?
        unset LC_ALL LANG
        echo
@@ -56,7 +56,7 @@
 
 stop() {
        echo -n $"Stopping $spooler: "
-       killproc $SPOOLERPROGRAM
+       killproc -p "$pidfile" $SPOOLERPROGRAM
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && rm -f $lockfile $pidfile
@@ -71,7 +71,7 @@
 
 reload() {
        echo -n $"Restarting $spooler: "
-       killproc $SPOOLERPROGRAM -SIGHUP
+       killproc -p "$pidfile" $SPOOLERPROGRAM -SIGHUP
        RETVAL=$?
        echo
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/installer/linux/server.cfg 
new/kopanocore-8.6.6.1/installer/linux/server.cfg
--- old/kopanocore-8.6.2.25/installer/linux/server.cfg  2018-07-02 
15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/linux/server.cfg   2018-08-03 
09:36:26.000000000 +0200
@@ -45,7 +45,11 @@
 # Default: root
 local_admin_users = root kopano
 
-# The user has full rights on a folder by default, uncomment the following 
line to disable this.
+# With owner_auto_full_access=true, the owner of an object is, in addition to
+# any ACLs, implicitly granted "read", "create-in" and "is-visible" rights,
+# even if the store belongs to another user, for example, when it has been
+# moved via kopano-storeadm -D,-A.
+#
 #owner_auto_full_access = true
 
 # e-mail address of the Kopano System user
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/installer/userscripts/Makefile.am 
new/kopanocore-8.6.6.1/installer/userscripts/Makefile.am
--- old/kopanocore-8.6.2.25/installer/userscripts/Makefile.am   2018-07-02 
15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/installer/userscripts/Makefile.am    2018-08-03 
09:36:26.000000000 +0200
@@ -3,8 +3,22 @@
 bindir = ${dcprefix}${USERSCRIPTDIR}
 dist_data_DATA = users_common.sh groups_common.sh companies_common.sh
 datadir = ${dcprefix}${USERSCRIPTDIR}
+replcmd = ${AM_V_GEN}${SED} -e 's|[@]sysconfdir@|${sysconfdir}|g' -e 
's|[@]PKGLIBEXECDIR@|${pkglibexecdir}|g' -e 
's|[@]USERSCRIPTDIR@|${USERSCRIPTDIR}|g' <"$<" >"$@"
 
 install-data-hook:
        for dir in $(SUBDIRS); do \
                mkdir -p ${DESTDIR}/${dcprefix}${USERSCRIPTDIR}/$$dir; \
        done
+
+createcompany: createcompany.in ${top_builddir}/config.status
+       ${replcmd}
+deletecompany: deletecompany.in ${top_builddir}/config.status
+       ${replcmd}
+creategroup: creategroup.in ${top_builddir}/config.status
+       ${replcmd}
+deletegroup: deletegroup.in ${top_builddir}/config.status
+       ${replcmd}
+createuser: createuser.in ${top_builddir}/config.status
+       ${replcmd}
+deleteuser: deleteuser.in ${top_builddir}/config.status
+       ${replcmd}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/php-ext/include/mapi/class.meetingrequest.php 
new/kopanocore-8.6.6.1/php-ext/include/mapi/class.meetingrequest.php
--- old/kopanocore-8.6.2.25/php-ext/include/mapi/class.meetingrequest.php       
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/php-ext/include/mapi/class.meetingrequest.php        
2018-08-03 09:36:26.000000000 +0200
@@ -173,7 +173,11 @@
                $properties["timezone"] = 
"PT_STRING8:PSETID_Appointment:0x8234";
                $properties["toattendeesstring"] = 
"PT_STRING8:PSETID_Appointment:0x823B";
                $properties["ccattendeesstring"] = 
"PT_STRING8:PSETID_Appointment:0x823C";
+
                $this->proptags = getPropIdsFromStrings($store, $properties);
+
+               $properties2["categories"] = 
"PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords";
+               $this->proptags2 = getPropIdsFromStrings($store, $properties2);
        }
 
        /**
@@ -739,6 +743,11 @@
 
                                // Copy properties
                                $props = mapi_getprops($this->message);
+
+                               // While we applying updates of MR then all 
local categories will be removed,
+                               // So get the local categories of all 
occurrence before applying update from organiser.
+                               $localCategories = 
$this->getLocalCategories($calendarItem, $store, $calFolder);
+
                                $props[PR_MESSAGE_CLASS] = 'IPM.Appointment';
                                $props[$this->proptags['meetingstatus']] = 
olMeetingReceived;
                                // when we are automatically processing the 
meeting request set responsestatus to olResponseNotResponded
@@ -784,6 +793,13 @@
                                        }
                                }
                                mapi_savechanges($calendarItem);
+
+                               // After applying update of organiser all local 
categories of occurrence was removed,
+                               // So if local categories exist then apply it 
on respective occurrence.
+                               if (!empty($localCategories)) {
+                                       
$this->applyLocalCategories($calendarItem, $store, $localCategories);
+                               }
+
                                if ($move) {
                                        $wastebasket = 
$this->openDefaultWastebasket();
                                        mapi_folder_copymessages($calFolder, 
Array($props[PR_ENTRYID]), $wastebasket, MESSAGE_MOVE);
@@ -816,8 +832,12 @@
                                if (!$calendarItem) {
                                        $items = 
$this->findCalendarItems($messageprops[$this->proptags['goid']], $calFolder);
 
-                                       if (is_array($items))
+                                       if (is_array($items)) {
+                                               // Get local categories before 
deleting MR.
+                                               $message = 
mapi_msgstore_openentry($store, $items[0]);
+                                               $localCategories = 
mapi_getprops($message, array($this->proptags2['categories']));
                                                
mapi_folder_deletemessages($calFolder, $items);
+                                       }
 
                                        if ($move) {
                                                // All we have to do is open 
the default calendar,
@@ -833,6 +853,11 @@
                                                /* release old message */
                                                $message = null;
 
+                                               // After creating new MR, If 
local categories exist then apply it on new MR.
+                                               if(!empty($localCategories)) {
+                                                       mapi_setprops($calmsg, 
$localCategories);
+                                               }
+
                                                $calItemProps = Array();
                                                $calItemProps[PR_MESSAGE_CLASS] 
= "IPM.Appointment";
 
@@ -889,6 +914,12 @@
                                                $props = 
mapi_getprops($this->message);
 
                                                $props[PR_MESSAGE_CLASS] = 
"IPM.Appointment";
+
+                                               // After creating new MR, If 
local categories exist then apply it on new MR.
+                                               if (!empty($localCategories)) {
+                                                       mapi_setprops($new, 
$localCategories);
+                                               }
+
                                                // when we are automatically 
processing the meeting request set responsestatus to olResponseNotResponded
                                                
$props[$this->proptags['responsestatus']] = $userAction ? ($tentative ? 
olResponseTentative : olResponseAccepted) : olResponseNotResponded;
 
@@ -3078,4 +3109,69 @@
        {
                $this->meetingTimeInfo = $meetingTimeInfo;
        }
+
+       /**
+        * Helper function which is use to get local categories of all 
occurrence.
+        *
+        * @param MAPIMessage $calendarItem meeting request item
+        * @param MAPIStore $store store containing calendar folder
+        * @param MAPIFolder $calFolder calendar folder
+        * @return Array $localCategories which contain array of basedate along 
with categories
+        */
+       function getLocalCategories($calendarItem, $store, $calFolder)
+       {
+               $calendarItemProps = mapi_getprops($calendarItem);
+               $recurrence = new Recurrence($store, $calendarItem);
+
+               //Retrieve all occurrences(max: 30 occurrence because 
recurrence can also be set as 'no end date')
+               $items = 
$recurrence->getItems($calendarItemProps[$this->proptags['clipstart']], 
$calendarItemProps[$this->proptags['clipend']] * (24*24*60), 30);
+               $localCategories = array();
+
+               foreach ($items as $item) {
+                       $recurrenceItems = 
$recurrence->getCalendarItems($store, $calFolder, 
$item[$this->proptags['startdate']], $item[$this->proptags['duedate']], 
array($this->proptags['goid'], $this->proptags['busystatus'], 
$this->proptags2['categories']));
+                       foreach ($recurrenceItems as $recurrenceItem) {
+
+                               // Check if occurrence is exception then get 
the local categories of that occurrence.
+                               if 
(isset($recurrenceItem[$this->proptags['goid']]) && 
$recurrenceItem[$this->proptags['goid']] == 
$calendarItemProps[$this->proptags['goid']]) {
+
+                                       $exceptionAttach = 
$recurrence->getExceptionAttachment($recurrenceItem['basedate']);
+
+                                       if ($exceptionAttach) {
+                                               $exception = 
mapi_attach_openobj($exceptionAttach, 0);
+                                               $exceptionProps = 
mapi_getprops($exception, array($this->proptags2['categories']));
+                                               if 
(isset($exceptionProps[$this->proptags2['categories']])) {
+                                                       
$localCategories[$recurrenceItem['basedate']] = 
$exceptionProps[$this->proptags2['categories']];
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return $localCategories;
+       }
+
+       /**
+        * Helper function which is use to apply local categories on respective 
occurrences.
+        *
+        * @param MAPIMessage $calendarItem meeting request item
+        * @param MAPIStore $store store containing calendar folder
+        * @param Array $localCategories array contains basedate and array of 
categories
+        */
+       function applyLocalCategories($calendarItem, $store, $localCategories)
+       {
+               $calendarItemProps = mapi_getprops($calendarItem, 
array(PR_PARENT_ENTRYID, PR_ENTRYID));
+               $message = mapi_msgstore_openentry($store, 
$calendarItemProps[PR_ENTRYID]);
+               $recurrence = new Recurrence($store, $message);
+
+               // Check for all occurrence if it is exception then modify the 
exception by setting up categories,
+               // Otherwise create new exception with categories.
+               foreach ($localCategories as $key => $value) {
+                       if ($recurrence->isException($key)) {
+                               
$recurrence->modifyException(array($this->proptags2['categories'] => $value), 
$key);
+                       } else {
+                               
$recurrence->createException(array($this->proptags2['categories'] => $value), 
$key, false);
+                       }
+                       mapi_savechanges($message);
+               }
+       }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/php7-ext/main.cpp 
new/kopanocore-8.6.6.1/php7-ext/main.cpp
--- old/kopanocore-8.6.2.25/php7-ext/main.cpp   2018-07-02 15:42:42.000000000 
+0200
+++ new/kopanocore-8.6.6.1/php7-ext/main.cpp    2018-08-03 09:36:26.000000000 
+0200
@@ -7101,7 +7101,7 @@
        zval *resSession;
        zval *resStore;
        zval *resMessage;
-       ULONG cbString = 0;
+       php_stringsize_t cbString = 0;
        char *szString = nullptr;
        IMAPISession *lpMAPISession = nullptr;
        IMessage *lpMessage = nullptr;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/provider/client/ClientUtil.cpp 
new/kopanocore-8.6.6.1/provider/client/ClientUtil.cpp
--- old/kopanocore-8.6.2.25/provider/client/ClientUtil.cpp      2018-07-02 
15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/provider/client/ClientUtil.cpp       2018-08-03 
09:36:26.000000000 +0200
@@ -710,41 +710,30 @@
 HRESULT HrGetServerURLFromStoreEntryId(ULONG cbEntryId,
     const ENTRYID *lpEntryId, std::string &rServerPath, bool *lpbIsPseudoUrl)
 {
-       PEID    peid = (PEID)lpEntryId;
-       EID_V0* peid_V0 = NULL;
-
-       ULONG   ulMaxSize = 0;
-       ULONG   ulSize = 0;
-       char*   lpTmpServerName = NULL;
-       bool    bIsPseudoUrl = false;
-
-       if (lpEntryId == NULL || lpbIsPseudoUrl == NULL)
+       if (lpEntryId == nullptr || lpbIsPseudoUrl == nullptr)
                return MAPI_E_INVALID_PARAMETER;
+       if (cbEntryId < offsetof(EID, ulVersion) + sizeof(EID::ulVersion))
+               return MAPI_E_INVALID_ENTRYID;
 
-       if (peid->ulVersion == 0) 
-       {
-               peid_V0 = (EID_V0*)lpEntryId;
-
-               ulMaxSize = cbEntryId - offsetof(EID_V0, szServer);
-               ulSize = strnlen((char*)peid_V0->szServer, ulMaxSize);
-               lpTmpServerName = (char*)peid_V0->szServer;
-       } else {
-               ulMaxSize = cbEntryId - offsetof(EID, szServer);
-               ulSize = strnlen((char*)peid->szServer, ulMaxSize);
-               lpTmpServerName = (char*)peid->szServer;
-       }
-
-       if (ulSize >= ulMaxSize)
-               return MAPI_E_NOT_FOUND;
-       if (strncasecmp(lpTmpServerName, "pseudo://", 9) == 0)
+       bool    bIsPseudoUrl = false;
+       auto eby = reinterpret_cast<const char *>(lpEntryId);
+       decltype(EID::ulVersion) version;
+       std::string path;
+
+       memcpy(&version, eby + offsetof(EID, ulVersion), sizeof(version));
+       auto z = (version == 0) ? offsetof(EID_V0, szServer) : offsetof(EID, 
szServer);
+       path.assign(eby + z, cbEntryId - z);
+       auto pos = path.find_first_of('\0');
+       if (pos != std::string::npos)
+               path.erase(pos);
+       if (kc_starts_with(path, "pseudo://"))
                bIsPseudoUrl = true;
-       else if (strncasecmp(lpTmpServerName, "http://";, 7) && 
-                        strncasecmp(lpTmpServerName, "https://";, 8) && 
-                        strncasecmp(lpTmpServerName, "file://", 7) &&
-                        strncasecmp(lpTmpServerName, "default:", 8))
+       else if (!kc_starts_with(path, "http://";) &&
+           !kc_starts_with(path, "https://";) &&
+           !kc_starts_with(path, "file://") &&
+           !kc_starts_with(path, "default:"))
                return MAPI_E_NOT_FOUND;
-
-       rServerPath = lpTmpServerName;
+       rServerPath = std::move(path);
        *lpbIsPseudoUrl = bIsPseudoUrl;
        return hrSuccess;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/provider/libserver/ECIndexer.cpp 
new/kopanocore-8.6.6.1/provider/libserver/ECIndexer.cpp
--- old/kopanocore-8.6.2.25/provider/libserver/ECIndexer.cpp    2018-07-02 
15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/provider/libserver/ECIndexer.cpp     2018-08-03 
09:36:26.000000000 +0200
@@ -313,7 +313,7 @@
        std::unique_ptr<ECSearchClient> lpSearchClient;
        std::set<unsigned int> setExcludePropTags;
        KC::time_point tstart;
-       LONGLONG        llelapsedtime;
+       LONGLONG llelapsedtime;
        struct restrictTable *lpOptimizedRestrict = NULL;
        std::list<SIndexedTerm> lstMultiSearches;
        const char* szSocket = lpConfig->GetSetting("search_socket");
@@ -372,7 +372,7 @@
                g_lpStatsCollector->Increment(SCN_INDEXER_SEARCH_ERRORS);
                ec_log_err("Error while querying search on \"%s\", 0x%08x", 
szSocket, er);
        } else
-               ec_log_debug("Indexed query results found in %.4f ms", 
llelapsedtime/1000.0);
+               ec_log_debug("Indexed query results found in %u ms", 
static_cast<unsigned int>(llelapsedtime));
 
        ec_log_debug("%zu indexed matches found", lstMatches.size());
        *lppNewRestrict = lpOptimizedRestrict;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/provider/libserver/ECS3Attachment.cpp 
new/kopanocore-8.6.6.1/provider/libserver/ECS3Attachment.cpp
--- old/kopanocore-8.6.2.25/provider/libserver/ECS3Attachment.cpp       
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/provider/libserver/ECS3Attachment.cpp        
2018-08-03 09:36:26.000000000 +0200
@@ -469,7 +469,7 @@
                ret = erSuccess;
        }
        if (ret != erSuccess && cd.data != nullptr && soap == nullptr)
-               delete cd.data;
+               s_free(nullptr, cd.data);
        /*
         * Make sure we clear the cd.data variable so we cannot write
         * to it after it is freed externally.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/provider/plugins/LDAPUserPlugin.cpp 
new/kopanocore-8.6.6.1/provider/plugins/LDAPUserPlugin.cpp
--- old/kopanocore-8.6.2.25/provider/plugins/LDAPUserPlugin.cpp 2018-07-02 
15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/provider/plugins/LDAPUserPlugin.cpp  2018-08-03 
09:36:26.000000000 +0200
@@ -245,7 +245,7 @@
 
 std::unique_ptr<LDAPCache> LDAPUserPlugin::m_lpCache(new LDAPCache());
 
-template<typename T> static constexpr inline LONGLONG dur2ms(const T &t)
+template<typename T> static constexpr inline LONGLONG dur2us(const T &t)
 {
        return std::chrono::duration_cast<std::chrono::milliseconds>(t).count();
 }
@@ -438,7 +438,6 @@
 LDAP *LDAPUserPlugin::ConnectLDAP(const char *bind_dn, const char *bind_pw) {
        int rc = -1;
        LDAP *ld = NULL;
-       LONGLONG llelapsedtime = 0;
        auto tstart = std::chrono::steady_clock::now();
 
        if ((bind_dn != nullptr && bind_dn[0] != '\0') &&
@@ -514,7 +513,7 @@
                        throw ldap_error("Failure connecting any of the LDAP 
servers");
        }
 
-       llelapsedtime = dur2ms(decltype(tstart)::clock::now() - tstart);
+       auto llelapsedtime = dur2us(decltype(tstart)::clock::now() - tstart);
        m_lpStatsCollector->Increment(SCN_LDAP_CONNECTS);
        m_lpStatsCollector->Increment(SCN_LDAP_CONNECT_TIME, llelapsedtime);
        m_lpStatsCollector->Max(SCN_LDAP_CONNECT_TIME_MAX, llelapsedtime);
@@ -598,7 +597,7 @@
                goto exit;
        }
 
-       llelapsedtime = dur2ms(decltype(tstart)::clock::now() - tstart);
+       llelapsedtime = dur2us(decltype(tstart)::clock::now() - tstart);
        LOG_PLUGIN_DEBUG("ldaptiming [%08.2f] (\"%s\" \"%s\" %s), results: %d", 
llelapsedtime/1000000.0, base, filter, req.c_str(), ldap_count_entries(m_ldap, 
res));
 
        *lppres = res.release(); // deref the pointer from object
@@ -1438,7 +1437,7 @@
                throw;
        }
 
-       auto llelapsedtime = dur2ms(decltype(tstart)::clock::now() - tstart);
+       auto llelapsedtime = dur2us(decltype(tstart)::clock::now() - tstart);
        m_lpStatsCollector->Increment(SCN_LDAP_AUTH_LOGINS);
        m_lpStatsCollector->Increment(SCN_LDAP_AUTH_TIME, llelapsedtime);
        m_lpStatsCollector->Max(SCN_LDAP_AUTH_TIME_MAX, llelapsedtime);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/provider/server/ECServer.cpp 
new/kopanocore-8.6.6.1/provider/server/ECServer.cpp
--- old/kopanocore-8.6.2.25/provider/server/ECServer.cpp        2018-07-02 
15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/provider/server/ECServer.cpp 2018-08-03 
09:36:26.000000000 +0200
@@ -1048,6 +1048,7 @@
 
        auto laters = make_scope_success([&]() {
                cleanup(er);
+               g_lpSoapServerConn.reset();
                ssl_threading_cleanup();
                SSL_library_cleanup(); //cleanup memory so valgrind is happy
        });
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kopanocore-8.6.2.25/spooler/rules.cpp 
new/kopanocore-8.6.6.1/spooler/rules.cpp
--- old/kopanocore-8.6.2.25/spooler/rules.cpp   2018-07-02 15:42:42.000000000 
+0200
+++ new/kopanocore-8.6.6.1/spooler/rules.cpp    2018-08-03 09:36:26.000000000 
+0200
@@ -446,7 +446,8 @@
        if (ret != hrSuccess)
                return kc_perror("K-2382", ret);
        object_ptr<IMAPIFolder> inbox;
-       ret = store->OpenEntry(eid_size, eid, &iid_of(inbox), MAPI_MODIFY, 
nullptr, &~inbox);
+       unsigned int objtype = 0;
+       ret = store->OpenEntry(eid_size, eid, &iid_of(inbox), MAPI_MODIFY, 
&objtype, &~inbox);
        if (ret != hrSuccess)
                return kc_perror("K-2383", ret);
        object_ptr<IMessage> msg;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kopanocore-8.6.2.25/swig/python/kopano/kopano/meetingrequest.py 
new/kopanocore-8.6.6.1/swig/python/kopano/kopano/meetingrequest.py
--- old/kopanocore-8.6.2.25/swig/python/kopano/kopano/meetingrequest.py 
2018-07-02 15:42:42.000000000 +0200
+++ new/kopanocore-8.6.6.1/swig/python/kopano/kopano/meetingrequest.py  
2018-08-03 09:36:26.000000000 +0200
@@ -314,6 +314,9 @@
                 self._init_calitem(cal_item, tentative)
 
         else:
+            # preserve categories # TODO preserve everything unrelated?
+            categories = cal_item.categories if cal_item else []
+
             # remove existing recurrence
             if cal_item and cal_item.recurring:
                 mr_counter = self.update_counter
@@ -336,6 +339,8 @@
 
             # create new recurrence
             cal_item = self.item.copy(calendar)
+            if categories:
+                cal_item.categories = categories
 
             # merge existing exceptions
             if cal_item.recurring and existing_items:


Reply via email to