File indexing completed on 2024-09-22 04:52:48

0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
0002 
0003    This file is part of the Trojita Qt IMAP e-mail client,
0004    http://trojita.flaska.net/
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU General Public License as
0008    published by the Free Software Foundation; either version 2 of
0009    the License or (at your option) version 3 or any later version
0010    accepted by the membership of KDE e.V. (or its successor approved
0011    by the membership of KDE e.V.), which shall act as a proxy
0012    defined in Section 14 of version 3 of the license.
0013 
0014    This program is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017    GNU General Public License for more details.
0018 
0019    You should have received a copy of the GNU General Public License
0020    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 #ifndef IMAP_COMMAND_H
0023 #define IMAP_COMMAND_H
0024 
0025 #include <QDateTime>
0026 #include <QList>
0027 #include <QTextStream>
0028 
0029 /** @short Namespace for IMAP interaction */
0030 namespace Imap
0031 {
0032 
0033 // Forward required for friend declaration
0034 class Parser;
0035 class CommandResult;
0036 
0037 QTextStream &operator<<(QTextStream &stream, const CommandResult &r);
0038 
0039 /** @short Namespace holding all supported IMAP commands and various helpers */
0040 namespace Commands
0041 {
0042 
0043 /** Enumeration that specifies required method of transmission of this string */
0044 enum TokenType {
0045     ATOM /**< Don't use any extra encoding, just send it directly, perhaps because it's already encoded */,
0046     QUOTED_STRING /**< Transmit using double-quotes */,
0047     LITERAL /**< Don't bother with checking this data, always use literal form */,
0048     IDLE, /**< Special case: IDLE command */
0049     IDLE_DONE, /**< Special case: the DONE for finalizing the IDLE command */
0050     STARTTLS, /**< Special case: STARTTLS */
0051     COMPRESS_DEFLATE, /**< Special case: COMPRESS DEFLATE */
0052     ATOM_NO_SPACE_AROUND /**< Do not add extra space either before or after this part */
0053 };
0054 
0055 /** @short Checks if we can use a quoted-string form for transmitting this string.
0056  *
0057  * We have to use literals for transmitting strings that are either too
0058  * long (as that'd cause problems with servers using too small line buffers),
0059  * contains CR, LF, zero byte or any characters outside of 7-bit ASCII range.
0060  */
0061 TokenType howToTransmit(const QByteArray &str);
0062 
0063 /** @short A part of the actual command and information on how to send it
0064  *
0065  * In IMAP, each command consists of several chunks of data to be sent over the wire. There are different
0066  * rules on how to transfer them -- some data can be just flushed to the wire as byte arrays without any
0067  * further processing, but there are places where the transmission just cannot happen "right now". An
0068  * example of this are huge blobs of binary data which need to be transmitted as synchronizing literals.
0069  * These literals need to wait for the server's explicit OK to send them, and the client is forbidden to
0070  * send them ahead.
0071  *
0072  * This class therefore encapsulates the "part of command" along with enough information on how it should
0073  * be transferred.
0074  *
0075  */
0076 class PartOfCommand
0077 {
0078     TokenType kind; /**< What encoding to use for this item */
0079     QByteArray text; /**< Actual text to send */
0080     bool numberSent;
0081 
0082     friend QTextStream &operator<<(QTextStream &stream, const PartOfCommand &c);
0083     friend class ::Imap::Parser;
0084 
0085 public:
0086     /** Default constructor */
0087     PartOfCommand(const TokenType kind, const QByteArray &text): kind(kind), text(text), numberSent(false) {}
0088     /** Constructor that guesses correct type for passed string */
0089     PartOfCommand(const QByteArray &text): kind(howToTransmit(text)), text(text), numberSent(false) {}
0090 };
0091 
0092 /** @short Abstract class for specifying what command to execute */
0093 class Command
0094 {
0095     friend QTextStream &operator<<(QTextStream &stream, const Command &c);
0096     friend class ::Imap::Parser;
0097     QList<PartOfCommand> cmds;
0098     int currentPart;
0099 public:
0100     Command &operator<<(const PartOfCommand &part) { cmds << part; return *this; }
0101     Command &operator<<(const QByteArray &text) { cmds << PartOfCommand(text); return *this; }
0102     Command(): currentPart(0) {}
0103     explicit Command(const QByteArray &name): currentPart(0) { cmds << PartOfCommand(ATOM, name); }
0104     void addTag(const QByteArray &tag) { cmds.insert(0, PartOfCommand(ATOM, tag)); }
0105 };
0106 
0107 /** @short Used for dumping a command to debug stream */
0108 QTextStream &operator<<(QTextStream &stream, const Command &cmd);
0109 
0110 }
0111 }
0112 #endif /* IMAP_COMMAND_H */