[pim/libksieve] /: Remove kioslave

Nicolas Fella null at kde.org
Sun Aug 7 18:32:20 BST 2022


Git commit 208b28a9dfe5e30eec47773c86d3963434211754 by Nicolas Fella.
Committed on 06/08/2022 at 14:41.
Pushed by mlaurent into branch 'master'.

Remove kioslave

It isn't used by anything, and there aren't really many use cases for it

Furthermore it has been broken for over a year due to incorrect metadata and nobody complained

M  +0    -1    CMakeLists.txt
D  +0    -5    kioslave/CMakeLists.txt
D  +0    -3    kioslave/doc/CMakeLists.txt
D  +0    -5    kioslave/doc/sieve/CMakeLists.txt
D  +0    -30   kioslave/doc/sieve/index.docbook
D  +0    -6    kioslave/src/CMakeLists.txt
D  +0    -6    kioslave/src/autotests/CMakeLists.txt
D  +0    -68   kioslave/src/autotests/regexptest.cpp
D  +0    -20   kioslave/src/autotests/regexptest.h
D  +0    -37   kioslave/src/common.h
D  +0    -24   kioslave/src/sieve/CMakeLists.txt
D  +0    -4    kioslave/src/sieve/Messages.sh
D  +0    -2    kioslave/src/sieve/RFCs
D  +0    -1314 kioslave/src/sieve/sieve.cpp
D  +0    -119  kioslave/src/sieve/sieve.h
D  +0    -22   kioslave/src/sieve/sieve.json

https://invent.kde.org/pim/libksieve/commit/208b28a9dfe5e30eec47773c86d3963434211754

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 696ab572..03288d29 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -122,7 +122,6 @@ if(BUILD_TESTING)
 endif()
 
 add_subdirectory(src)
-add_subdirectory(kioslave)
 ecm_qt_install_logging_categories(
         EXPORT LIBKSIEVE
         FILE libksieve.categories
diff --git a/kioslave/CMakeLists.txt b/kioslave/CMakeLists.txt
deleted file mode 100644
index 03158f28..00000000
--- a/kioslave/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-FileCopyrightText: 2011-2022 Laurent Montel <montel at kde.org>
-# SPDX-License-Identifier: BSD-3-Clause
-add_subdirectory(src)
-add_subdirectory(doc)
-
diff --git a/kioslave/doc/CMakeLists.txt b/kioslave/doc/CMakeLists.txt
deleted file mode 100644
index 4328488c..00000000
--- a/kioslave/doc/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-FileCopyrightText: 2011-2022 Laurent Montel <montel at kde.org>
-# SPDX-License-Identifier: BSD-3-Clause
-add_subdirectory(sieve)
diff --git a/kioslave/doc/sieve/CMakeLists.txt b/kioslave/doc/sieve/CMakeLists.txt
deleted file mode 100644
index 12e7a0dc..00000000
--- a/kioslave/doc/sieve/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-FileCopyrightText: 2011-2022 Laurent Montel <montel at kde.org>
-# SPDX-License-Identifier: BSD-3-Clause
-########### install files ###############
-kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kioslave5/sieve)
-
diff --git a/kioslave/doc/sieve/index.docbook b/kioslave/doc/sieve/index.docbook
deleted file mode 100644
index 976e4a87..00000000
--- a/kioslave/doc/sieve/index.docbook
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE article PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN"
-"dtd/kdedbx45.dtd" [
-<!ENTITY % addindex "IGNORE">
-<!ENTITY % English "INCLUDE" > <!-- change language only here -->
-]>
-	
-<article lang="&language;" id="sieve">
-<title>sieve</title>
-<articleinfo>
-
-<authorgroup>
-<author><personname><firstname>Daniel</firstname><surname>Black</surname></personname>
-<email>daniel.subs at internode.on.net</email></author>
-<!-- TRANS:ROLES_OF_TRANSLATORS -->
-</authorgroup>
- 
-<date>2009-11-05</date>
-
- 
-</articleinfo>
-
-<para>Sieve is a protocol that is used to manage filters for email.</para> 
-
-<para>The filters are stored and run on the email server.</para>
-
-<para><ulink url="https://www.ietf.org/rfc/rfc5228.txt">IETF
-RF5228</ulink> provides more information.</para>
-
-</article>
diff --git a/kioslave/src/CMakeLists.txt b/kioslave/src/CMakeLists.txt
deleted file mode 100644
index 0060cce4..00000000
--- a/kioslave/src/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-FileCopyrightText: 2011-2022 Laurent Montel <montel at kde.org>
-# SPDX-License-Identifier: BSD-3-Clause
-add_subdirectory(sieve)
-if(BUILD_TESTING)
-    add_subdirectory(autotests)
-endif()
diff --git a/kioslave/src/autotests/CMakeLists.txt b/kioslave/src/autotests/CMakeLists.txt
deleted file mode 100644
index d803881c..00000000
--- a/kioslave/src/autotests/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-FileCopyrightText: 2011-2022 Laurent Montel <montel at kde.org>
-# SPDX-License-Identifier: BSD-3-Clause
-if (QT_MAJOR_VERSION STREQUAL "5")
-    ecm_add_tests( regexptest.cpp  NAME_PREFIX "libksieve-" LINK_LIBRARIES Qt${QT_MAJOR_VERSION}::Test)
-endif()
-
diff --git a/kioslave/src/autotests/regexptest.cpp b/kioslave/src/autotests/regexptest.cpp
deleted file mode 100644
index e7bfc65f..00000000
--- a/kioslave/src/autotests/regexptest.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-   SPDX-FileCopyrightText: 2018-2022 Laurent Montel <montel at kde.org>
-
-   SPDX-License-Identifier: LGPL-2.0-or-later
-*/
-
-#include "regexptest.h"
-#include <QRegExp>
-#include <QRegularExpression>
-#include <QTest>
-QTEST_GUILESS_MAIN(RegexpTest)
-
-RegexpTest::RegexpTest(QObject *parent)
-    : QObject(parent)
-{
-}
-
-void RegexpTest::compareRegexp_data()
-{
-    QTest::addColumn<QString>("input");
-    QTest::addColumn<int>("major");
-    QTest::addColumn<int>("minor");
-    QTest::addColumn<int>("patch");
-    QTest::addColumn<QString>("vendor");
-    QTest::addColumn<bool>("valid");
-
-    QTest::newRow("empty") << QString() << 0 << 0 << 0 << QString() << false;
-    QTest::newRow("Cyrus timsieved v2.2.12") << QStringLiteral("Cyrus timsieved v2.2.12") << 2 << 2 << 12 << QString() << true;
-    QTest::newRow("Cyrus timsieved v2.2.12-kolab-nocaps")
-        << QStringLiteral("Cyrus timsieved v2.2.12-kolab-nocaps") << 2 << 2 << 12 << QStringLiteral("-kolab-nocaps") << true;
-    QTest::newRow("Cyrus timsieved v5.2.12") << QStringLiteral("Cyrus timsieved v5.2.12") << 5 << 2 << 12 << QString() << true;
-}
-
-void RegexpTest::compareRegexp()
-{
-    QFETCH(QString, input);
-    QFETCH(int, major);
-    QFETCH(int, minor);
-    QFETCH(int, patch);
-    QFETCH(QString, vendor);
-    QFETCH(bool, valid);
-
-    QRegExp regExp(QStringLiteral("Cyrus\\stimsieved\\sv(\\d+)\\.(\\d+)\\.(\\d+)([-\\w]*)"), Qt::CaseInsensitive);
-    bool ok;
-    if (regExp.indexIn(input) >= 0) {
-        QCOMPARE(regExp.cap(1).toInt(), major);
-        QCOMPARE(regExp.cap(2).toInt(), minor);
-        QCOMPARE(regExp.cap(3).toInt(), patch);
-        QCOMPARE(regExp.cap(4), vendor);
-        ok = true;
-    } else {
-        ok = false;
-    }
-    QCOMPARE(valid, ok);
-
-    QRegularExpression re(QStringLiteral("Cyrus\\stimsieved\\sv(\\d+)\\.(\\d+)\\.(\\d+)([-\\w]*)"), QRegularExpression::CaseInsensitiveOption);
-    QRegularExpressionMatch match = re.match(input);
-    if (match.hasMatch()) {
-        QCOMPARE(match.captured(1).toInt(), major);
-        QCOMPARE(match.captured(2).toInt(), minor);
-        QCOMPARE(match.captured(3).toInt(), patch);
-        QCOMPARE(match.captured(4), vendor);
-        ok = true;
-    } else {
-        ok = false;
-    }
-    QCOMPARE(valid, ok);
-}
diff --git a/kioslave/src/autotests/regexptest.h b/kioslave/src/autotests/regexptest.h
deleted file mode 100644
index e7c5b760..00000000
--- a/kioslave/src/autotests/regexptest.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-   SPDX-FileCopyrightText: 2018-2022 Laurent Montel <montel at kde.org>
-
-   SPDX-License-Identifier: LGPL-2.0-or-later
-*/
-
-#pragma once
-
-#include <QObject>
-
-class RegexpTest : public QObject
-{
-    Q_OBJECT
-public:
-    explicit RegexpTest(QObject *parent = nullptr);
-    ~RegexpTest() override = default;
-private Q_SLOTS:
-    void compareRegexp_data();
-    void compareRegexp();
-};
diff --git a/kioslave/src/common.h b/kioslave/src/common.h
deleted file mode 100644
index 549f0af2..00000000
--- a/kioslave/src/common.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*  This file is part of the KDE project
-    SPDX-FileCopyrightText: 2008 Jarosław Staniek <staniek at kde.org>
-
-    SPDX-License-Identifier: LGPL-2.0-or-later
-*/
-
-#pragma once
-
-#include <QCoreApplication>
-#include <QDir>
-#include <QFile>
-#include <cstdio>
-extern "C" {
-#include <sasl/sasl.h>
-}
-
-inline bool initSASL()
-{
-#ifdef Q_OS_WIN // krazy:exclude=cpp
-    for (const auto &path : QCoreApplication::libraryPaths()) {
-        QDir dir(path);
-        if (dir.exists(QStringLiteral("sasl2"))) {
-            auto libInstallPath = QFile::encodeName(dir.absoluteFilePath(QStringLiteral("sasl2")));
-            if (sasl_set_path(SASL_PATH_TYPE_PLUGIN, libInstallPath.data()) != SASL_OK) {
-                fprintf(stderr, "SASL path initialization failed!\n");
-                return false;
-            }
-            break;
-        }
-    }
-#endif
-    if (sasl_client_init(nullptr) != SASL_OK) {
-        fprintf(stderr, "SASL library initialization failed!\n");
-        return false;
-    }
-    return true;
-}
diff --git a/kioslave/src/sieve/CMakeLists.txt b/kioslave/src/sieve/CMakeLists.txt
deleted file mode 100644
index 5de45470..00000000
--- a/kioslave/src/sieve/CMakeLists.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-# SPDX-FileCopyrightText: 2011-2022 Laurent Montel <montel at kde.org>
-# SPDX-License-Identifier: BSD-3-Clause
-
-add_library(kio_sieve MODULE)
-target_sources(kio_sieve PRIVATE sieve.cpp sieve.h)
-ecm_qt_declare_logging_category(kio_sieve HEADER sieve_debug.h IDENTIFIER SIEVE_LOG CATEGORY_NAME org.kde.pim.sieve
-        DESCRIPTION "kioslave (sieve)"
-        OLD_CATEGORY_NAMES log_sieve
-        EXPORT LIBKSIEVE
-    )
-
-
-
-if (WIN32)
-    set(extra_LIBS ws2_32)
-endif()
-
-target_link_libraries(kio_sieve KF5::KIOCore KF5::I18n Qt${QT_MAJOR_VERSION}::Network KF5::WidgetsAddons Sasl2::Sasl2 ${extra_LIBS})
-set_target_properties(kio_sieve PROPERTIES OUTPUT_NAME "sieve")
-if (COMPILE_WITH_UNITY_CMAKE_SUPPORT)
-    set_target_properties(kio_sieve PROPERTIES UNITY_BUILD ON)
-endif()
-
-install(TARGETS kio_sieve  DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf${QT_MAJOR_VERSION}/kio/)
diff --git a/kioslave/src/sieve/Messages.sh b/kioslave/src/sieve/Messages.sh
deleted file mode 100644
index 01f32cff..00000000
--- a/kioslave/src/sieve/Messages.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#! /bin/sh
-# SPDX-License-Identifier: CC0-1.0
-# SPDX-FileCopyrightText: none
-$XGETTEXT *.cpp -o $podir/kio_sieve.pot
diff --git a/kioslave/src/sieve/RFCs b/kioslave/src/sieve/RFCs
deleted file mode 100644
index aa71ffbc..00000000
--- a/kioslave/src/sieve/RFCs
+++ /dev/null
@@ -1,2 +0,0 @@
-3028: Sieve: A Mail Filtering Language
-3431: Sieve Extension: Relational Tests
diff --git a/kioslave/src/sieve/sieve.cpp b/kioslave/src/sieve/sieve.cpp
deleted file mode 100644
index 4e9567b6..00000000
--- a/kioslave/src/sieve/sieve.cpp
+++ /dev/null
@@ -1,1314 +0,0 @@
-/*
-    sieve.cpp
-
-    SPDX-FileCopyrightText: 2001 Hamish Rodda <meddie at yoyo.cc.monash.edu.au>
-
-    SPDX-License-Identifier: GPL-2.0-only
-*/
-
-/**
- * Portions adapted from the SMTP ioslave.
- * SPDX-FileCopyrightText: 2000, 2001 Alex Zepeda <jazepeda at pacbell.net>
- * SPDX-FileCopyrightText: 2001 Michael Häckel <Michael at Haeckel.Net>
- *
- * Policy: the function where the error occurs calls error(). A result of
- * false, where it signifies an error, thus doesn't need to call error() itself.
- */
-
-#include "sieve.h"
-#include "../common.h"
-#include "sieve_debug.h"
-
-extern "C" {
-#include <sasl/sasl.h>
-}
-
-#include <QRegularExpression>
-#include <QSslSocket>
-#include <QUrlQuery>
-
-#include <KLocalizedString>
-#include <KMessageBox>
-#include <QApplication>
-#include <QUrl>
-#include <cassert>
-#include <sys/stat.h>
-namespace
-{
-auto returnEndLine()
-{
-    return Qt::endl;
-}
-}
-#define ksDebug qCDebug(SIEVE_LOG)
-
-#define SIEVE_DEFAULT_PORT 2000
-
-static const sasl_callback_t callbacks[] = {{SASL_CB_ECHOPROMPT, nullptr, nullptr},
-                                            {SASL_CB_NOECHOPROMPT, nullptr, nullptr},
-                                            {SASL_CB_GETREALM, nullptr, nullptr},
-                                            {SASL_CB_USER, nullptr, nullptr},
-                                            {SASL_CB_AUTHNAME, nullptr, nullptr},
-                                            {SASL_CB_PASS, nullptr, nullptr},
-                                            {SASL_CB_CANON_USER, nullptr, nullptr},
-                                            {SASL_CB_LIST_END, nullptr, nullptr}};
-
-static const unsigned int SIEVE_DEFAULT_RECIEVE_BUFFER = 512;
-
-// Pseudo plugin class to embed meta data
-class KIOPluginForMetaData : public QObject
-{
-    Q_OBJECT
-    Q_PLUGIN_METADATA(IID "org.kde.kio.slave.sieve" FILE "sieve.json")
-};
-
-using namespace KIO;
-extern "C" {
-Q_DECL_EXPORT int kdemain(int argc, char **argv)
-{
-    QApplication app(argc, argv);
-    app.setApplicationName(QStringLiteral("kio_sieve"));
-
-    ksDebug << "*** Starting kio_sieve " << returnEndLine();
-
-    if (argc != 4) {
-        ksDebug << "Usage: kio_sieve protocol domain-socket1 domain-socket2" << returnEndLine();
-        return -1;
-    }
-
-    if (!initSASL()) {
-        ::exit(-1);
-    }
-
-    kio_sieveProtocol slave(argv[2], argv[3]);
-    slave.dispatchLoop();
-
-    sasl_done();
-
-    ksDebug << "*** kio_sieve Done" << returnEndLine();
-    return 0;
-}
-}
-
-/* ---------------------------------------------------------------------------------- */
-kio_sieveResponse::kio_sieveResponse()
-{
-    clear();
-}
-
-/* ---------------------------------------------------------------------------------- */
-const uint &kio_sieveResponse::getType() const
-{
-    return rType;
-}
-
-/* ---------------------------------------------------------------------------------- */
-uint kio_sieveResponse::getQuantity() const
-{
-    return quantity;
-}
-
-/* ---------------------------------------------------------------------------------- */
-const QByteArray &kio_sieveResponse::getAction() const
-{
-    return key;
-}
-
-/* ---------------------------------------------------------------------------------- */
-const QByteArray &kio_sieveResponse::getKey() const
-{
-    return key;
-}
-
-/* ---------------------------------------------------------------------------------- */
-const QByteArray &kio_sieveResponse::getVal() const
-{
-    return val;
-}
-
-/* ---------------------------------------------------------------------------------- */
-const QByteArray &kio_sieveResponse::getExtra() const
-{
-    return extra;
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveResponse::setQuantity(uint newQty)
-{
-    rType = QUANTITY;
-    quantity = newQty;
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveResponse::setAction(const QByteArray &newAction)
-{
-    rType = ACTION;
-    key = newAction;
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveResponse::setKey(const QByteArray &newKey)
-{
-    rType = KEY_VAL_PAIR;
-    key = newKey;
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveResponse::setVal(const QByteArray &newVal)
-{
-    val = newVal;
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveResponse::setExtra(const QByteArray &newExtra)
-{
-    extra = newExtra;
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveResponse::clear()
-{
-    rType = NONE;
-    extra = key = val = QByteArray();
-    quantity = 0;
-}
-
-/* ---------------------------------------------------------------------------------- */
-kio_sieveProtocol::kio_sieveProtocol(const QByteArray &pool_socket, const QByteArray &app_socket)
-    : TCPSlaveBase("sieve", pool_socket, app_socket, false)
-    , m_connMode(NORMAL)
-    , m_supportsTLS(false)
-    , m_shouldBeConnected(false)
-    , m_allowUnencrypted(false)
-    , m_port(SIEVE_DEFAULT_PORT)
-{
-}
-
-/* ---------------------------------------------------------------------------------- */
-kio_sieveProtocol::~kio_sieveProtocol()
-{
-    if (isConnected()) {
-        disconnect();
-    }
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveProtocol::setHost(const QString &host, quint16 port, const QString &user, const QString &pass)
-{
-    if (isConnected() && (m_sServer != host || m_port != port || m_sUser != user || m_sPass != pass)) {
-        disconnect();
-    }
-    m_sServer = host;
-    m_port = port ? port : SIEVE_DEFAULT_PORT;
-    m_sUser = user;
-    m_sPass = pass;
-    m_supportsTLS = false;
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveProtocol::openConnection()
-{
-    m_connMode = CONNECTION_ORIENTED;
-    connect();
-}
-
-bool kio_sieveProtocol::parseCapabilities(bool requestCapabilities /* = false*/)
-{
-    ksDebug << returnEndLine();
-
-    // Setup...
-    bool ret = false;
-
-    if (requestCapabilities) {
-        sendData("CAPABILITY");
-    }
-
-    while (receiveData()) {
-        ksDebug << "Looping receive" << returnEndLine();
-
-        if (r.getType() == kio_sieveResponse::ACTION) {
-            if (r.getAction().toLower().contains("ok")) {
-                ksDebug << "Sieve server ready & awaiting authentication." << returnEndLine();
-                break;
-            } else {
-                ksDebug << "Unknown action " << r.getAction() << "." << returnEndLine();
-            }
-        } else if (r.getKey() == "IMPLEMENTATION") {
-            ksDebug << "Connected to Sieve server: " << r.getVal() << returnEndLine();
-            ret = true;
-            setMetaData(QStringLiteral("implementation"), QLatin1String(r.getVal()));
-            m_implementation = QLatin1String(r.getVal());
-        } else if (r.getKey() == "SASL") {
-            // Save list of available SASL methods
-            const QString val = QLatin1String(r.getVal());
-            m_sasl_caps = val.split(QLatin1Char(' '));
-            ksDebug << "Server SASL authentication methods: " << m_sasl_caps.join(QLatin1String(", ")) << returnEndLine();
-            setMetaData(QStringLiteral("saslMethods"), QLatin1String(r.getVal()));
-        } else if (r.getKey() == "SIEVE") {
-            // Save script capabilities; report back as meta data:
-            const QString val = QLatin1String(r.getVal());
-            ksDebug << "Server script capabilities: " << val.split(QLatin1Char(' ')).join(QLatin1String(", ")) << returnEndLine();
-            setMetaData(QStringLiteral("sieveExtensions"), QLatin1String(r.getVal()));
-        } else if (r.getKey() == "STARTTLS") {
-            // The server supports TLS
-            ksDebug << "Server supports TLS" << returnEndLine();
-            m_supportsTLS = true;
-            setMetaData(QStringLiteral("tlsSupported"), QStringLiteral("true"));
-        } else {
-            ksDebug << "Unrecognised key " << r.getKey() << returnEndLine();
-        }
-    }
-
-    if (!m_supportsTLS) {
-        setMetaData(QStringLiteral("tlsSupported"), QStringLiteral("false"));
-    }
-
-    return ret;
-}
-
-/* ---------------------------------------------------------------------------------- */
-/**
- * Checks if connection parameters have changed.
- * If it it, close the current connection
- */
-void kio_sieveProtocol::changeCheck(const QUrl &url)
-{
-    QString auth;
-
-    // Check the SASL auth mechanism in the 'sasl' metadata...
-    if (!metaData(QStringLiteral("sasl")).isEmpty()) {
-        auth = metaData(QStringLiteral("sasl")).toUpper();
-    } else {
-        // ... and if not found, check the x-mech=AUTH query part of the url.
-        QString query = url.query();
-        if (query.startsWith(QLatin1Char('?'))) {
-            query.remove(0, 1);
-        }
-        QStringList q = query.split(QLatin1Char(','));
-
-        for (QStringList::iterator it = q.begin(), end(q.end()); it != end; ++it) {
-            if (((*it).section(QLatin1Char('='), 0, 0)).toLower() == QLatin1String("x-mech")) {
-                auth = ((*it).section(QLatin1Char('='), 1)).toUpper();
-                break;
-            }
-        }
-    }
-    ksDebug << "auth: " << auth << " m_sAuth: " << m_sAuth << returnEndLine();
-    if (m_sAuth != auth) {
-        m_sAuth = auth;
-        if (isConnected()) {
-            disconnect();
-        }
-    }
-    // For TLS, only disconnect if we are unencrypted and are
-    // no longer allowed (otherwise, it's still fine):
-    const bool allowUnencryptedNow = QUrlQuery(url).queryItemValue(QStringLiteral("x-allow-unencrypted")) == QLatin1String("true");
-    if (m_allowUnencrypted && !allowUnencryptedNow) {
-        if (isConnected()) {
-            disconnect();
-        }
-    }
-    m_allowUnencrypted = allowUnencryptedNow;
-}
-
-/* ---------------------------------------------------------------------------------- */
-/**
- * Connects to the server.
- * returns false and calls error() if an error occurred.
- */
-bool kio_sieveProtocol::connect(bool useTLSIfAvailable)
-{
-    ksDebug << returnEndLine();
-
-    if (isConnected()) {
-        return true;
-    }
-
-    infoMessage(i18n("Connecting to %1...", m_sServer));
-
-    if (m_connMode == CONNECTION_ORIENTED && m_shouldBeConnected) {
-        error(ERR_CONNECTION_BROKEN, i18n("The connection to the server was lost."));
-        return false;
-    }
-
-    setBlocking(true);
-
-    if (!connectToHost(QStringLiteral("sieve"), m_sServer, m_port)) {
-        return false;
-    }
-
-    if (!parseCapabilities()) {
-        disconnectFromHost();
-        error(ERR_UNSUPPORTED_PROTOCOL, i18n("Server identification failed."));
-        return false;
-    }
-
-    // Attempt to start TLS
-    if (!m_allowUnencrypted && !QSslSocket::supportsSsl()) {
-        error(KIO::ERR_WORKER_DEFINED, i18n("Can not use TLS since the underlying Qt library does not support it."));
-        disconnect();
-        return false;
-    }
-
-    if (!m_allowUnencrypted && useTLSIfAvailable && QSslSocket::supportsSsl() && !m_supportsTLS
-        && messageBox(WarningContinueCancel,
-                      i18n("TLS encryption was requested, but your Sieve server does not advertise TLS in its capabilities.\n"
-                           "You can choose to try to initiate TLS negotiations nonetheless, or cancel the operation."),
-                      i18n("Server Does Not Advertise TLS"),
-                      i18n("&Start TLS nonetheless"),
-                      i18n("&Cancel"))
-            != KMessageBox::Continue) {
-        error(ERR_USER_CANCELED, i18n("TLS encryption requested, but not supported by server."));
-        disconnect();
-        return false;
-    }
-
-    // FIXME find a test server and test that this works
-    if (useTLSIfAvailable && m_supportsTLS && QSslSocket::supportsSsl()) {
-        sendData("STARTTLS");
-        if (operationSuccessful()) {
-            ksDebug << "TLS has been accepted. Starting TLS..." << returnEndLine() << "WARNING this is untested and may fail.";
-            if (startSsl()) {
-                ksDebug << "TLS enabled successfully." << returnEndLine();
-                // reparse capabilities:
-                parseCapabilities(requestCapabilitiesAfterStartTLS());
-            } else {
-                ksDebug << "TLS initiation failed.";
-                if (m_allowUnencrypted) {
-                    disconnect(true);
-                    return connect(false);
-                }
-                messageBox(Information,
-                           i18n("Your Sieve server claims to support TLS, "
-                                "but negotiation was unsuccessful."),
-                           i18n("Connection Failed"));
-                disconnect(true);
-                return false;
-            }
-        } else if (!m_allowUnencrypted) {
-            ksDebug << "Server incapable of TLS.";
-            disconnect();
-            error(KIO::ERR_WORKER_DEFINED,
-                  i18n("The server does not seem to support TLS. "
-                       "Disable TLS if you want to connect without encryption."));
-            return false;
-        } else {
-            ksDebug << "Server incapable of TLS. Transmitted documents will be unencrypted." << returnEndLine();
-        }
-    } else {
-        ksDebug << "We are incapable of TLS. Transmitted documents will be unencrypted." << returnEndLine();
-    }
-
-    assert(m_allowUnencrypted || isUsingSsl());
-
-    infoMessage(i18n("Authenticating user..."));
-    if (!authenticate()) {
-        disconnect();
-        error(ERR_CANNOT_AUTHENTICATE, i18n("Authentication failed."));
-        return false;
-    }
-
-    m_shouldBeConnected = true;
-    return true;
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveProtocol::closeConnection()
-{
-    m_connMode = CONNECTION_ORIENTED;
-    disconnect();
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveProtocol::disconnect(bool forcibly)
-{
-    if (!forcibly) {
-        sendData("LOGOUT");
-
-        if (!operationSuccessful()) {
-            ksDebug << "Server did not logout cleanly." << returnEndLine();
-        }
-    }
-
-    disconnectFromHost();
-    m_shouldBeConnected = false;
-}
-
-/* ---------------------------------------------------------------------------------- */
-/*void kio_sieveProtocol::slave_status()
-{
-    slaveStatus(isConnected() ? m_sServer : "", isConnected());
-
-    finished();
-}*/
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveProtocol::special(const QByteArray &data)
-{
-    int tmp;
-    QDataStream stream(data);
-    QUrl url;
-
-    stream >> tmp;
-
-    switch (tmp) {
-    case 1:
-        stream >> url;
-        if (!activate(url)) {
-            return;
-        }
-        break;
-    case 2:
-        if (!deactivate()) {
-            return;
-        }
-        break;
-    case 3:
-        parseCapabilities(true);
-        break;
-    }
-
-    infoMessage(i18nc("special command completed", "Done."));
-
-    finished();
-}
-
-/* ---------------------------------------------------------------------------------- */
-bool kio_sieveProtocol::activate(const QUrl &url)
-{
-    changeCheck(url);
-    if (!connect()) {
-        return false;
-    }
-
-    infoMessage(i18n("Activating script..."));
-
-    QString filename = url.fileName();
-
-    if (filename.isEmpty()) {
-        error(ERR_DOES_NOT_EXIST, url.toDisplayString());
-        return false;
-    }
-
-    if (!sendData("SETACTIVE \"" + filename.toUtf8() + "\"")) {
-        return false;
-    }
-
-    if (operationSuccessful()) {
-        ksDebug << "Script activation complete." << returnEndLine();
-        return true;
-    } else {
-        error(ERR_INTERNAL_SERVER, i18n("There was an error activating the script."));
-        return false;
-    }
-}
-
-/* ---------------------------------------------------------------------------------- */
-bool kio_sieveProtocol::deactivate()
-{
-    if (!connect()) {
-        return false;
-    }
-
-    if (!sendData("SETACTIVE \"\"")) {
-        return false;
-    }
-
-    if (operationSuccessful()) {
-        ksDebug << "Script deactivation complete." << returnEndLine();
-        return true;
-    } else {
-        error(ERR_INTERNAL_SERVER, i18n("There was an error deactivating the script."));
-        return false;
-    }
-}
-
-static void append_lf2crlf(QByteArray &out, const QByteArray &in)
-{
-    if (in.isEmpty()) {
-        return;
-    }
-    const unsigned int oldOutSize = out.size();
-    out.resize(oldOutSize + 2 * in.size());
-    const char *s = in.begin();
-    const char *const end = in.end();
-    char *d = out.begin() + oldOutSize;
-    char last = '\0';
-    while (s < end) {
-        if (*s == '\n' && last != '\r') {
-            *d++ = '\r';
-        }
-        *d++ = last = *s++;
-    }
-    out.resize(d - out.begin());
-}
-
-void kio_sieveProtocol::put(const QUrl &url, int /*permissions*/, KIO::JobFlags)
-{
-    changeCheck(url);
-    if (!connect()) {
-        return;
-    }
-
-    infoMessage(i18n("Sending data..."));
-
-    QString filename = url.fileName();
-
-    if (filename.isEmpty()) {
-        error(ERR_MALFORMED_URL, url.toDisplayString());
-        return;
-    }
-
-    QByteArray data;
-    for (;;) {
-        dataReq();
-        QByteArray buffer;
-        const int newSize = readData(buffer);
-        append_lf2crlf(data, buffer);
-        if (newSize < 0) {
-            // read error: network in unknown state so disconnect
-            error(ERR_CANNOT_READ, i18n("KIO data supply error."));
-            return;
-        }
-        if (newSize == 0) {
-            break;
-        }
-    }
-
-    // script size
-    int bufLen = (int)data.size();
-    totalSize(bufLen);
-
-    // timsieved 1.1.0:
-    // C: HAVESPACE "rejected" 74
-    // S: NO "Number expected"
-    // C: HAVESPACE 74
-    // S: NO "Missing script name"
-    // S: HAVESPACE "rejected" "74"
-    // C: NO "Number expected"
-    // => broken, we can't use it :-(
-    // (will be fixed in Cyrus 2.1.10)
-
-    if (!sendData("PUTSCRIPT \"" + filename.toUtf8() + "\" {" + QByteArray::number(bufLen) + "+}")) {
-        return;
-    }
-
-    // atEnd() lies so the code below doesn't work.
-    /*if (!atEnd()) {
-        // We are not expecting any data here, so if the server has responded
-        // with anything but OK we treat it as an error.
-        char * buf = new char[2];
-        while (!atEnd()) {
-                ksDebug << "Reading..." << returnEndLine();
-                read(buf, 1);
-                ksDebug << "Trailing [" << buf[0] << "]" << returnEndLine();
-        }
-        ksDebug << "End of data." << returnEndLine();
-        delete[] buf;
-
-        if (!operationSuccessful()) {
-                error(ERR_UNSUPPORTED_PROTOCOL, i18n("A protocol error occurred "
-                                        "while trying to negotiate script uploading.\n"
-                                        "The server responded:\n%1")
-                                                .arg(r.getAction().right(r.getAction().length() - 3)));
-                return;
-        }
-    }*/
-
-    // upload data to the server
-    if (write(data.constData(), bufLen) != bufLen) {
-        error(ERR_CANNOT_WRITE, i18n("Network error."));
-        disconnect(true);
-        return;
-    }
-
-    // finishing CR/LF
-    if (!sendData("")) {
-        return;
-    }
-
-    processedSize(bufLen);
-
-    infoMessage(i18n("Verifying upload completion..."));
-
-    if (operationSuccessful()) {
-        ksDebug << "Script upload complete." << returnEndLine();
-    } else {
-        /* The managesieve server parses received scripts and rejects
-         * scripts which are not syntactically correct. Here we expect
-         * to receive a message detailing the error (only the first
-         * error is reported. */
-        if (r.getAction().length() > 3) {
-            // make a copy of the extra info
-            QByteArray extra = r.getAction().right(r.getAction().length() - 3);
-
-            // send the extra message off for re-processing
-            receiveData(false, extra);
-
-            if (r.getType() == kio_sieveResponse::QUANTITY) {
-                // length of the error message
-                uint len = r.getQuantity();
-
-                QByteArray errmsg(len, 0);
-
-                read(errmsg.data(), len);
-
-                error(ERR_INTERNAL_SERVER,
-                      i18n("The script did not upload successfully.\n"
-                           "This is probably due to errors in the script.\n"
-                           "The server responded:\n%1",
-                           QString::fromLatin1(errmsg.data(), errmsg.size())));
-
-                // clear the rest of the incoming data
-                receiveData();
-            } else if (r.getType() == kio_sieveResponse::KEY_VAL_PAIR) {
-                error(ERR_INTERNAL_SERVER,
-                      i18n("The script did not upload successfully.\n"
-                           "This is probably due to errors in the script.\n"
-                           "The server responded:\n%1",
-                           QString::fromUtf8(r.getKey())));
-            } else {
-                error(ERR_INTERNAL_SERVER,
-                      i18n("The script did not upload successfully.\n"
-                           "The script may contain errors."));
-            }
-        } else {
-            error(ERR_INTERNAL_SERVER,
-                  i18n("The script did not upload successfully.\n"
-                       "The script may contain errors."));
-        }
-    }
-
-    // if ( permissions != -1 )
-    //        chmod( url, permissions );
-
-    infoMessage(i18nc("data upload complete", "Done."));
-
-    finished();
-}
-
-static void inplace_crlf2lf(QByteArray &in)
-{
-    if (in.isEmpty()) {
-        return;
-    }
-    QByteArray &out = in; // inplace
-    const char *s = in.begin();
-    const char *const end = in.end();
-    char *d = out.begin();
-    char last = '\0';
-    while (s < end) {
-        if (*s == '\n' && last == '\r') {
-            --d;
-        }
-        *d++ = last = *s++;
-    }
-    out.resize(d - out.begin());
-}
-
-/* ---------------------------------------------------------------------------------- */
-void kio_sieveProtocol::get(const QUrl &url)
-{
-    changeCheck(url);
-    if (!connect()) {
-        return;
-    }
-
-    infoMessage(i18n("Retrieving data..."));
-
-    QString filename = url.fileName();
-
-    if (filename.isEmpty()) {
-        error(ERR_MALFORMED_URL, url.toDisplayString());
-        return;
-    }
-
-    // SlaveBase::mimetype( QString("text/plain") ); // "application/sieve");
-
-    if (!sendData("GETSCRIPT \"" + filename.toUtf8() + "\"")) {
-        return;
-    }
-
-    if (receiveData() && r.getType() == kio_sieveResponse::QUANTITY) {
-        // determine script size
-        ssize_t total_len = r.getQuantity();
-        totalSize(total_len);
-
-        ssize_t recv_len = 0;
-        do {
-            // wait for data...
-            if (!waitForResponse(600)) {
-                error(KIO::ERR_SERVER_TIMEOUT, m_sServer);
-                disconnect(true);
-                return;
-            }
-
-            // ...read data...
-            // Only read as much as we need, otherwise we slurp in the OK that
-            // operationSuccessful() is expecting below.
-            QByteArray dat(qMin(total_len - recv_len, ssize_t(64 * 1024)), '\0');
-            ssize_t this_recv_len = read(dat.data(), dat.size());
-
-            if (this_recv_len < 1 && !isConnected()) {
-                error(KIO::ERR_CONNECTION_BROKEN, m_sServer);
-                disconnect(true);
-                return;
-            }
-
-            dat.resize(this_recv_len);
-            inplace_crlf2lf(dat);
-            // send data to slaveinterface
-            data(dat);
-
-            recv_len += this_recv_len;
-            processedSize(recv_len);
-        } while (recv_len < total_len);
-
-        infoMessage(i18n("Finishing up..."));
-        data(QByteArray());
-
-        if (operationSuccessful()) {
-            ksDebug << "Script retrieval complete." << returnEndLine();
-        } else {
-            ksDebug << "Script retrieval failed." << returnEndLine();
-        }
-    } else {
-        error(ERR_UNSUPPORTED_PROTOCOL,
-              i18n("A protocol error occurred "
-                   "while trying to negotiate script downloading."));
-        return;
-    }
-
-    infoMessage(i18nc("data retrieval complete", "Done."));
-    finished();
-}
-
-void kio_sieveProtocol::del(const QUrl &url, bool isfile)
-{
-    if (!isfile) {
-        error(ERR_INTERNAL, i18n("Folders are not supported."));
-        return;
-    }
-
-    changeCheck(url);
-    if (!connect()) {
-        return;
-    }
-
-    infoMessage(i18n("Deleting file..."));
-
-    QString filename = url.fileName();
-
-    if (filename.isEmpty()) {
-        error(ERR_MALFORMED_URL, url.toDisplayString());
-        return;
-    }
-
-    if (!sendData("DELETESCRIPT \"" + filename.toUtf8() + "\"")) {
-        return;
-    }
-
-    if (operationSuccessful()) {
-        ksDebug << "Script deletion successful." << returnEndLine();
-    } else {
-        error(ERR_INTERNAL_SERVER, i18n("The server would not delete the file."));
-        return;
-    }
-
-    infoMessage(i18nc("file removal complete", "Done."));
-
-    finished();
-}
-
-void kio_sieveProtocol::chmod(const QUrl &url, int permissions)
-{
-    switch (permissions) {
-    case 0700: // activate
-        activate(url);
-        break;
-    case 0600: // deactivate
-        deactivate();
-        break;
-    default: // unsupported
-        error(ERR_CANNOT_CHMOD, i18n("Cannot chmod to anything but 0700 (active) or 0600 (inactive script)."));
-        return;
-    }
-
-    finished();
-}
-
-void kio_sieveProtocol::urlStat(const QUrl &url)
-{
-    changeCheck(url);
-    if (!connect()) {
-        return;
-    }
-
-    UDSEntry entry;
-
-    QString filename = url.fileName();
-
-    if (filename.isEmpty()) {
-        entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("/"));
-
-        entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
-
-        entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, 0700);
-
-        statEntry(entry);
-    } else {
-        if (!sendData("LISTSCRIPTS")) {
-            return;
-        }
-
-        while (receiveData()) {
-            if (r.getType() == kio_sieveResponse::ACTION) {
-                if (r.getAction().toLower().count("ok") == 1) {
-                    // Script list completed
-                    break;
-                }
-            } else {
-                if (filename == QString::fromUtf8(r.getKey())) {
-                    entry.clear();
-
-                    entry.fastInsert(KIO::UDSEntry::UDS_NAME, QString::fromUtf8(r.getKey()));
-
-                    entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG);
-
-                    if (r.getExtra() == "ACTIVE") {
-                        entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, 0700);
-                    } else {
-                        entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, 0600);
-                    }
-
-                    entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("application/sieve"));
-
-                    // setMetaData("active", (r.getExtra() == "ACTIVE") ? "yes" : "no");
-
-                    statEntry(entry);
-                    // cannot break here because we need to clear
-                    // the rest of the incoming data.
-                }
-            }
-        }
-    }
-
-    finished();
-}
-
-void kio_sieveProtocol::listDir(const QUrl &url)
-{
-    changeCheck(url);
-    if (!connect()) {
-        return;
-    }
-
-    if (!sendData("LISTSCRIPTS")) {
-        return;
-    }
-
-    UDSEntry entry;
-
-    while (receiveData()) {
-        if (r.getType() == kio_sieveResponse::ACTION) {
-            if (r.getAction().toLower().count("ok") == 1) {
-                // Script list completed.
-                break;
-            }
-        } else {
-            entry.clear();
-            entry.fastInsert(KIO::UDSEntry::UDS_NAME, QString::fromUtf8(r.getKey()));
-
-            entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG);
-
-            if (r.getExtra() == "ACTIVE") {
-                entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, 0700); // mark exec'able
-            } else {
-                entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, 0600);
-            }
-
-            entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("application/sieve"));
-
-            // asetMetaData("active", (r.getExtra() == "ACTIVE") ? "true" : "false");
-
-            ksDebug << "Listing script " << r.getKey() << returnEndLine();
-            listEntry(entry);
-        }
-    }
-
-    finished();
-}
-
-/* ---------------------------------------------------------------------------------- */
-bool kio_sieveProtocol::saslInteract(void *in, AuthInfo &ai)
-{
-    ksDebug << "sasl_interact" << returnEndLine();
-    auto *interact = (sasl_interact_t *)in;
-
-    // some mechanisms do not require username && pass, so it doesn't need a popup
-    // window for getting this info
-    for (; interact->id != SASL_CB_LIST_END; interact++) {
-        if (interact->id == SASL_CB_AUTHNAME || interact->id == SASL_CB_PASS) {
-            if (m_sUser.isEmpty() || m_sPass.isEmpty()) {
-                const int errorCode = openPasswordDialogV2(ai);
-                if (errorCode) {
-                    // calling error() below is wrong for two reasons:
-                    // - ERR_ABORTED is too harsh
-                    // - higher layers already call error() and that can't happen twice.
-                    // error(ERR_ABORTED, i18n("No authentication details supplied."));
-                    error(errorCode, QString());
-                    return false;
-                }
-                m_sUser = ai.username;
-                m_sPass = ai.password;
-            }
-            break;
-        }
-    }
-
-    interact = (sasl_interact_t *)in;
-    while (interact->id != SASL_CB_LIST_END) {
-        ksDebug << "SASL_INTERACT id: " << interact->id << returnEndLine();
-        switch (interact->id) {
-        case SASL_CB_USER:
-        case SASL_CB_AUTHNAME:
-            ksDebug << "SASL_CB_[AUTHNAME|USER]: '" << m_sUser << "'" << returnEndLine();
-            interact->result = strdup(m_sUser.toUtf8().constData());
-            interact->len = strlen((const char *)interact->result);
-            break;
-        case SASL_CB_PASS:
-            ksDebug << "SASL_CB_PASS: [hidden] " << returnEndLine();
-            interact->result = strdup(m_sPass.toUtf8().constData());
-            interact->len = strlen((const char *)interact->result);
-            break;
-        default:
-            interact->result = nullptr;
-            interact->len = 0;
-            break;
-        }
-        interact++;
-    }
-    return true;
-}
-
-#define SASLERROR error(ERR_CANNOT_AUTHENTICATE, i18n("An error occurred during authentication: %1", QString::fromUtf8(sasl_errdetail(conn))));
-
-bool kio_sieveProtocol::authenticate()
-{
-    int result;
-    sasl_conn_t *conn = nullptr;
-    sasl_interact_t *client_interact = nullptr;
-    const char *out = nullptr;
-    uint outlen;
-    const char *mechusing = nullptr;
-    QByteArray challenge;
-
-    /* Retrieve authentication details from user.
-     * Note: should this require realm as well as user & pass details
-     * before it automatically skips the prompt?
-     * Note2: encoding issues with PLAIN login? */
-    AuthInfo ai;
-    ai.url.setScheme(QStringLiteral("sieve"));
-    ai.url.setHost(m_sServer);
-    ai.url.setPort(m_port);
-    ai.username = m_sUser;
-    ai.password = m_sPass;
-    ai.keepPassword = true;
-    ai.caption = i18n("Sieve Authentication Details");
-    ai.comment = i18n(
-        "Please enter your authentication details for your sieve account "
-        "(usually the same as your email password):");
-
-    result = sasl_client_new("sieve", m_sServer.toLatin1().constData(), nullptr, nullptr, callbacks, 0, &conn);
-    if (result != SASL_OK) {
-        ksDebug << "sasl_client_new failed with: " << result << returnEndLine();
-        SASLERROR
-        return false;
-    }
-
-    QStringList strList;
-    //    strList.append("NTLM");
-
-    if (!m_sAuth.isEmpty()) {
-        strList.append(m_sAuth);
-    } else {
-        strList = m_sasl_caps;
-    }
-
-    do {
-        result = sasl_client_start(conn, strList.join(QLatin1Char(' ')).toLatin1().constData(), &client_interact, &out, &outlen, &mechusing);
-
-        if (result == SASL_INTERACT) {
-            if (!saslInteract(client_interact, ai)) {
-                sasl_dispose(&conn);
-                return false;
-            }
-        }
-    } while (result == SASL_INTERACT);
-
-    if (result != SASL_CONTINUE && result != SASL_OK) {
-        ksDebug << "sasl_client_start failed with: " << result << returnEndLine();
-        SASLERROR
-        sasl_dispose(&conn);
-        return false;
-    }
-
-    ksDebug << "Preferred authentication method is " << mechusing << "." << returnEndLine();
-
-    QString firstCommand = QLatin1String("AUTHENTICATE \"") + QString::fromLatin1(mechusing) + QLatin1String("\"");
-    challenge = QByteArray::fromRawData(out, outlen).toBase64();
-    if (!challenge.isEmpty()) {
-        firstCommand += QLatin1String(" \"");
-        firstCommand += QString::fromLatin1(challenge.data(), challenge.size());
-        firstCommand += QLatin1Char('\"');
-    }
-
-    if (!sendData(firstCommand.toLatin1())) {
-        return false;
-    }
-
-    do {
-        receiveData();
-
-        if (operationResult() != OTHER) {
-            break;
-        }
-
-        ksDebug << "Challenge len  " << r.getQuantity() << returnEndLine();
-
-        if (r.getType() != kio_sieveResponse::QUANTITY) {
-            sasl_dispose(&conn);
-            error(ERR_UNSUPPORTED_PROTOCOL, QString::fromLatin1(mechusing));
-            return false;
-        }
-
-        int qty = r.getQuantity();
-
-        receiveData();
-
-        if (r.getType() != kio_sieveResponse::ACTION && r.getAction().length() != qty) {
-            sasl_dispose(&conn);
-            error(ERR_UNSUPPORTED_PROTOCOL,
-                  i18n("A protocol error occurred during authentication.\n"
-                       "Choose a different authentication method to %1.",
-                       QLatin1String(mechusing)));
-            return false;
-        }
-        challenge = QByteArray::fromBase64(QByteArray::fromRawData(r.getAction().data(), qty));
-        //        ksDebug << "S:  [" << r.getAction() << "]." << returnEndLine();
-
-        do {
-            result = sasl_client_step(conn, challenge.isEmpty() ? nullptr : challenge.data(), challenge.size(), &client_interact, &out, &outlen);
-
-            if (result == SASL_INTERACT) {
-                if (!saslInteract(client_interact, ai)) {
-                    sasl_dispose(&conn);
-                    return false;
-                }
-            }
-        } while (result == SASL_INTERACT);
-
-        ksDebug << "sasl_client_step: " << result << returnEndLine();
-        if (result != SASL_CONTINUE && result != SASL_OK) {
-            ksDebug << "sasl_client_step failed with: " << result << returnEndLine();
-            SASLERROR
-            sasl_dispose(&conn);
-            return false;
-        }
-
-        sendData('\"' + QByteArray::fromRawData(out, outlen).toBase64() + '\"');
-        //    ksDebug << "C-1:  [" << out << "]." << returnEndLine();
-    } while (true);
-
-    ksDebug << "Challenges finished." << returnEndLine();
-    sasl_dispose(&conn);
-
-    if (operationResult() == OK) {
-        // Authentication succeeded.
-        return true;
-    } else {
-        // Authentication failed.
-        error(ERR_CANNOT_AUTHENTICATE,
-              i18n("Authentication failed.\nMost likely the password is wrong.\nThe server responded:\n%1", QString::fromLatin1(r.getAction())));
-        return false;
-    }
-}
-
-/* --------------------------------------------------------------------------- */
-void kio_sieveProtocol::mimetype(const QUrl &url)
-{
-    ksDebug << "Requesting mimetype for " << url.toDisplayString() << returnEndLine();
-
-    if (url.fileName().isEmpty()) {
-        mimeType(QStringLiteral("inode/directory"));
-    } else {
-        mimeType(QStringLiteral("application/sieve"));
-    }
-
-    finished();
-}
-
-/* --------------------------------------------------------------------------- */
-bool kio_sieveProtocol::sendData(const QByteArray &data)
-{
-    QByteArray write_buf = data + "\r\n";
-
-    // ksDebug << "C: " << data << returnEndLine();
-
-    // Write the command
-    ssize_t write_buf_len = write_buf.length();
-    if (write(write_buf.data(), write_buf_len) != write_buf_len) {
-        error(ERR_CANNOT_WRITE, i18n("Network error."));
-        disconnect(true);
-        return false;
-    }
-
-    return true;
-}
-
-/* --------------------------------------------------------------------------- */
-bool kio_sieveProtocol::receiveData(bool waitForData, const QByteArray &reparse)
-{
-    QByteArray interpret;
-    int start;
-    int end;
-
-    if (reparse.isEmpty()) {
-        if (!waitForData) {
-            // is there data waiting?
-            if (atEnd()) {
-                return false;
-            }
-        }
-
-        // read data from the server
-        char buffer[SIEVE_DEFAULT_RECIEVE_BUFFER];
-        const ssize_t numRead = readLine(buffer, SIEVE_DEFAULT_RECIEVE_BUFFER - 1);
-        if (numRead < 0) {
-            return false;
-        }
-        buffer[SIEVE_DEFAULT_RECIEVE_BUFFER - 1] = '\0';
-
-        // strip LF/CR
-        interpret = QByteArray(buffer, qstrlen(buffer) - 2);
-    } else {
-        interpret = reparse;
-    }
-
-    r.clear();
-
-    // ksDebug << "S: " << interpret << returnEndLine();
-
-    switch (interpret[0]) {
-    case '{': {
-        // expecting {quantity}
-        start = 0;
-        end = interpret.indexOf("+}", start + 1);
-        // some older versions of Cyrus enclose the literal size just in { } instead of { +}
-        if (end == -1) {
-            end = interpret.indexOf('}', start + 1);
-        }
-
-        bool ok = false;
-        r.setQuantity(interpret.mid(start + 1, end - start - 1).toUInt(&ok));
-        if (!ok) {
-            disconnect();
-            error(ERR_INTERNAL_SERVER, i18n("A protocol error occurred."));
-            return false;
-        }
-
-        return true;
-    }
-    case '"':
-        // expecting "key" "value" pairs
-        break;
-    default:
-        // expecting single string
-        r.setAction(interpret);
-        return true;
-    }
-
-    start = 0;
-
-    end = interpret.indexOf('"', start + 1);
-    if (end == -1) {
-        ksDebug << "Possible insufficient buffer size." << returnEndLine();
-        r.setKey(interpret.right(interpret.length() - start));
-        return true;
-    }
-
-    r.setKey(interpret.mid(start + 1, end - start - 1));
-
-    start = interpret.indexOf('"', end + 1);
-    if (start == -1) {
-        if ((int)interpret.length() > end) {
-            // skip " and space
-            r.setExtra(interpret.right(interpret.length() - end - 2));
-        }
-
-        return true;
-    }
-
-    end = interpret.indexOf('"', start + 1);
-    if (end == -1) {
-        ksDebug << "Possible insufficient buffer size." << returnEndLine();
-        r.setVal(interpret.right(interpret.length() - start));
-        return true;
-    }
-
-    r.setVal(interpret.mid(start + 1, end - start - 1));
-    return true;
-}
-
-bool kio_sieveProtocol::operationSuccessful()
-{
-    while (receiveData(true)) {
-        if (r.getType() == kio_sieveResponse::ACTION) {
-            QByteArray response = r.getAction().left(2);
-            if (response == "OK") {
-                return true;
-            } else if (response == "NO") {
-                return false;
-            }
-        }
-    }
-    return false;
-}
-
-int kio_sieveProtocol::operationResult()
-{
-    if (r.getType() == kio_sieveResponse::ACTION) {
-        QByteArray response = r.getAction().left(2);
-        if (response == "OK") {
-            return OK;
-        } else if (response == "NO") {
-            return NO;
-        } else if (response == "BY" /*E*/) {
-            return BYE;
-        }
-    }
-
-    return OTHER;
-}
-
-bool kio_sieveProtocol::requestCapabilitiesAfterStartTLS() const
-{
-    // Cyrus didn't send CAPABILITIES after STARTTLS until 2.3.11, which is
-    // not standard conform, but we need to support that anyway.
-    // m_implementation looks like this 'Cyrus timsieved v2.2.12' for Cyrus btw.
-    QRegularExpression regExp(QStringLiteral("Cyrus\\stimsieved\\sv(\\d+)\\.(\\d+)\\.(\\d+)([-\\w]*)"), QRegularExpression::CaseInsensitiveOption);
-    QRegularExpressionMatch match = regExp.match(m_implementation);
-    if (match.hasMatch()) {
-        const int major = match.captured(1).toInt();
-        const int minor = match.captured(2).toInt();
-        const int patch = match.captured(3).toInt();
-        const QString vendor = match.captured(4);
-        if (major < 2 || (major == 2 && (minor < 3 || (minor == 3 && patch < 11))) || (vendor == QLatin1String("-kolab-nocaps"))) {
-            ksDebug << " kio_sieveProtocol::requestCapabilitiesAfterStartTLS : Enabling compat mode for Cyrus < 2.3.11 or Cyrus marked as \"kolab-nocaps\""
-                    << returnEndLine();
-            return true;
-        }
-    }
-    return false;
-}
-#include "sieve.moc"
diff --git a/kioslave/src/sieve/sieve.h b/kioslave/src/sieve/sieve.h
deleted file mode 100644
index c8abc73f..00000000
--- a/kioslave/src/sieve/sieve.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
-    sieve.h
-
-    SPDX-FileCopyrightText: 2001 Hamish Rodda <meddie at yoyo.cc.monash.edu.au>
-
-    SPDX-License-Identifier: GPL-2.0-only
-*/
-
-#pragma once
-
-#include <KIO/AuthInfo>
-#include <KIO/TCPSlaveBase>
-
-#include <QByteArray>
-#include <QString>
-#include <QStringList>
-
-class kio_sieveResponse
-{
-public:
-    enum responses { NONE, KEY_VAL_PAIR, ACTION, QUANTITY };
-
-    kio_sieveResponse();
-
-    const uint &getType() const;
-
-    const QByteArray &getAction() const;
-    uint getQuantity() const;
-    const QByteArray &getKey() const;
-    const QByteArray &getVal() const;
-    const QByteArray &getExtra() const;
-
-    void setQuantity(uint quantity);
-    void setAction(const QByteArray &newAction);
-    void setKey(const QByteArray &newKey);
-    void setVal(const QByteArray &newVal);
-    void setExtra(const QByteArray &newExtra);
-
-    void clear();
-
-protected:
-    uint rType;
-    uint quantity;
-    QByteArray key;
-    QByteArray val;
-    QByteArray extra;
-};
-
-class kio_sieveProtocol : public KIO::TCPSlaveBase
-{
-public:
-    enum connectionModes { NORMAL, CONNECTION_ORIENTED };
-    enum Results { OK, NO, BYE, OTHER };
-
-    kio_sieveProtocol(const QByteArray &pool_socket, const QByteArray &app_socket);
-    ~kio_sieveProtocol() override;
-
-    void mimetype(const QUrl &url) override;
-    void get(const QUrl &url) override;
-    void put(const QUrl &url, int permissions, KIO::JobFlags flags) override;
-    void del(const QUrl &url, bool isfile) override;
-
-    void listDir(const QUrl &url) override;
-    void chmod(const QUrl &url, int permissions) override;
-    virtual void urlStat(const QUrl &url);
-
-    void setHost(const QString &host, quint16 port, const QString &user, const QString &pass) override;
-    void openConnection() override;
-    void closeConnection() override;
-    // virtual void slave_status();
-
-    /**
-     * Special commands supported by this slave:
-     * 1 - activate script
-     * 2 - deactivate (all - only one active at any one time) scripts
-     * 3 - request capabilities, returned as metadata
-     */
-    void special(const QByteArray &data) override;
-    bool activate(const QUrl &url);
-    bool deactivate();
-
-protected:
-    bool connect(bool useTLSIfAvailable = true);
-    bool authenticate();
-    void disconnect(bool forcibly = false);
-    void changeCheck(const QUrl &url);
-
-    bool sendData(const QByteArray &data);
-    bool receiveData(bool waitForData = true, const QByteArray &reparse = QByteArray());
-    bool operationSuccessful();
-    int operationResult();
-
-    bool parseCapabilities(bool requestCapabilities = false);
-    bool saslInteract(void *in, KIO::AuthInfo &ai);
-
-    // IOSlave global data
-    uint m_connMode;
-
-    // Host-specific data
-    QStringList m_sasl_caps;
-    bool m_supportsTLS;
-
-    // Global server response class
-    kio_sieveResponse r;
-
-    // connection details
-    QString m_sServer;
-    QString m_sUser;
-    QString m_sPass;
-    QString m_sAuth;
-    bool m_shouldBeConnected;
-    bool m_allowUnencrypted;
-    quint16 m_port;
-
-private:
-    bool requestCapabilitiesAfterStartTLS() const;
-
-    QString m_implementation;
-};
diff --git a/kioslave/src/sieve/sieve.json b/kioslave/src/sieve/sieve.json
deleted file mode 100644
index e84da9b8..00000000
--- a/kioslave/src/sieve/sieve.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-    "KDE-KIO-Protocols": {
-        "ldap": {
-            "Icon": "view-filter",
-            "X-DocPath": "kioslave5/sieve/index.html",
-            "deleting": true,
-            "determineMimetypeFromExtension": false,
-            "input": "none",
-            "listing": [
-                "Name",
-		"Access",
-		"Type",
-		"MimeType"
-            ],
-            "output": "filesystem",
-            "protocol": "sieve",
-            "reading": true,
-            "source": true,
-            "writing": true
-        }
-    }
-}


More information about the kde-doc-english mailing list