File indexing completed on 2024-05-26 05:14:35

0001 /***************************************************************************
0002  *   SPDX-FileCopyrightText: 2006 Till Adam <adam@kde.org>                 *
0003  *                                                                         *
0004  *   SPDX-License-Identifier: LGPL-2.0-or-later                            *
0005  ***************************************************************************/
0006 #pragma once
0007 
0008 #include "connection.h"
0009 #include "exception.h"
0010 #include "global.h"
0011 
0012 #include "private/protocol_p.h"
0013 
0014 namespace Akonadi
0015 {
0016 namespace Server
0017 {
0018 class AkonadiServer;
0019 class Response;
0020 
0021 AKONADI_EXCEPTION_MAKE_INSTANCE(HandlerException);
0022 
0023 /**
0024   \defgroup akonadi_server_handler Command handlers
0025 
0026   All commands supported by the Akonadi server are implemented as sub-classes of Akonadi::Handler.
0027 */
0028 
0029 /**
0030 The handler interfaces describes an entity capable of handling an AkonadiIMAP command.*/
0031 class Handler
0032 {
0033 public:
0034     Handler() = delete;
0035     Handler(const Handler &) = delete;
0036     Handler(Handler &&) noexcept = delete;
0037     Handler &operator=(const Handler &) = delete;
0038     Handler &operator=(Handler &&) noexcept = delete;
0039 
0040     virtual ~Handler() = default;
0041 
0042     /**
0043      * Set the tag of the command to be processed, and thus of the response
0044      * generated by this handler.
0045      * @param tag The command tag, an alphanumerical string, normally.
0046      */
0047     void setTag(quint64 tag);
0048 
0049     /**
0050      * The tag of the command associated with this handler.
0051      */
0052     quint64 tag() const;
0053 
0054     void setCommand(const Protocol::CommandPtr &cmd);
0055     Protocol::CommandPtr command() const;
0056 
0057     /**
0058      * Find a handler for a command that is always allowed, like LOGOUT.
0059      * @param cmd the command string
0060      * @return an instance to the handler. The handler is deleted after @see handelLine is executed. The caller needs to delete the handler in case an exception
0061      * is thrown from handelLine.
0062      */
0063     static std::unique_ptr<Handler> findHandlerForCommandAlwaysAllowed(Protocol::Command::Type cmd, AkonadiServer &akonadi);
0064 
0065     /**
0066      * Find a handler for a command that is allowed when the client is not yet authenticated, like LOGIN.
0067      * @param cmd the command string
0068      * @return an instance to the handler. The handler is deleted after @see handelLine is executed. The caller needs to delete the handler in case an exception
0069      * is thrown from handelLine.
0070      */
0071     static std::unique_ptr<Handler> findHandlerForCommandNonAuthenticated(Protocol::Command::Type cmd, AkonadiServer &akonadi);
0072 
0073     /**
0074      * Find a handler for a command that is allowed when the client is authenticated, like LIST, FETCH, etc.
0075      * @param cmd the command string
0076      * @return an instance to the handler. The handler is deleted after @see handelLine is executed. The caller needs to delete the handler in case an exception
0077      * is thrown from handelLine.
0078      */
0079     static std::unique_ptr<Handler> findHandlerForCommandAuthenticated(Protocol::Command::Type cmd, AkonadiServer &akonadi);
0080 
0081     void setConnection(Connection *connection);
0082     Connection *connection() const;
0083     DataStore *storageBackend() const;
0084 
0085     AkonadiServer &akonadi() const;
0086 
0087     bool failureResponse(const char *response);
0088     bool failureResponse(const QByteArray &response);
0089     bool failureResponse(const QString &response);
0090 
0091     template<typename T>
0092     inline bool successResponse();
0093     template<typename T>
0094     inline bool successResponse(T &&response);
0095 
0096     template<typename T>
0097     inline void sendResponse(T &&response);
0098     template<typename T>
0099     inline void sendResponse();
0100 
0101     /**
0102      * Parse and handle the IMAP message using the streaming parser. The implementation MUST leave the trailing newline character(s) in the stream!
0103      * @return true if parsed successfully, false in case of parse failure
0104      */
0105     virtual bool parseStream() = 0;
0106 
0107     bool checkScopeConstraints(const Scope &scope, int permittedScopes);
0108 
0109 protected:
0110     Handler(AkonadiServer &akonadi);
0111 
0112 private:
0113     AkonadiServer &m_akonadi;
0114     quint64 m_tag = 0;
0115     Connection *m_connection = nullptr;
0116     bool m_sentFailureResponse = false;
0117 
0118 protected:
0119     Protocol::CommandPtr m_command;
0120 };
0121 
0122 template<typename T>
0123 inline bool Handler::successResponse()
0124 {
0125     sendResponse<T>(T{});
0126     return true;
0127 }
0128 
0129 template<typename T>
0130 inline bool Handler::successResponse(T &&response)
0131 {
0132     sendResponse<T>(std::move(response));
0133     return true;
0134 }
0135 
0136 template<typename T>
0137 inline void Handler::sendResponse()
0138 {
0139     m_connection->sendResponse<T>(T{});
0140 }
0141 
0142 template<typename T>
0143 inline void Handler::sendResponse(T &&response)
0144 {
0145     m_connection->sendResponse<T>(std::move(response));
0146 }
0147 
0148 } // namespace Server
0149 } // namespace Akonadi