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:
