Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package gromox for openSUSE:Factory checked 
in at 2024-10-16 23:44:43
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gromox (Old)
 and      /work/SRC/openSUSE:Factory/.gromox.new.19354 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "gromox"

Wed Oct 16 23:44:43 2024 rev:37 rq:1208138 version:2.35

Changes:
--------
--- /work/SRC/openSUSE:Factory/gromox/gromox.changes    2024-10-09 
22:12:45.301773739 +0200
+++ /work/SRC/openSUSE:Factory/.gromox.new.19354/gromox.changes 2024-10-16 
23:45:48.138604012 +0200
@@ -1,0 +2,13 @@
+Tue Oct 15 11:24:31 UTC 2024 - Jan Engelhardt <jeng...@inai.de>
+
+- Update to release 2.35
+  * alias_resolve: resolve nullptr deref crash
+  * ews: resolve nullptr deref crash
+  * mapi_lib: fix out-of-bounds access in PROBLEM_ARRAY::transform
+  * mapi_lib: rop_util_get_gc_value used the wrong mask, which
+    caused "Change commit failed because the object was changed
+    separately"
+  * exmdb: let PR_ACCESS include permissions from all group
+    memberships
+
+-------------------------------------------------------------------

Old:
----
  gromox-2.34.tar.asc
  gromox-2.34.tar.zst

New:
----
  gromox-2.35.tar.asc
  gromox-2.35.tar.zst

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

Other differences:
------------------
++++++ gromox.spec ++++++
--- /var/tmp/diff_new_pack.VAxCOQ/_old  2024-10-16 23:45:50.094685590 +0200
+++ /var/tmp/diff_new_pack.VAxCOQ/_new  2024-10-16 23:45:50.094685590 +0200
@@ -19,7 +19,7 @@
 %define _libexecdir %_prefix/libexec
 
 Name:           gromox
-Version:        2.34
+Version:        2.35
 Release:        0
 Summary:        Groupware server backend with RPC, IMAP,POP3, PHP-MAPI support
 License:        AGPL-3.0-or-later AND GPL-2.0-only AND GPL-3.0-or-later

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.VAxCOQ/_old  2024-10-16 23:45:50.122686758 +0200
+++ /var/tmp/diff_new_pack.VAxCOQ/_new  2024-10-16 23:45:50.126686925 +0200
@@ -1,5 +1,5 @@
-mtime: 1728411261
-commit: cc345f88432cf95111be4b4453707448701142ce36438794c307db79bab02063
+mtime: 1728994419
+commit: fbc8d5d4df0f2ccdb4181c021e33c3f7e1d54871af839a0bb7c1d754fa4f8ebd
 url: https://src.opensuse.org/jengelh/gromox
 revision: master
 

++++++ build.specials.obscpio ++++++
diff: old/*: No such file or directory
diff: new/*: No such file or directory

++++++ debian.changelog ++++++
--- /var/tmp/diff_new_pack.VAxCOQ/_old  2024-10-16 23:45:50.214690595 +0200
+++ /var/tmp/diff_new_pack.VAxCOQ/_new  2024-10-16 23:45:50.218690762 +0200
@@ -1,9 +1,9 @@
-gromox (2.34-0) unstable; urgency=low
+gromox (2.35-0) unstable; urgency=low
 
   * The build process is supposed to replace the entries here
     automatically from data present in gromox.changes.
     But if you see this message in installed systems,
     that would indicate a problem in debtransform(1).
 
- -- Gromox <n...@gromox.com>  Tue, 08 Oct 2024 17:10:00 +0200
+ -- Gromox <n...@gromox.com>  Tue, 15 Oct 2024 13:25:00 +0200
 

++++++ gromox-2.34.tar.zst -> gromox-2.35.tar.zst ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/Makefile.am new/gromox-2.35/Makefile.am
--- old/gromox-2.34/Makefile.am 2024-10-08 17:35:13.000000000 +0200
+++ new/gromox-2.35/Makefile.am 2024-10-15 13:20:17.000000000 +0200
@@ -277,7 +277,7 @@
 tests_epv_unpack_SOURCES = tests/epv_unpack.cpp tools/edb_pack.cpp 
tools/edb_pack.hpp
 tests_epv_unpack_LDADD = ${libesedb_LIBS} ${libHX_LIBS} libgromox_common.la 
libgromox_mapi.la
 tests_exrpctest_SOURCES = tests/exrpctest.cpp
-tests_exrpctest_LDADD = libgromox_common.la libgromox_exrpc.la
+tests_exrpctest_LDADD = libgromox_common.la libgromox_exrpc.la 
libgromox_mapi.la
 tests_gxl_383_SOURCES = tests/gxl-383.cpp
 tests_gxl_383_LDADD = libgromox_common.la libgromox_exrpc.la libgromox_mapi.la
 tests_jsontest_SOURCES = tests/jsontest.cpp
@@ -373,7 +373,7 @@
         -e 's|#define LOCALSTATEDIR .*|#define LOCALSTATEDIR 
"${localstatedir}"|' \
         -e 's|#define PKGDATADIR .*|#define PKGDATADIR "${pkgdatadir}"|' \
                <${srcdir}/include/gromox/paths.h.in >"$@.tmp"
-       ${AM_V_at}if ! cmp "$@" "$@.tmp" 2>/dev/null; then mv "$@.tmp" "$@"; 
fi; rm -f "$@.tmp"
+       ${AM_V_at}if ! cmp "$@" "$@.tmp" >/dev/null 2>/dev/null; then mv 
"$@.tmp" "$@"; fi; rm -f "$@.tmp"
 
 include/mapierr.cpp: include/gromox/mapierr.hpp tools/defs2php.sh 
tools/defs2php.pl
        ${AM_V_GEN}${MKDIR_P} include/gromox
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/Makefile.in new/gromox-2.35/Makefile.in
--- old/gromox-2.34/Makefile.in 2024-10-08 17:41:16.622193396 +0200
+++ new/gromox-2.35/Makefile.in 2024-10-15 14:11:18.645312781 +0200
@@ -767,7 +767,8 @@
        $(am__DEPENDENCIES_1) libgromox_common.la libgromox_mapi.la
 am_tests_exrpctest_OBJECTS = tests/exrpctest.$(OBJEXT)
 tests_exrpctest_OBJECTS = $(am_tests_exrpctest_OBJECTS)
-tests_exrpctest_DEPENDENCIES = libgromox_common.la libgromox_exrpc.la
+tests_exrpctest_DEPENDENCIES = libgromox_common.la libgromox_exrpc.la \
+       libgromox_mapi.la
 am_tests_gxl_383_OBJECTS = tests/gxl-383.$(OBJEXT)
 tests_gxl_383_OBJECTS = $(am_tests_gxl_383_OBJECTS)
 tests_gxl_383_DEPENDENCIES = libgromox_common.la libgromox_exrpc.la \
@@ -1899,7 +1900,7 @@
 tests_epv_unpack_SOURCES = tests/epv_unpack.cpp tools/edb_pack.cpp 
tools/edb_pack.hpp
 tests_epv_unpack_LDADD = ${libesedb_LIBS} ${libHX_LIBS} libgromox_common.la 
libgromox_mapi.la
 tests_exrpctest_SOURCES = tests/exrpctest.cpp
-tests_exrpctest_LDADD = libgromox_common.la libgromox_exrpc.la
+tests_exrpctest_LDADD = libgromox_common.la libgromox_exrpc.la 
libgromox_mapi.la
 tests_gxl_383_SOURCES = tests/gxl-383.cpp
 tests_gxl_383_LDADD = libgromox_common.la libgromox_exrpc.la libgromox_mapi.la
 tests_jsontest_SOURCES = tests/jsontest.cpp
@@ -5750,7 +5751,7 @@
         -e 's|#define LOCALSTATEDIR .*|#define LOCALSTATEDIR 
"${localstatedir}"|' \
         -e 's|#define PKGDATADIR .*|#define PKGDATADIR "${pkgdatadir}"|' \
                <${srcdir}/include/gromox/paths.h.in >"$@.tmp"
-       ${AM_V_at}if ! cmp "$@" "$@.tmp" 2>/dev/null; then mv "$@.tmp" "$@"; 
fi; rm -f "$@.tmp"
+       ${AM_V_at}if ! cmp "$@" "$@.tmp" >/dev/null 2>/dev/null; then mv 
"$@.tmp" "$@"; fi; rm -f "$@.tmp"
 
 include/mapierr.cpp: include/gromox/mapierr.hpp tools/defs2php.sh 
tools/defs2php.pl
        ${AM_V_GEN}${MKDIR_P} include/gromox
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/configure new/gromox-2.35/configure
--- old/gromox-2.34/configure   2024-10-08 17:41:16.062181357 +0200
+++ new/gromox-2.35/configure   2024-10-15 14:11:18.091981290 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for gromox 2.34.
+# Generated by GNU Autoconf 2.72 for gromox 2.35.
 #
 #
 # Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
@@ -611,8 +611,8 @@
 # Identity of this package.
 PACKAGE_NAME='gromox'
 PACKAGE_TARNAME='gromox'
-PACKAGE_VERSION='2.34'
-PACKAGE_STRING='gromox 2.34'
+PACKAGE_VERSION='2.35'
+PACKAGE_STRING='gromox 2.35'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1483,7 +1483,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-'configure' configures gromox 2.34 to adapt to many kinds of systems.
+'configure' configures gromox 2.35 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1554,7 +1554,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of gromox 2.34:";;
+     short | recursive ) echo "Configuration of gromox 2.35:";;
    esac
   cat <<\_ACEOF
 
@@ -1747,7 +1747,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-gromox configure 2.34
+gromox configure 2.35
 generated by GNU Autoconf 2.72
 
 Copyright (C) 2023 Free Software Foundation, Inc.
@@ -2197,7 +2197,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by gromox $as_me 2.34, which was
+It was created by gromox $as_me 2.35, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -3891,7 +3891,7 @@
 
 # Define the identity of the package.
  PACKAGE='gromox'
- VERSION='2.34'
+ VERSION='2.35'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -17715,51 +17715,56 @@
 my_CFLAGS="-Wall -Wmissing-declarations -Wwrite-strings"
 my_CXXFLAGS="-Wall -Wmissing-declarations"
 my_LDFLAGS=""
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking available C++ standard" 
>&5
-printf %s "checking available C++ standard... " >&6; }
-cxxmode=""
-for i in "c++26" "c++2c" "c++23" "c++2b" "c++20"; do
+cxxmode="error"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ standard 
availability" >&5
+printf %s "checking for C++ standard availability... " >&6; }
+echo ""
+for i in "" "c++26" "c++2c" "c++23" "c++2b" "c++20"; do
                if test -n "$COVERITY" && test "$i" != "c++20"
 then :
   continue
 fi
-       CXXFLAGS="$saved_CXXFLAGS -std=$i"
+       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CXX${i:+ 
-std=$i} works for our code" >&5
+printf %s "checking if $CXX${i:+ -std=$i} works for our code... " >&6; }
+       CXXFLAGS="$saved_CXXFLAGS${i:+ -std=$i}"
        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
                #include <span>
+               #include <unordered_map>
                #include <vector>
                int main() {
                        std::vector<int> v{1,9};
                        std::span s = v;
+                       std::unordered_map<int, int> um{{}};
                }
 
 _ACEOF
 if ac_fn_cxx_try_compile "$LINENO"
 then :
-  cxxmode="$i"
+
+               { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+               cxxmode="${i:+ -std=$i}"
+               break
+
+else case e in #(
+  e)
+               { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+        ;;
+esac
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-       if test -n "$cxxmode"
-then :
-  break
-fi
 done
 CXXFLAGS="$saved_CXXFLAGS"
-if test -n "$cxxmode"
+if test "$cxxmode" = error
 then :
 
-       my_CXXFLAGS="$my_CXXFLAGS -std=$cxxmode"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cxxmode" >&5
-printf "%s\n" "$cxxmode" >&6; }
+       as_fn_error $? "None of the -std= flags we tried led to successful 
compilation, but we need C++20 support." "$LINENO" 5
 
-else case e in #(
-  e)
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
-printf "%s\n" "none" >&6; }
- ;;
-esac
 fi
+my_CXXFLAGS="$my_CXXFLAGS${cxxmode}"
 
 
 # Check whether --with-asan was given.
@@ -21220,7 +21225,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by gromox $as_me 2.34, which was
+This file was extended by gromox $as_me 2.35, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21288,7 +21293,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-gromox config.status 2.34
+gromox config.status 2.35
 configured by $0, generated by GNU Autoconf 2.72,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/configure.ac new/gromox-2.35/configure.ac
--- old/gromox-2.34/configure.ac        2024-10-08 17:35:13.000000000 +0200
+++ new/gromox-2.35/configure.ac        2024-10-15 13:20:17.000000000 +0200
@@ -1,4 +1,4 @@
-AC_INIT([gromox], [2.34])
+AC_INIT([gromox], [2.35])
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_MACRO_DIR([build-aux])
 AC_PREFIX_DEFAULT([/usr])
@@ -24,29 +24,36 @@
 my_CFLAGS="-Wall -Wmissing-declarations -Wwrite-strings"
 my_CXXFLAGS="-Wall -Wmissing-declarations"
 my_LDFLAGS=""
-AC_MSG_CHECKING([available C++ standard])
-cxxmode=""
-for i in "c++26" "c++2c" "c++23" "c++2b" "c++20"; do
+cxxmode="error"
+AC_MSG_CHECKING([for C++ standard availability])
+echo ""
+for i in "" "c++26" "c++2c" "c++23" "c++2b" "c++20"; do
        dnl cov-scan cannot take too high a standard
        AS_IF([test -n "$COVERITY" && test "$i" != "c++20"], [continue])
-       CXXFLAGS="$saved_CXXFLAGS -std=$i"
+       AC_MSG_CHECKING([if $CXX${i:+ -std=$i} works for our code])
+       CXXFLAGS="$saved_CXXFLAGS${i:+ -std=$i}"
        AC_COMPILE_IFELSE([AC_LANG_SOURCE([
                #include <span>
+               #include <unordered_map>
                #include <vector>
                int main() {
                        std::vector<int> v{1,9};
                        std::span s = v;
+                       std::unordered_map<int, int> um{{}};
                }
-       ])], [cxxmode="$i"])
-       AS_IF([test -n "$cxxmode"], [break])
+       ])], [
+               AC_MSG_RESULT([yes])
+               cxxmode="${i:+ -std=$i}"
+               break
+       ], [
+               AC_MSG_RESULT([no])
+       ])
 done
 CXXFLAGS="$saved_CXXFLAGS"
-AS_IF([test -n "$cxxmode"], [
-       my_CXXFLAGS="$my_CXXFLAGS -std=$cxxmode"
-       AC_MSG_RESULT([$cxxmode])
-], [
-       AC_MSG_RESULT([none])
+AS_IF([test "$cxxmode" = error], [
+       AC_MSG_ERROR([None of the -std= flags we tried led to successful 
compilation, but we need C++20 support.])
 ])
+my_CXXFLAGS="$my_CXXFLAGS${cxxmode}"
 
 AC_ARG_WITH([asan], AS_HELP_STRING([--with-asan], [Activate Address 
Sanitizer]),
        [
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/doc/changelog.rst 
new/gromox-2.35/doc/changelog.rst
--- old/gromox-2.34/doc/changelog.rst   2024-10-08 17:35:13.000000000 +0200
+++ new/gromox-2.35/doc/changelog.rst   2024-10-15 13:20:17.000000000 +0200
@@ -1,3 +1,19 @@
+Gromox 2.35 92024-10-15)
+========================
+
+Fixes:
+
+* alias_resolve: resolve nullptr deref crash
+* ews: resolve nullptr deref crash
+* mapi_lib: fix out-of-bounds access in PROBLEM_ARRAY::transform
+* mapi_lib: rop_util_get_gc_value used the wrong mask, which caused
+  "Change commit failed because the object was changed separately"
+
+Changes:
+
+* exmdb: let PR_ACCESS include permissions from all group memberships
+
+
 Gromox 2.34 (2024-10-08)
 ========================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/exch/emsmdb/attachment_object.cpp 
new/gromox-2.35/exch/emsmdb/attachment_object.cpp
--- old/gromox-2.34/exch/emsmdb/attachment_object.cpp   2024-10-08 
17:35:13.000000000 +0200
+++ new/gromox-2.35/exch/emsmdb/attachment_object.cpp   2024-10-15 
13:20:17.000000000 +0200
@@ -1,10 +1,13 @@
 // SPDX-License-Identifier: GPL-2.0-only WITH linking exception
+// SPDX-FileCopyrightText: 2021–2024 grommunio GmbH
+// This file is part of Gromox.
 #include <climits>
 #include <cstdint>
 #include <cstdlib>
 #include <cstring>
 #include <memory>
 #include <utility>
+#include <vector>
 #include <gromox/defs.h>
 #include <gromox/mapidefs.h>
 #include <gromox/proptag_array.hpp>
@@ -16,6 +19,8 @@
 #include "message_object.hpp"
 #include "stream_object.hpp"
 
+using namespace gromox;
+
 static constexpr uint32_t indet_rendering_pos = UINT32_MAX;
 
 std::unique_ptr<attachment_object> attachment_object::create(message_object 
*pparent,
@@ -316,7 +321,7 @@
 }
 
 BOOL attachment_object::set_properties(const TPROPVAL_ARRAY *ppropvals,
-    PROBLEM_ARRAY *pproblems)
+    PROBLEM_ARRAY *pproblems) try
 {
        auto pattachment = this;
        PROBLEM_ARRAY tmp_problems;
@@ -330,9 +335,7 @@
        tmp_propvals.ppropval = cu_alloc<TAGGED_PROPVAL>(ppropvals->count);
        if (tmp_propvals.ppropval == nullptr)
                return FALSE;
-       auto poriginal_indices = cu_alloc<uint16_t>(ppropvals->count);
-       if (poriginal_indices == nullptr)
-               return FALSE;
+       std::vector<uint16_t> poriginal_indices;
        for (unsigned int i = 0; i < ppropvals->count; ++i) {
                const auto &pv = ppropvals->ppropval[i];
                if (is_readonly_prop(pv.proptag) ||
@@ -340,8 +343,8 @@
                        pproblems->emplace_back(i, pv.proptag, ecAccessDenied);
                        continue;
                }
-               tmp_propvals.ppropval[tmp_propvals.count] = pv;
-               poriginal_indices[tmp_propvals.count++] = i;
+               tmp_propvals.ppropval[tmp_propvals.count++] = pv;
+               poriginal_indices.push_back(i);
        }
        if (tmp_propvals.count == 0)
                return TRUE;
@@ -361,10 +364,13 @@
                }
        }
        return TRUE;
+} catch (const std::bad_alloc &) {
+       mlog(LV_ERR, "E-1669: ENOMEM");
+       return false;
 }
 
 BOOL attachment_object::remove_properties(const PROPTAG_ARRAY *pproptags,
-    PROBLEM_ARRAY *pproblems)
+    PROBLEM_ARRAY *pproblems) try
 {
        auto pattachment = this;
        PROBLEM_ARRAY tmp_problems;
@@ -378,9 +384,7 @@
        tmp_proptags.pproptag = cu_alloc<uint32_t>(pproptags->count);
        if (tmp_proptags.pproptag == nullptr)
                return FALSE;
-       auto poriginal_indices = cu_alloc<uint16_t>(pproptags->count);
-       if (poriginal_indices == nullptr)
-               return FALSE;
+       std::vector<uint16_t> poriginal_indices;
        for (unsigned int i = 0; i < pproptags->count; ++i) {
                const auto tag = pproptags->pproptag[i];
                if (is_readonly_prop(tag) ||
@@ -388,7 +392,7 @@
                        pproblems->emplace_back(i, tag, ecAccessDenied);
                        continue;
                }
-               poriginal_indices[tmp_proptags.count] = i;
+               poriginal_indices.push_back(i);
                tmp_proptags.emplace_back(tag);
        }
        if (tmp_proptags.count == 0)
@@ -409,6 +413,9 @@
                }
        }
        return TRUE;
+} catch (const std::bad_alloc &) {
+       mlog(LV_ERR, "E-1670: ENOMEM");
+       return false;
 }
 
 BOOL attachment_object::copy_properties(attachment_object *pattachment_src,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/exch/emsmdb/folder_object.cpp 
new/gromox-2.35/exch/emsmdb/folder_object.cpp
--- old/gromox-2.34/exch/emsmdb/folder_object.cpp       2024-10-08 
17:35:13.000000000 +0200
+++ new/gromox-2.35/exch/emsmdb/folder_object.cpp       2024-10-15 
13:20:17.000000000 +0200
@@ -1,4 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only WITH linking exception
+// SPDX-FileCopyrightText: 2021–2024 grommunio GmbH
+// This file is part of Gromox.
 #include <algorithm>
 #include <climits>
 #include <cstdint>
@@ -7,6 +9,7 @@
 #include <cstring>
 #include <memory>
 #include <utility>
+#include <vector>
 #include <gromox/defs.h>
 #include <gromox/ext_buffer.hpp>
 #include <gromox/mapidefs.h>
@@ -18,6 +21,8 @@
 #include "folder_object.hpp"
 #include "logon_object.hpp"
 
+using namespace gromox;
+
 std::unique_ptr<folder_object> folder_object::create(logon_object *plogon,
        uint64_t folder_id, uint8_t type, uint32_t tag_access)
 {
@@ -458,7 +463,7 @@
 }
 
 BOOL folder_object::set_properties(const TPROPVAL_ARRAY *ppropvals,
-    PROBLEM_ARRAY *pproblems)
+    PROBLEM_ARRAY *pproblems) try
 {
        uint16_t count;
        BINARY *pbin_pcl;
@@ -479,17 +484,15 @@
        tmp_propvals.ppropval = cu_alloc<TAGGED_PROPVAL>(count);
        if (tmp_propvals.ppropval == nullptr)
                return FALSE;
-       auto poriginal_indices = cu_alloc<uint16_t>(ppropvals->count);
-       if (poriginal_indices == nullptr)
-               return FALSE;
+       std::vector<uint16_t> poriginal_indices;
        auto pfolder = this;
        for (unsigned int i = 0; i < ppropvals->count; ++i) {
                const auto &pv = ppropvals->ppropval[i];
                if (pfolder->is_readonly_prop(pv.proptag)) {
                        pproblems->emplace_back(i, pv.proptag, ecAccessDenied);
                } else {
-                       tmp_propvals.ppropval[tmp_propvals.count] = pv;
-                       poriginal_indices[tmp_propvals.count++] = i;
+                       tmp_propvals.ppropval[tmp_propvals.count++] = pv;
+                       poriginal_indices.push_back(i);
                }
        }
        if (tmp_propvals.count == 0)
@@ -522,6 +525,9 @@
        tmp_problems.transform(poriginal_indices);
        *pproblems += std::move(tmp_problems);
        return TRUE;
+} catch (const std::bad_alloc &) {
+       mlog(LV_ERR, "E-1743: ENOMEM");
+       return false;
 }
 
 BOOL folder_object::remove_properties(const PROPTAG_ARRAY *pproptags,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/exch/emsmdb/logon_object.cpp 
new/gromox-2.35/exch/emsmdb/logon_object.cpp
--- old/gromox-2.34/exch/emsmdb/logon_object.cpp        2024-10-08 
17:35:13.000000000 +0200
+++ new/gromox-2.35/exch/emsmdb/logon_object.cpp        2024-10-15 
13:20:17.000000000 +0200
@@ -10,6 +10,7 @@
 #include <cstring>
 #include <memory>
 #include <utility>
+#include <vector>
 #include <libHX/string.h>
 #include <gromox/defs.h>
 #include <gromox/mapidefs.h>
@@ -664,7 +665,7 @@
 }
 
 BOOL logon_object::set_properties(const TPROPVAL_ARRAY *ppropvals,
-    PROBLEM_ARRAY *pproblems)
+    PROBLEM_ARRAY *pproblems) try
 {
        PROBLEM_ARRAY tmp_problems;
        TPROPVAL_ARRAY tmp_propvals;
@@ -680,17 +681,15 @@
        tmp_propvals.ppropval = cu_alloc<TAGGED_PROPVAL>(ppropvals->count);
        if (tmp_propvals.ppropval == nullptr)
                return FALSE;
-       auto poriginal_indices = cu_alloc<uint16_t>(ppropvals->count);
-       if (poriginal_indices == nullptr)
-               return FALSE;
+       std::vector<uint16_t> poriginal_indices;
        auto plogon = this;
        for (unsigned int i = 0; i < ppropvals->count; ++i) {
                const auto &pv = ppropvals->ppropval[i];
                if (lo_is_readonly_prop(plogon, pv.proptag)) {
                        pproblems->emplace_back(i, pv.proptag, ecAccessDenied);
                } else {
-                       tmp_propvals.ppropval[tmp_propvals.count] = pv;
-                       poriginal_indices[tmp_propvals.count++] = i;
+                       tmp_propvals.ppropval[tmp_propvals.count++] = pv;
+                       poriginal_indices.push_back(i);
                }
        }
        if (tmp_propvals.count == 0)
@@ -703,6 +702,9 @@
        tmp_problems.transform(poriginal_indices);
        *pproblems += std::move(tmp_problems);
        return TRUE;
+} catch (const std::bad_alloc &) {
+       mlog(LV_ERR, "E-1744: ENOMEM");
+       return false;
 }
 
 BOOL logon_object::remove_properties(const PROPTAG_ARRAY *pproptags,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/exch/emsmdb/message_object.cpp 
new/gromox-2.35/exch/emsmdb/message_object.cpp
--- old/gromox-2.34/exch/emsmdb/message_object.cpp      2024-10-08 
17:35:13.000000000 +0200
+++ new/gromox-2.35/exch/emsmdb/message_object.cpp      2024-10-15 
13:20:17.000000000 +0200
@@ -6,6 +6,7 @@
 #include <cstdlib>
 #include <cstring>
 #include <memory>
+#include <vector>
 #include <libHX/string.h>
 #include <gromox/defs.h>
 #include <gromox/ext_buffer.hpp>
@@ -1054,7 +1055,7 @@
 }
 
 static BOOL message_object_set_properties_internal(message_object *pmessage,
-       BOOL b_check, const TPROPVAL_ARRAY *ppropvals, PROBLEM_ARRAY *pproblems)
+    BOOL b_check, const TPROPVAL_ARRAY *ppropvals, PROBLEM_ARRAY *pproblems) 
try
 {
        uint8_t tmp_bytes[3];
        PROBLEM_ARRAY tmp_problems;
@@ -1072,10 +1073,8 @@
        tmp_propvals.ppropval = cu_alloc<TAGGED_PROPVAL>(ppropvals->count);
        if (tmp_propvals.ppropval == nullptr)
                return FALSE;
-       auto poriginal_indices = cu_alloc<uint16_t>(ppropvals->count);
-       if (poriginal_indices == nullptr)
-               return FALSE;
-       
+
+       std::vector<uint16_t> poriginal_indices;
        auto dir = pmessage->plogon->get_dir();
        for (unsigned int i = 0; i < ppropvals->count; ++i) {
                /* if property is being open as stream object, can not be 
modified */
@@ -1116,8 +1115,8 @@
                                        return FALSE;   
                        }
                }
-               tmp_propvals.ppropval[tmp_propvals.count] = pv;
-               poriginal_indices[tmp_propvals.count++] = i;
+               tmp_propvals.ppropval[tmp_propvals.count++] = pv;
+               poriginal_indices.push_back(i);
        }
        if (tmp_propvals.count == 0)
                return TRUE;
@@ -1142,6 +1141,9 @@
                        return FALSE;   
        }
        return TRUE;
+} catch (const std::bad_alloc &) {
+       mlog(LV_ERR, "E-1745: ENOMEM");
+       return false;
 }
 
 BOOL message_object::set_properties(const TPROPVAL_ARRAY *ppropvals,
@@ -1153,7 +1155,7 @@
 }
 
 BOOL message_object::remove_properties(const PROPTAG_ARRAY *pproptags,
-    PROBLEM_ARRAY *pproblems)
+    PROBLEM_ARRAY *pproblems) try
 {
        auto pmessage = this;
        PROBLEM_ARRAY tmp_problems;
@@ -1169,9 +1171,7 @@
        tmp_proptags.pproptag = cu_alloc<uint32_t>(pproptags->count);
        if (tmp_proptags.pproptag == nullptr)
                return FALSE;
-       auto poriginal_indices = cu_alloc<uint16_t>(pproptags->count);
-       if (poriginal_indices == nullptr)
-               return FALSE;
+       std::vector<uint16_t> poriginal_indices;
        /* if property is being open as stream object, can not be removed */
        for (unsigned int i = 0; i < pproptags->count; ++i) {
                const auto tag = pproptags->pproptag[i];
@@ -1190,7 +1190,7 @@
                                tag, static_cast<unsigned long 
long>(message_id), instance_id);
                        continue;
                default:
-                       poriginal_indices[tmp_proptags.count] = i;
+                       poriginal_indices.push_back(i);
                        tmp_proptags.emplace_back(tag);
                        break;
                }
@@ -1218,6 +1218,9 @@
                        return FALSE;   
        }
        return TRUE;
+} catch (const std::bad_alloc &) {
+       mlog(LV_ERR, "E-1746: ENOMEM");
+       return false;
 }
 
 BOOL message_object::copy_to(message_object *pmessage_src,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/exch/emsmdb/oxcprpt.cpp 
new/gromox-2.35/exch/emsmdb/oxcprpt.cpp
--- old/gromox-2.34/exch/emsmdb/oxcprpt.cpp     2024-10-08 17:35:13.000000000 
+0200
+++ new/gromox-2.35/exch/emsmdb/oxcprpt.cpp     2024-10-15 13:20:17.000000000 
+0200
@@ -5,6 +5,7 @@
 #include <cstdint>
 #include <cstring>
 #include <utility>
+#include <vector>
 #include <gromox/defs.h>
 #include <gromox/mapidefs.h>
 #include <gromox/proc_common.h>
@@ -565,7 +566,7 @@
 
 ec_error_t rop_copyproperties(uint8_t want_asynchronous, uint8_t copy_flags,
     const PROPTAG_ARRAY *pproptags, PROBLEM_ARRAY *pproblems, LOGMAP *plogmap,
-    uint8_t logon_id, uint32_t hsrc, uint32_t hdst)
+    uint8_t logon_id, uint32_t hsrc, uint32_t hdst) try
 {
        BOOL b_force;
        BOOL b_result;
@@ -600,9 +601,7 @@
        pproblems->pproblem = cu_alloc<PROPERTY_PROBLEM>(pproptags->count);
        if (pproblems->pproblem == nullptr)
                return ecServerOOM;
-       auto poriginal_indices = cu_alloc<uint16_t>(pproptags->count);
-       if (poriginal_indices == nullptr)
-               return ecError;
+       std::vector<uint16_t> poriginal_indices;
        switch (object_type) {
        case ems_objtype::folder: {
                auto fldsrc = static_cast<folder_object *>(pobject);
@@ -626,7 +625,7 @@
                        }
                        if (copy_flags & MAPI_NOREPLACE && proptags1.has(tag))
                                continue;
-                       poriginal_indices[proptags.count] = i;
+                       poriginal_indices.push_back(i);
                        proptags.emplace_back(tag);
                }
                if (!fldsrc->get_properties(&proptags, &propvals))
@@ -676,7 +675,7 @@
                        }
                        if (copy_flags & MAPI_NOREPLACE && proptags1.has(tag))
                                continue;
-                       poriginal_indices[proptags.count] = i;
+                       poriginal_indices.push_back(i);
                        proptags.emplace_back(tag);
                }
                if (!msgsrc->get_properties(0, &proptags, &propvals))
@@ -710,7 +709,7 @@
                        }
                        if (copy_flags & MAPI_NOREPLACE && proptags1.has(tag))
                                continue;
-                       poriginal_indices[proptags.count] = i;
+                       poriginal_indices.push_back(i);
                        proptags.emplace_back(tag);
                }
                if (!atsrc->get_properties(0, &proptags, &propvals))
@@ -730,6 +729,9 @@
        default:
                return ecNotSupported;
        }
+} catch (const std::bad_alloc &) {
+       mlog(LV_ERR, "E-1747: ENOMEM");
+       return ecServerOOM;
 }
 
 ec_error_t rop_copyto(uint8_t want_asynchronous, uint8_t want_subobjects,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/exch/ews/context.cpp 
new/gromox-2.35/exch/ews/context.cpp
--- old/gromox-2.34/exch/ews/context.cpp        2024-10-08 17:35:13.000000000 
+0200
+++ new/gromox-2.35/exch/ews/context.cpp        2024-10-15 13:20:17.000000000 
+0200
@@ -1032,8 +1032,9 @@
        auto& exmdb = m_plugin.exmdb;
        if(special & sShape::MimeContent)
        {
-               MESSAGE_CONTENT* content;
-               if(!exmdb.read_message(dir.c_str(), nullptr, CP_ACP, mid, 
&content))
+               MESSAGE_CONTENT *content = nullptr;
+               if (!exmdb.read_message(dir.c_str(), nullptr, CP_ACP, mid, 
&content) ||
+                   content == nullptr)
                        throw EWSError::ItemNotFound(E3071);
                MAIL mail;
                auto getPropIds = [&](const PROPNAME_ARRAY* names, 
PROPID_ARRAY* ids)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/exch/ews/requests.cpp 
new/gromox-2.35/exch/ews/requests.cpp
--- old/gromox-2.34/exch/ews/requests.cpp       2024-10-08 17:35:13.000000000 
+0200
+++ new/gromox-2.35/exch/ews/requests.cpp       2024-10-15 13:20:17.000000000 
+0200
@@ -1452,8 +1452,10 @@
                if(!(ctx.permissions(dir, folder.folderId) & frightsReadAny))
                        throw EWSError::AccessDenied(E3142);
 
-               MESSAGE_CONTENT* content;
-               if(!ctx.plugin().exmdb.read_message(dir.c_str(), 
ctx.effectiveUser(folder), CP_ACP, meid.messageId(), &content))
+               MESSAGE_CONTENT *content = nullptr;
+               if (!ctx.plugin().exmdb.read_message(dir.c_str(),
+                   ctx.effectiveUser(folder), CP_ACP, meid.messageId(),
+                   &content) || content == nullptr)
                        throw EWSError::ItemNotFound(E3143);
                ctx.send(dir, *content);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/exch/exmdb/common_util.cpp 
new/gromox-2.35/exch/exmdb/common_util.cpp
--- old/gromox-2.34/exch/exmdb/common_util.cpp  2024-10-08 17:35:13.000000000 
+0200
+++ new/gromox-2.35/exch/exmdb/common_util.cpp  2024-10-15 13:20:17.000000000 
+0200
@@ -3999,12 +3999,15 @@
                auto pstmt1 = gx_sql_prep(psqlite, sql_string);
                if (pstmt1 == nullptr)
                        return FALSE;
+               bool group_match = false;
                while (pstmt1.step() == SQLITE_ROW) {
                        if (common_util_check_mlist_include(pstmt1.col_text(0), 
username)) {
-                               *ppermission = sqlite3_column_int64(pstmt1, 1);
-                               return TRUE;
+                               *ppermission |= pstmt1.col_int64(1);
+                               group_match = true;
                        }
                }
+               if (group_match)
+                       return TRUE;
                pstmt1.finalize();
                sqlite3_reset(pstmt);
                sqlite3_bind_text(pstmt, 1, "default", -1, SQLITE_STATIC);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/exch/zcore/message_object.cpp 
new/gromox-2.35/exch/zcore/message_object.cpp
--- old/gromox-2.34/exch/zcore/message_object.cpp       2024-10-08 
17:35:13.000000000 +0200
+++ new/gromox-2.35/exch/zcore/message_object.cpp       2024-10-15 
13:20:17.000000000 +0200
@@ -7,6 +7,7 @@
 #include <cstring>
 #include <memory>
 #include <utility>
+#include <vector>
 #include <libHX/string.h>
 #include <gromox/defs.h>
 #include <gromox/ext_buffer.hpp>
@@ -811,13 +812,12 @@
 }
 
 static BOOL message_object_set_properties_internal(message_object *pmessage,
-    BOOL b_check, const TPROPVAL_ARRAY *ppropvals)
+    BOOL b_check, const TPROPVAL_ARRAY *ppropvals) try
 {
        uint8_t tmp_bytes[3];
        PROBLEM_ARRAY problems;
        PROBLEM_ARRAY tmp_problems;
        TPROPVAL_ARRAY tmp_propvals;
-       uint16_t *poriginal_indices;
        TPROPVAL_ARRAY tmp_propvals1;
        TAGGED_PROPVAL propval_buff[3];
        
@@ -831,9 +831,7 @@
        tmp_propvals.ppropval = cu_alloc<TAGGED_PROPVAL>(ppropvals->count);
        if (tmp_propvals.ppropval == nullptr)
                return FALSE;
-       poriginal_indices = cu_alloc<uint16_t>(ppropvals->count);
-       if (poriginal_indices == nullptr)
-               return FALSE;
+       std::vector<uint16_t> poriginal_indices;
        for (unsigned int i = 0; i < ppropvals->count; ++i) {
                const auto &pv = ppropvals->ppropval[i];
                if (b_check) {
@@ -870,8 +868,8 @@
                                        return FALSE;   
                        }
                }
-               tmp_propvals.ppropval[tmp_propvals.count] = pv;
-               poriginal_indices[tmp_propvals.count++] = i;
+               tmp_propvals.ppropval[tmp_propvals.count++] = pv;
+               poriginal_indices.push_back(i);
        }
        if (tmp_propvals.count == 0)
                return TRUE;
@@ -895,6 +893,9 @@
                        return FALSE;   
        }
        return TRUE;
+} catch (const std::bad_alloc &) {
+       mlog(LV_ERR, "E-1748: ENOMEM");
+       return false;
 }
 
 BOOL message_object::set_properties(TPROPVAL_ARRAY *ppropvals)
@@ -904,13 +905,12 @@
                                                pmessage, TRUE, ppropvals);
 }
 
-BOOL message_object::remove_properties(const PROPTAG_ARRAY *pproptags)
+BOOL message_object::remove_properties(const PROPTAG_ARRAY *pproptags) try
 {
        auto pmessage = this;
        PROBLEM_ARRAY problems;
        PROBLEM_ARRAY tmp_problems;
        PROPTAG_ARRAY tmp_proptags;
-       uint16_t *poriginal_indices;
        
        if (!pmessage->b_writable)
                return FALSE;
@@ -922,9 +922,7 @@
        tmp_proptags.pproptag = cu_alloc<uint32_t>(pproptags->count);
        if (tmp_proptags.pproptag == nullptr)
                return FALSE;
-       poriginal_indices = cu_alloc<uint16_t>(pproptags->count);
-       if (poriginal_indices == nullptr)
-               return FALSE;
+       std::vector<uint16_t> poriginal_indices;
        for (unsigned int i = 0; i < pproptags->count; ++i) {
                const auto tag = pproptags->pproptag[i];
                if (msgo_is_readonly_prop(pmessage, tag)) {
@@ -932,7 +930,7 @@
                        continue;
                }
                tmp_proptags.pproptag[tmp_proptags.count] = tag;
-               poriginal_indices[tmp_proptags.count++] = i;
+               poriginal_indices.push_back(i);
        }
        if (tmp_proptags.count == 0)
                return TRUE;
@@ -956,6 +954,9 @@
                        return FALSE;   
        }
        return TRUE;
+} catch (const std::bad_alloc &) {
+       mlog(LV_ERR, "E-1749: ENOMEM");
+       return false;
 }
 
 BOOL message_object::copy_to(message_object *pmessage_src,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/include/gromox/exmdb_idef.hpp 
new/gromox-2.35/include/gromox/exmdb_idef.hpp
--- old/gromox-2.34/include/gromox/exmdb_idef.hpp       2024-10-08 
17:35:13.000000000 +0200
+++ new/gromox-2.35/include/gromox/exmdb_idef.hpp       2024-10-15 
13:20:17.000000000 +0200
@@ -132,7 +132,7 @@
 EXMIDL(unload_store, (const char *dir))
 EXMIDL(notify_new_mail, (const char *dir, uint64_t folder_id, uint64_t 
message_id))
 EXMIDL(store_eid_to_user, (const char *dir, const STORE_ENTRYID *store_eid, 
IDLOUT char **maildir, unsigned int *user_id, unsigned int *domain_id))
-EXMIDL(purge_softdelete, (const char *dir, const char *username, uint64_t 
folder_id, uint32_t del_flags, mapitime_t cutoff))
+EXMIDL(purge_softdelete, (const char *dir, const char *username, uint64_t 
folder_id, uint32_t del_flags, gromox::mapitime_t cutoff))
 EXMIDL(purge_datafiles, (const char *dir))
 EXMIDL(autoreply_tsquery, (const char *dir, const char *peer, uint64_t window, 
IDLOUT uint64_t *tdiff))
 EXMIDL(autoreply_tsupdate, (const char *dir, const char *peer))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/include/gromox/exmdb_rpc.hpp 
new/gromox-2.35/include/gromox/exmdb_rpc.hpp
--- old/gromox-2.34/include/gromox/exmdb_rpc.hpp        2024-10-08 
17:35:13.000000000 +0200
+++ new/gromox-2.35/include/gromox/exmdb_rpc.hpp        2024-10-15 
13:20:17.000000000 +0200
@@ -836,7 +836,7 @@
        char *username;
        uint64_t folder_id = 0;
        uint32_t del_flags = 0;
-       mapitime_t cutoff = 0;
+       gromox::mapitime_t cutoff = 0;
 };
 
 struct exreq_autoreply_tsquery final : public exreq {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/include/gromox/mapi_types.hpp 
new/gromox-2.35/include/gromox/mapi_types.hpp
--- old/gromox-2.34/include/gromox/mapi_types.hpp       2024-10-08 
17:35:13.000000000 +0200
+++ new/gromox-2.35/include/gromox/mapi_types.hpp       2024-10-15 
13:20:17.000000000 +0200
@@ -246,7 +246,7 @@
        inline void emplace_back(unsigned int i, uint32_t tag, uint32_t err) {
                pproblem[count++] = PROPERTY_PROBLEM{static_cast<uint16_t>(i), 
tag, err};
        }
-       void transform(const uint16_t *);
+       void transform(const std::vector<uint16_t> &);
        size_t indexof(uint32_t tag) const;
        inline bool has(uint32_t tag) const { return indexof(tag) != npos; }
        static constexpr size_t npos = -1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/include/gromox/mapidefs.h 
new/gromox-2.35/include/gromox/mapidefs.h
--- old/gromox-2.34/include/gromox/mapidefs.h   2024-10-08 17:35:13.000000000 
+0200
+++ new/gromox-2.35/include/gromox/mapidefs.h   2024-10-15 13:20:17.000000000 
+0200
@@ -10,9 +10,19 @@
 #include <type_traits>
 #include <gromox/defs.h>
 
-#define PROP_ID(x) static_cast<uint16_t>((x) >> 16)
-#define PROP_TYPE(x) static_cast<uint16_t>((x) & 0xFFFF)
-#define CHANGE_PROP_TYPE(tag, newtype) static_cast<uint32_t>(((tag) & ~0xFFFF) 
| (newtype))
+namespace gromox {
+
+using propid_t = uint16_t;
+using proptype_t = uint16_t;
+using proptag_t = uint32_t;
+/* N.B.: PidLids are not propids (they are also 32-bit wide) */
+using mapitime_t = uint64_t;
+
+}
+
+#define PROP_ID(x) static_cast<gromox::propid_t>((x) >> 16)
+#define PROP_TYPE(x) static_cast<gromox::proptype_t>((x) & 0xFFFF)
+#define CHANGE_PROP_TYPE(tag, newtype) static_cast<gromox::proptag_t>(((tag) & 
~0xFFFF) | (newtype))
 
 /*
  * x|y yields an unsigned result if either x or y are unsigned.
@@ -20,7 +30,7 @@
  * All the while | and << only make *sense* in an unsigned _context_ anyway
  * (i.e. the operator should have returned unsigned all the time)
  */
-#define PROP_TAG(type, tag) static_cast<uint32_t>((static_cast<uint32_t>(tag) 
<< 16) | (type))
+#define PROP_TAG(type, tag) 
static_cast<gromox::proptag_t>((static_cast<uint32_t>(tag) << 16) | (type))
 namespace {
 enum {
        /*
@@ -76,11 +86,8 @@
        PT_MV_CLSID = 0x1048, /* PtypMultipleGuid */
        PT_MV_BINARY = 0x1102, /* PtypMultipleBinary */
 };
-using proptype_t = decltype(PT_NULL);
 }
 
-using mapitime_t = uint64_t;
-
 #include "mapitags.hpp"
 
 enum {
@@ -839,9 +846,14 @@
 
 /* cf. glossary.rst "Internal Identifier" */
 struct eid_t {
+       static constexpr uint64_t GCV_MASK = 0xFFFFFFFFFFFF;
        eid_t() = default;
        constexpr eid_t(uint64_t v) : m_value(v) {}
+       constexpr eid_t(uint16_t r, uint64_t v) : m_value(__builtin_bswap64(v & 
GCV_MASK) | r) {}
        constexpr operator uint64_t() const { return m_value; }
+       constexpr uint64_t gcv() const { return __builtin_bswap64(m_value) & 
GCV_MASK; }
+       constexpr uint16_t replid() const { return m_value & 0xFFFF; }
+       constexpr uint64_t raw() const { return m_value; }
        void operator=(uint64_t) = delete;
        uint64_t m_value;
 };
@@ -1053,7 +1065,7 @@
        std::string name;
 };
 
-using PROPID_ARRAY = std::vector<uint16_t>;
+using PROPID_ARRAY = std::vector<gromox::propid_t>;
 
 struct PROPNAME_ARRAY {
        uint16_t count;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/include/gromox/mapitags.hpp 
new/gromox-2.35/include/gromox/mapitags.hpp
--- old/gromox-2.34/include/gromox/mapitags.hpp 2024-10-08 17:35:13.000000000 
+0200
+++ new/gromox-2.35/include/gromox/mapitags.hpp 2024-10-15 13:20:17.000000000 
+0200
@@ -1113,7 +1113,6 @@
        PR_EMS_AB_PARENT_ENTRYID = PROP_TAG(PT_BINARY, 0xFFFC), /* 
PidTagAddressBookParentEntryId */
        PR_EMS_AB_CONTAINERID = PROP_TAG(PT_LONG, 0xFFFD), /* 
PidTagAddressBookContainerId */
 };
-using proptag_t = decltype(PR_NULL);
 }
 
 enum {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/lib/mapi/element_data.cpp 
new/gromox-2.35/lib/mapi/element_data.cpp
--- old/gromox-2.34/lib/mapi/element_data.cpp   2024-10-08 17:35:13.000000000 
+0200
+++ new/gromox-2.35/lib/mapi/element_data.cpp   2024-10-15 13:20:17.000000000 
+0200
@@ -1,9 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0-only WITH linking exception
+// SPDX-FileCopyrightText: 2021–2024 grommunio GmbH
+// This file is part of Gromox.
 #include <algorithm>
 #include <cstdlib>
 #include <cstring>
 #include <memory>
 #include <utility>
+#include <vector>
 #include <gromox/eid_array.hpp>
 #include <gromox/element_data.hpp>
 #include <gromox/mapi_types.hpp>
@@ -401,8 +404,15 @@
        return *this;
 }
 
-void PROBLEM_ARRAY::transform(const uint16_t *orig_indices)
+void PROBLEM_ARRAY::transform(const std::vector<uint16_t> &orig_indices)
 {
-       for (size_t i = 0; i < count; ++i)
+       /*
+        * Cut off problems related to internally tacked-on properties (cf.
+        * emsmdb/folder_object::set_folder_properties).
+        */
+       auto end = std::remove_if(&pproblem[0], &pproblem[count],
+                  [=](const PROPERTY_PROBLEM &p) { return p.index >= 
orig_indices.size(); });
+       count = end - &pproblem[0];
+       for (unsigned int i = 0; i < count; ++i)
                pproblem[i].index = orig_indices[pproblem[i].index];
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/lib/mapi/rop_util.cpp 
new/gromox-2.35/lib/mapi/rop_util.cpp
--- old/gromox-2.34/lib/mapi/rop_util.cpp       2024-10-08 17:35:13.000000000 
+0200
+++ new/gromox-2.35/lib/mapi/rop_util.cpp       2024-10-15 13:20:17.000000000 
+0200
@@ -34,7 +34,7 @@
  */
 uint64_t rop_util_get_gc_value(eid_t eid)
 {
-       return __builtin_bswap64(eid.m_value) & 0xFFFFFFFF;
+       return __builtin_bswap64(eid.m_value) & eid_t::GCV_MASK;
 }
 
 /**
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/lib/ruleproc.cpp 
new/gromox-2.35/lib/ruleproc.cpp
--- old/gromox-2.34/lib/ruleproc.cpp    2024-10-08 17:35:13.000000000 +0200
+++ new/gromox-2.35/lib/ruleproc.cpp    2024-10-15 13:20:17.000000000 +0200
@@ -1222,6 +1222,8 @@
        if (!exmdb_client::read_message(cur.dirc(), nullptr, CP_ACP,
            cur.mid, &unique_tie(ctnt)))
                return ecError;
+       if (ctnt == nullptr)
+               return ecNotFound;
        for (auto &&rule : rule_list) {
                err = rule.extended ? opx_process(*this, rule) : 
op_process(*this, rule);
                if (err != ecSuccess)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/mda/alias_resolve.cpp 
new/gromox-2.35/mda/alias_resolve.cpp
--- old/gromox-2.34/mda/alias_resolve.cpp       2024-10-08 17:35:13.000000000 
+0200
+++ new/gromox-2.35/mda/alias_resolve.cpp       2024-10-15 13:20:17.000000000 
+0200
@@ -50,6 +50,8 @@
 
 static std::atomic<bool> xa_notify_stop{false};
 static std::condition_variable xa_thread_wake;
+static alias_map xa_empty_alias_map;
+static domain_set xa_empty_domain_set;
 static std::shared_ptr<alias_map> xa_alias_map;
 static std::shared_ptr<domain_set> xa_domain_set;
 static std::mutex xa_alias_lock;
@@ -149,22 +151,27 @@
        return nullptr;
 }
 
+static void xa_refresh_once()
+{
+       auto conn = sql_make_conn();
+       auto newmap = xa_refresh_aliases(conn);
+       auto newdom = xa_refresh_domains(conn);
+       std::unique_lock lk(xa_alias_lock);
+       if (newmap != nullptr)
+               xa_alias_map = std::move(newmap);
+       if (newdom != nullptr)
+               xa_domain_set = std::move(newdom);
+}
+
 static void xa_refresh_thread()
 {
        std::mutex slp_mtx;
        while (!xa_notify_stop) {
                {
-                       auto conn = sql_make_conn();
-                       auto newmap = xa_refresh_aliases(conn);
-                       auto newdom = xa_refresh_domains(conn);
-                       std::unique_lock lk(xa_alias_lock);
-                       if (newmap != nullptr) {
-                               xa_alias_map = std::move(newmap);
-                               xa_domain_set = std::move(newdom);
-                       }
+                       std::unique_lock slp_hold(slp_mtx);
+                       xa_thread_wake.wait_for(slp_hold, g_cache_lifetime);
                }
-               std::unique_lock slp_hold(slp_mtx);
-               xa_thread_wake.wait_for(slp_hold, g_cache_lifetime);
+               xa_refresh_once();
        }
 }
 
@@ -177,8 +184,8 @@
                alias_map_ptr = xa_alias_map;
                domset_ptr = xa_domain_set;
        }
-       auto &alias_map = *alias_map_ptr;
-       auto &domset = *domset_ptr;
+       auto &alias_map = alias_map_ptr != nullptr ? *alias_map_ptr : 
xa_empty_alias_map;
+       auto &domset = domset_ptr != nullptr ? *domset_ptr : 
xa_empty_domain_set;
 
        auto ctrl = &ctx->ctrl;
        if (strchr(ctrl->from, '@') != nullptr) {
@@ -363,8 +370,10 @@
                       strerror(errno));
                return false;
        }
-       if (!xa_reload_config(std::move(mcfg), std::move(acfg)) ||
-           !register_hook(xa_alias_subst))
+       if (!xa_reload_config(std::move(mcfg), std::move(acfg)))
+               return false;
+       xa_refresh_once();
+       if (!register_hook(xa_alias_subst))
                return false;
        try {
                xa_thread = std::thread(xa_refresh_thread);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/tests/exrpctest.cpp 
new/gromox-2.35/tests/exrpctest.cpp
--- old/gromox-2.34/tests/exrpctest.cpp 2024-10-08 17:35:13.000000000 +0200
+++ new/gromox-2.35/tests/exrpctest.cpp 2024-10-15 13:20:17.000000000 +0200
@@ -3,6 +3,7 @@
 // This file is part of Gromox.
 #include <cstdint>
 #include <cstdlib>
+#include <vector>
 #include <gromox/exmdb_client.hpp>
 #include <gromox/exmdb_rpc.hpp>
 #include <gromox/paths.h>
@@ -15,6 +16,42 @@
 
 static alloc_context g_alloc_mgr;
 
+static int t_2209(const char *dir)
+{
+       static constexpr uint64_t v_zero = 0;
+       static constexpr BINARY v_binzero = {0, {.pc = deconst("")}};
+       const TAGGED_PROPVAL pvd[] = {
+               {PR_COMMENT, deconst("acomment")},
+       };
+       TAGGED_PROPVAL qvd[std::size(pvd)+4]{};
+       const TPROPVAL_ARRAY pvals = {std::size(pvd), deconst(pvd)};
+       TPROPVAL_ARRAY qvals = {0, deconst(qvd)};
+       std::vector<uint16_t> original_indices;
+       PROBLEM_ARRAY problems{};
+
+       for (size_t i = 0; i < pvals.count; ++i) {
+               const auto &pv = pvals.ppropval[i];
+               if (pv.proptag == PR_ACCESS) {
+                       problems.emplace_back(i, pv.proptag, ecAccessDenied);
+               } else {
+                       qvals.ppropval[qvals.count++] = pv;
+                       original_indices.push_back(i);
+               }
+       }
+       qvals.emplace_back(PidTagChangeNumber, &v_zero);
+       qvals.emplace_back(PR_CHANGE_KEY, &v_binzero);
+       qvals.emplace_back(PR_PREDECESSOR_CHANGE_LIST, &v_binzero);
+       qvals.emplace_back(PROP_TAG(PT_I8, 0), &v_zero);
+
+       if (!exmdb_client::set_folder_properties(dir, CP_UTF8,
+           rop_util_make_eid_ex(1, PRIVATE_FID_ROOT), &qvals, &problems)) {
+               mlog(LV_ERR, "set_folder_properties failed unexpectedly");
+               return EXIT_FAILURE;
+       }
+       problems.transform(original_indices);
+       return EXIT_SUCCESS;
+}
+
 int main(int argc, char **argv)
 {
        exmdb_rpc_alloc = [](size_t z) { return g_alloc_mgr.alloc(z); };
@@ -43,5 +80,6 @@
        TPROPVAL_ARRAY props{};
        if (!exmdb_client::get_store_properties(g_storedir, CP_UTF8, &ptags, 
&props))
                mlog(LV_ERR, "get_store_properties failed unexpectedly");
-       return 0;
+
+       return t_2209(g_storedir);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gromox-2.34/tools/exm2eml.cpp 
new/gromox-2.35/tools/exm2eml.cpp
--- old/gromox-2.34/tools/exm2eml.cpp   2024-10-08 17:35:13.000000000 +0200
+++ new/gromox-2.35/tools/exm2eml.cpp   2024-10-15 13:20:17.000000000 +0200
@@ -178,6 +178,8 @@
                msg_id = strtoull(sep + 1, nullptr, 0);
                uint32_t inst_id = 0;
                ctnt = message_content_init();
+               if (ctnt == nullptr)
+                       throw std::bad_alloc();
                if (!exmdb_client_remote::load_message_instance(g_storedir,
                    nullptr, CP_UTF8, false, rop_util_make_eid_ex(1, folder_id),
                    rop_util_make_eid_ex(1, msg_id), &inst_id)) {
@@ -199,7 +201,7 @@
                }
                if (ctnt == nullptr) {
                        fprintf(stderr, "A message by the id %llxh was not 
found\n",
-                               static_cast<unsigned long long>(msg_id));
+                               static_cast<unsigned long long>(msg_id));
                        return EXIT_FAILURE;
                }
        }

Reply via email to