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