From eca150ab086c33ccdc116be665dc163181073cb4 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Mon, 29 May 2023 09:39:02 +0300 Subject: [PATCH] Fix windows unicode ldap search (#1194) IB-7738, IB-7743 Signed-off-by: Raul Metsma --- .github/workflows/build.yml | 8 +++--- client/LdapSearch.cpp | 43 ++++++++++++++++++++++---------- client/dialogs/AddRecipients.cpp | 15 ++++++++--- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 57c34ef7b..0fb6f4277 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,7 +55,7 @@ jobs: container: ${{ matrix.container }} strategy: matrix: - container: ['ubuntu:20.04', 'ubuntu:22.04', 'ubuntu:22.10'] + container: ['ubuntu:20.04', 'ubuntu:22.04', 'ubuntu:23.04'] env: DEBIAN_FRONTEND: noninteractive DEBFULLNAME: github-actions @@ -63,10 +63,10 @@ jobs: steps: - name: Install dependencies if: matrix.container == 'ubuntu:20.04' - run: apt update -qq && apt install --no-install-recommends -y git lsb-release fakeroot build-essential devscripts cdbs pkg-config cmake libldap2-dev gettext libpcsclite-dev libssl-dev libqt5svg5-dev qttools5-dev-tools qttools5-dev lintian + run: apt update -qq && apt install --no-install-recommends -y git lsb-release fakeroot build-essential devscripts debhelper cdbs pkg-config cmake libldap2-dev gettext libpcsclite-dev libssl-dev libqt5svg5-dev qttools5-dev-tools qttools5-dev lintian - name: Install dependencies if: matrix.container != 'ubuntu:20.04' - run: apt update -qq && apt install --no-install-recommends -y git lsb-release fakeroot build-essential devscripts cdbs pkg-config cmake libldap2-dev gettext libpcsclite-dev libssl-dev libgl-dev libqt6svg6-dev qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools libqt6core5compat6-dev lintian + run: apt update -qq && apt install --no-install-recommends -y git lsb-release fakeroot build-essential devscripts debhelper cdbs pkg-config cmake libldap2-dev gettext libpcsclite-dev libssl-dev libgl-dev libqt6svg6-dev qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools libqt6core5compat6-dev lintian - name: Checkout uses: actions/checkout@v3 with: @@ -105,7 +105,7 @@ jobs: container: ${{ matrix.container }} strategy: matrix: - container: ['fedora:36', 'fedora:37'] + container: ['fedora:37', 'fedora:38'] env: MAKEFLAGS: -j3 steps: diff --git a/client/LdapSearch.cpp b/client/LdapSearch.cpp index 9f2c182f4..c5ab73151 100644 --- a/client/LdapSearch.cpp +++ b/client/LdapSearch.cpp @@ -25,26 +25,43 @@ #include #ifdef Q_OS_WIN -#undef UNICODE #include #include #include +using STR_T = PWSTR; +#define STR(X) const_cast(L##X) +#define TO_STR(X) STR_T((X).utf16()) #else #define LDAP_DEPRECATED 1 #include #include using ULONG = int; using LDAP_TIMEVAL = timeval; +using STR_T = char *; +#define STR(X) const_cast(X) +#define TO_STR(X) STR_T((X).toLocal8Bit().constData()) #endif #include +#include + +using namespace std::chrono; + +template +static constexpr auto TO_QSTR(const T *str) +{ + if constexpr (std::is_same::value) + return QLatin1String(str); + else + return QStringView(str); +} class LdapSearch::Private { public: LDAP *ldap {}; QByteArray host; - QTimer *timer; + QTimer *timer {}; }; LdapSearch::LdapSearch(QByteArray host, QObject *parent) @@ -72,7 +89,7 @@ bool LdapSearch::init() { if(d->ldap) { - d->timer->start(4*60*60); + d->timer->start(4min); return true; } @@ -81,7 +98,7 @@ bool LdapSearch::init() int ssl = url.scheme() == QStringLiteral("ldaps") ? 1 : 0; QString host = url.host(); ULONG port = ULONG(url.port(ssl ? LDAP_SSL_PORT : LDAP_PORT)); - if(!(d->ldap = ldap_sslinit(const_cast(host.toLocal8Bit().constData()), port, ssl))) + if(d->ldap = ldap_sslinit(TO_STR(host), port, ssl); !d->ldap) { setLastError(tr("Failed to init ldap"), int(LdapGetLastError())); return false; @@ -127,7 +144,7 @@ bool LdapSearch::init() if(err) setLastError(tr("Failed to init ldap"), err); - d->timer->start(4*60*60); + d->timer->start(4min); return !err; } @@ -146,15 +163,15 @@ void LdapSearch::search(const QString &search, const QVariantMap &userData) return; } - std::array attrs { const_cast("userCertificate;binary"), nullptr }; + std::array attrs { STR("userCertificate;binary"), nullptr }; ULONG msg_id = 0; - int err = ldap_search_ext( d->ldap, const_cast("c=EE"), LDAP_SCOPE_SUBTREE, - const_cast(search.toUtf8().constData()), attrs.data(), 0, nullptr, nullptr, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &msg_id); + int err = ldap_search_ext(d->ldap, STR("c=EE"), LDAP_SCOPE_SUBTREE, + TO_STR(search), attrs.data(), 0, nullptr, nullptr, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &msg_id); if(err) return setLastError( tr("Failed to init ldap search"), err ); - QTimer *timer = new QTimer(this); + auto *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [this, msg_id, timer, userData] { LDAPMessage *result = nullptr; LDAP_TIMEVAL t { 5, 0 }; @@ -179,14 +196,14 @@ void LdapSearch::search(const QString &search, const QVariantMap &userData) for(; entry; entry = ldap_next_entry(d->ldap, entry)) { BerElement *pos = nullptr; - for(char *attr = ldap_first_attribute(d->ldap, entry, &pos); + for(auto *attr = ldap_first_attribute(d->ldap, entry, &pos); attr; attr = ldap_next_attribute(d->ldap, entry, pos)) { - if( qstrcmp( attr, "userCertificate;binary" ) == 0 ) + if(QLatin1String("userCertificate;binary") == TO_QSTR(attr)) { berval **cert = ldap_get_values_len(d->ldap, entry, attr); for(ULONG i = 0; i < ldap_count_values_len(cert); ++i) - list << QSslCertificate(QByteArray::fromRawData(cert[i]->bv_val, int(cert[i]->bv_len)), QSsl::Der); + list.append(QSslCertificate(QByteArray::fromRawData(cert[i]->bv_val, int(cert[i]->bv_len)), QSsl::Der)); ldap_value_free_len(cert); } ldap_memfree(attr); @@ -197,7 +214,7 @@ void LdapSearch::search(const QString &search, const QVariantMap &userData) Q_EMIT searchResult(list, count, userData); }); - timer->start(1000); + timer->start(1s); } void LdapSearch::setLastError( const QString &msg, int err ) diff --git a/client/dialogs/AddRecipients.cpp b/client/dialogs/AddRecipients.cpp index 3e6da00fd..a053301e4 100644 --- a/client/dialogs/AddRecipients.cpp +++ b/client/dialogs/AddRecipients.cpp @@ -384,10 +384,17 @@ void AddRecipients::search(const QString &term, bool select, const QString &type {QStringLiteral("select"), select} }; QString cleanTerm = term.simplified() - .replace(QStringLiteral("*"), QStringLiteral("\2A")) - .replace(QStringLiteral("("), QStringLiteral("\28")) - .replace(QStringLiteral(")"), QStringLiteral("\29")) - .replace(QStringLiteral("\\"), QStringLiteral("\5c")); +#ifdef Q_OS_WIN + .replace(QStringLiteral("\\"), QStringLiteral("\\5c")) + .replace(QStringLiteral("*"), QStringLiteral("\\2A")) + .replace(QStringLiteral("("), QStringLiteral("\\28")) + .replace(QStringLiteral(")"), QStringLiteral("\\29")); +#else + .replace(QStringLiteral("\\"), QStringLiteral("\\\\")) + .replace(QStringLiteral("*"), QStringLiteral("\\*")) + .replace(QStringLiteral("("), QStringLiteral("\\(")) + .replace(QStringLiteral(")"), QStringLiteral("\\)")); +#endif bool isDigit = false; void(cleanTerm.toULongLong(&isDigit)); if(isDigit && (cleanTerm.size() == 11 || cleanTerm.size() == 8))