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

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_RESPONSE_H
0023 #define IMAP_RESPONSE_H
0024 
0025 #include <QMap>
0026 #include <QPair>
0027 #include <QSharedPointer>
0028 #include <QStringList>
0029 #include <QTextStream>
0030 #include <QVariantList>
0031 #include <QVector>
0032 #include "Command.h"
0033 #include "../Exceptions.h"
0034 #include "Data.h"
0035 #include "ThreadingNode.h"
0036 #include "Uids.h"
0037 
0038 class QSslCertificate;
0039 class QSslError;
0040 
0041 /**
0042  * @file
0043  * @short Various data structures related to IMAP responses
0044  *
0045  * @author Jan Kundrát <jkt@flaska.net>
0046  */
0047 
0048 /** @short Namespace for IMAP interaction */
0049 namespace Imap
0050 {
0051 
0052 namespace Mailbox
0053 {
0054 class Model;
0055 class ImapTask;
0056 }
0057 
0058 class Parser;
0059 
0060 /** @short IMAP server responses
0061  *
0062  * @ref AbstractResponse is an abstact parent of all classes. Each response
0063  * that might be received from the server is a child of this one.
0064  * */
0065 namespace Responses
0066 {
0067 
0068 /** @short Result of a command */
0069 enum Kind {
0070     OK /**< @short OK */,
0071     NO /**< @short NO */,
0072     BAD /**< @short BAD */,
0073     BYE,
0074     PREAUTH,
0075     EXPUNGE,
0076     FETCH,
0077     EXISTS,
0078     RECENT,
0079     CAPABILITY,
0080     LIST,
0081     LSUB,
0082     FLAGS,
0083     SEARCH,
0084     ESEARCH, /**< @short RFC 4731 ESEARCH */
0085     STATUS,
0086     NAMESPACE,
0087     SORT,
0088     THREAD,
0089     ID,
0090     ENABLED, /**< @short RFC 5161 ENABLE */
0091     VANISHED, /**< @short RFC 5162 VANISHED (for QRESYNC) */
0092     GENURLAUTH /**< @short GENURLAUTH, RFC 4467 */
0093 }; // aren't those comments just sexy? :)
0094 
0095 /** @short Response Code */
0096 enum Code {
0097     NONE /**< @short No response code specified */,
0098     ATOM /**< @short Not recognized */,
0099     ALERT /**< @short ALERT */,
0100     BADCHARSET /**< @short BADCHARSET */,
0101     /** @short CAPABILITY.
0102      *
0103      * Yeah, it's different than the RFC3501 name for it.
0104      * Responses::Kind already defines a CAPABILITY and we aren't using
0105      * C++0x yet.
0106      *
0107      * */
0108     CAPABILITIES,
0109     PARSE /**< @short PARSE */,
0110     PERMANENTFLAGS /**< @short PERMANENTFLAGS */,
0111     READ_ONLY /**< @short READ-ONLY */,
0112     READ_WRITE /**< @short READ-WRITE */,
0113     TRYCREATE /**< @short TRYCREATE */,
0114     UIDNEXT /**< @short UIDNEXT */,
0115     UIDVALIDITY /**< @short UIDVALIDITY */,
0116     UNSEEN /**< @short UNSEEN */,
0117 
0118     // obsolete from RFC 2060
0119     NEWNAME /**< Obsolete NEWNAME from RFC 2060 */,
0120 
0121     // RFC 2221
0122     REFERRAL /**< REFERRAL from RFC 2221 */,
0123 
0124     // RFC 3516
0125     UNKNOWN_CTE /**< UNKNOWN-CTE from RFC 3516 */,
0126 
0127     // RFC 4315
0128     UIDNOTSTICKY /**< UIDNOTSTICKY from RFC 4315 */,
0129     APPENDUID /**< APPENDUID from RFC 4315 */,
0130     COPYUID /**< COPYUID from RFC 4315 */,
0131 
0132     // RFC 4467
0133     URLMECH /**< URLMECH from RFC 4467 */,
0134 
0135     // RFC 4469
0136     TOOBIG /**< RFC 4469's TOOBIG */,
0137     BADURL /**< BADURL from RFC 4469 */,
0138 
0139     // RFC 4551
0140     HIGHESTMODSEQ /**< HIGHESTMODSEQ from RFC 4451 */,
0141     NOMODSEQ /**< NOMODSEQ from RFC 4551 */,
0142     MODIFIED /**< MODIFIED from RFC 4551 */,
0143 
0144     // RFC 4978
0145     COMPRESSIONACTIVE /**< COMPRESSIONACTIVE from RFC 4978 */,
0146 
0147     // RFC 5162
0148     CLOSED /**< CLOSED from the QRESYNC RFC 5162 */,
0149 
0150     // RFC 5182
0151     NOTSAVED /**< NOTSAVED from RFC 5182 */,
0152 
0153     // RFC 5255
0154     BADCOMPARATOR /**< BADCOMPARATOR from RFC 5255 */,
0155 
0156     // RFC 5257
0157     ANNOTATE /**< ANNOTATE from RFC 5257 */,
0158     ANNOTATIONS /**< ANNOTATIONS from RFC 5257 */,
0159 
0160     // RFC 5259
0161     TEMPFAIL /**< TEMPFAIL from RFC 5259 */,
0162     MAXCONVERTMESSAGES /**< MAXCONVERTMESSAGES from RFC 5259 */,
0163     MAXCONVERTPARTS /**< MAXCONVERTPARTS from RFC 5259 */,
0164 
0165     // RFC 5267
0166     NOUPDATE /**< NOUPDATE from RFC 5267 */,
0167 
0168     // RFC 5464
0169     METADATA /**< METADATA from RFC 5464 */,
0170 
0171     // RFC 5465
0172     NOTIFICATIONOVERFLOW /**< NOTIFICATIONOVERFLOW from RFC 5465 */,
0173     BADEVENT /**< BADEVENT from RFC 5465 */,
0174 
0175     // RFC 5466
0176     UNDEFINED_FILTER /**< UNDEFINED-FILTER from RFC 5466 */,
0177 
0178     // RFC5530
0179     UNAVAILABLE /**< UNAVAILABLE from RFC 5530 */,
0180     AUTHENTICATIONFAILED /**< AUTHENTICATIONFAILED from RFC 5530 */,
0181     AUTHORIZATIONFAILED /**< AUTHORIZATIONFAILED from RFC 5530 */,
0182     EXPIRED /**< EXPIRED from RFC 5530 */,
0183     PRIVACYREQUIRED /**< PRIVACYREQUIRED from RFC 5530 */,
0184     CONTACTADMIN /**< CONTACTADMIN from RFC 5530 */,
0185     NOPERM /**< NOPERM from RFC 5530 */,
0186     INUSE /**< INUSE from RFC 5530 */,
0187     EXPUNGEISSUED /**< EXPUNGEISSUED from RFC 5530 */,
0188     CORRUPTION /**< CORRUPTION from RFC 5530 */,
0189     SERVERBUG /**< SERVERBUG from RFC 5530 */,
0190     CLIENTBUG /**< CLIENTBUG from RFC 5530 */,
0191     CANNOT /**< CANNOT from RFC 5530 */,
0192     LIMIT /**< LIMIT from RFC 5530 */,
0193     OVERQUOTA /**< OVERQUOTA from RFC 5530 */,
0194     ALREADYEXISTS /**< ALREADYEXISTS from RFC 5530 */,
0195     NONEXISTENT /**< NONEXISTENT from RFC 5530 */,
0196 
0197     // draft-imap-sendmail by yours truly
0198     POLICYDENIED,
0199     SUBMISSIONRACE
0200 
0201 }; // luvly comments, huh? :)
0202 
0203 /** @short Parent class for all server responses */
0204 class AbstractResponse
0205 {
0206 public:
0207     AbstractResponse() {}
0208     virtual ~AbstractResponse();
0209     /** @short Helper for operator<<() */
0210     virtual QTextStream &dump(QTextStream &) const = 0;
0211     /** @short Helper for operator==() */
0212     virtual bool eq(const AbstractResponse &other) const = 0;
0213     /** @short Helper for Imap::Mailbox::MailboxModel to prevent ugly
0214      * dynamic_cast<>s */
0215     virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const = 0;
0216     virtual bool plug(Imap::Mailbox::ImapTask *task) const = 0;
0217 };
0218 
0219 /** @short Structure storing OK/NO/BAD/PREAUTH/BYE responses */
0220 class State : public AbstractResponse
0221 {
0222 public:
0223     /** @short Tag name or QString::null if untagged */
0224     QByteArray tag;
0225 
0226     /** @short Kind of response
0227      *
0228      * A tagged status response might be either OK, NO or BAD.
0229      * Untagged status response might be either te same as tagged or BYE or
0230      * PREAUTH.
0231      * */
0232     Kind kind;
0233 
0234     /** @short Textual information embedded in the response
0235      *
0236      * While this information might be handy for correct understanding of
0237      * what happens at ther server, its value is not standardized so the
0238      * meaning is usually either duplicate to what's already said elsewhere
0239      * or only a hint to the user. Nevertheless, we decode and store it.
0240      * */
0241     QString message;
0242 
0243     /** @short Kind of optional Response Code
0244      *
0245      * For each supported value, type of ResponseCodeData stored in the
0246      * respCodeData is defined as follows:
0247      *
0248      *  ALERT, PARSE, READ_ONLY, READ_WRITE, TRYCREATE:
0249      *      Nothing else should be included, ie. void
0250      *
0251      *  UIDNEXT, UIDVALIDITY, UNSEEN:
0252      *      Only number, ie. unsigned int
0253      *
0254      *  BADCHARSET, PERMANENTFLAGS:
0255      *      List of strings, ie. QStringList
0256      *
0257      *  default:
0258      *      Any data, ie. QString
0259      * */
0260     Code respCode;
0261 
0262     /** @short Response Code Data
0263      *
0264      * Format is explained in the respCode documentation.
0265      * We have to use pointer indirection because virtual methods wouldn't
0266      * work otherwise.
0267      * */
0268     QSharedPointer<AbstractData> respCodeData;
0269 
0270     /** @short Default constructor
0271      *
0272      * No error checking takes place, we assume _respCodeData's type
0273      * actually corresponds to all invariants we declare as per respCode's
0274      * documentation.
0275      * */
0276     State(const QByteArray &tag, const Kind kind, const QString &message, const Code respCode, const QSharedPointer<AbstractData> respCodeData):
0277         tag(tag), kind(kind), message(message), respCode(respCode), respCodeData(respCodeData) {}
0278 
0279     /** @short "Smart" constructor that parses a response out of a QByteArray */
0280     State(const QByteArray &tag, const Kind kind, const QByteArray &line, int &start);
0281 
0282     /** @short Default destructor that makes containers and QtTest happy */
0283     State(): respCode(NONE) {}
0284 
0285     /** @short helper for operator<<( QTextStream& ) */
0286     QTextStream &dump(QTextStream &s) const override;
0287     bool eq(const AbstractResponse &other) const override;
0288     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0289     bool plug(Imap::Mailbox::ImapTask *task) const override;
0290 };
0291 
0292 /** @short Structure storing a CAPABILITY untagged response */
0293 class Capability : public AbstractResponse
0294 {
0295 public:
0296     /** @short List of capabilities */
0297     QStringList capabilities;
0298     Capability(const QStringList &capabilities): capabilities(capabilities) {}
0299     QTextStream &dump(QTextStream &s) const override;
0300     bool eq(const AbstractResponse &other) const override;
0301     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0302     bool plug(Imap::Mailbox::ImapTask *task) const override;
0303 };
0304 
0305 /** @short Structure for EXISTS/EXPUNGE/RECENT responses */
0306 class NumberResponse : public AbstractResponse
0307 {
0308 public:
0309     Kind kind;
0310     /** @short Number that we're storing */
0311     uint number;
0312     NumberResponse(const Kind kind, const uint number);
0313     QTextStream &dump(QTextStream &s) const override;
0314     bool eq(const AbstractResponse &other) const override;
0315     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0316     bool plug(Imap::Mailbox::ImapTask *task) const override;
0317 };
0318 
0319 /** @short Structure storing a LIST untagged response */
0320 class List : public AbstractResponse
0321 {
0322 public:
0323     /** @short LIST or LSUB */
0324     Kind kind;
0325     /** @short Flags for this particular mailbox */
0326     QStringList flags;
0327     /** @short Hierarchy separator
0328      *
0329      * QString::null in case original response containded NIL
0330      * */
0331     QString separator;
0332     /** @short Mailbox name */
0333     QString mailbox;
0334 
0335     /** @short Extended LIST data (mbox-list-extended from RFC5258) */
0336     QMap<QByteArray, QVariant> extendedData;
0337 
0338     /** @short Parse line and construct List object from it */
0339     List(const Kind kind, const QByteArray &line, int &start);
0340     List(const Kind kind, const QStringList &flags, const QString &separator, const QString &mailbox,
0341          const QMap<QByteArray, QVariant> &extendedData):
0342         kind(kind), flags(flags), separator(separator), mailbox(mailbox), extendedData(extendedData) {}
0343     QTextStream &dump(QTextStream &s) const override;
0344     bool eq(const AbstractResponse &other) const override;
0345     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0346     bool plug(Imap::Mailbox::ImapTask *task) const override;
0347 };
0348 
0349 struct NamespaceData {
0350     QString prefix;
0351     QString separator;
0352     NamespaceData(const QString &prefix, const QString &separator): prefix(prefix), separator(separator) {};
0353     bool operator==(const NamespaceData &other) const;
0354     bool operator!=(const NamespaceData &other) const;
0355     static QList<NamespaceData> listFromLine(const QByteArray &line, int &start);
0356 };
0357 
0358 /** @short Structure storing a NAMESPACE untagged response */
0359 class Namespace : public AbstractResponse
0360 {
0361 public:
0362     QList<NamespaceData> personal, users, other;
0363     /** @short Parse line and construct List object from it */
0364     Namespace(const QByteArray &line, int &start);
0365     Namespace(const QList<NamespaceData> &personal, const QList<NamespaceData> &users,
0366               const QList<NamespaceData> &other):
0367         personal(personal), users(users), other(other) {};
0368     QTextStream &dump(QTextStream &s) const override;
0369     bool eq(const AbstractResponse &other) const override;
0370     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0371     bool plug(Imap::Mailbox::ImapTask *task) const override;
0372 };
0373 
0374 
0375 /** @short Structure storing a FLAGS untagged response */
0376 class Flags : public AbstractResponse
0377 {
0378 public:
0379     /** @short List of flags */
0380     QStringList flags;
0381     Flags(const QStringList &flags) : flags(flags) {};
0382     Flags(const QByteArray &line, int &start);
0383     QTextStream &dump(QTextStream &s) const override;
0384     bool eq(const AbstractResponse &other) const override;
0385     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0386     bool plug(Imap::Mailbox::ImapTask *task) const override;
0387 };
0388 
0389 /** @short Structure storing a SEARCH untagged response */
0390 class Search : public AbstractResponse
0391 {
0392 public:
0393     /** @short List of matching messages */
0394     Uids items;
0395     Search(const QByteArray &line, int &start);
0396     Search(const Uids &items) : items(items) {};
0397     QTextStream &dump(QTextStream &s) const override;
0398     bool eq(const AbstractResponse &other) const override;
0399     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0400     bool plug(Imap::Mailbox::ImapTask *task) const override;
0401 };
0402 
0403 /** @short Structure storing an ESEARCH untagged response */
0404 class ESearch : public AbstractResponse
0405 {
0406 public:
0407     /** @short Is the response given in UIDs, or just in sequence numbers */
0408     typedef enum {
0409         SEQUENCE, /**< @short In sequence numbers */
0410         UIDS /**< @short In UIDs */
0411     } SequencesOrUids;
0412 
0413     /** @short Convenience typedef for the received data of the list type */
0414     typedef QVector<QPair<QByteArray, Uids>> ListData_t;
0415 
0416     /** @short Represent one item to be added/removed by an incremental SEARCH/SORT response */
0417     struct ContextIncrementalItem {
0418 
0419         /** @short Is this incremental update record about adding an item, or removing it?
0420 
0421         These correspond to RFC 5267's ADDTO and REMOVEFROM identifiers.
0422         */
0423         typedef enum {
0424             ADDTO, /**< ADDTO, adding items to the search/sort criteria */
0425             REMOVEFROM /**< REMOVEFROM, removing items from the list of matches */
0426         } Modification;
0427 
0428         /** @short Type of modification */
0429         Modification modification;
0430 
0431         /** @short Offset at which the modification shall be performed */
0432         uint offset;
0433 
0434         /** @short Sequence of UIDs to apply */
0435         Uids uids;
0436 
0437         ContextIncrementalItem(const Modification modification, const uint offset, const Uids &uids):
0438             modification(modification), offset(offset), uids(uids) {}
0439 
0440         bool operator==(const ContextIncrementalItem &other) const {
0441             return modification == other.modification && offset == other.offset && uids == other.uids;
0442         }
0443     };
0444 
0445     typedef QList<ContextIncrementalItem> IncrementalContextData_t;
0446 
0447     /** @short The tag of the command which requested in this operation */
0448     QByteArray tag;
0449 
0450     /** @short Are the numbers given in UIDs, or as sequence numbers? */
0451     SequencesOrUids seqOrUids;
0452 
0453     /** @short The received data: list of numbers */
0454     ListData_t listData;
0455 
0456     /** @short The received data: incremental updates to SEARCH/SORT according to RFC 5267 */
0457     IncrementalContextData_t incrementalContextData;
0458 
0459     /** @short Incremental threading information along its identifier and the preceding thread root in an ESEARCH response */
0460     struct IncrementalThreadingItem_t {
0461         /** @short UID of the previous thread root's item or 0 if there's no previous item */
0462         uint previousThreadRoot;
0463 
0464         /** @short A complete subthread */
0465         QVector<ThreadingNode> thread;
0466 
0467         IncrementalThreadingItem_t(const uint previousThreadRoot, const QVector<ThreadingNode> &thread):
0468             previousThreadRoot(previousThreadRoot), thread(thread) {}
0469 
0470         bool operator==(const IncrementalThreadingItem_t &other) const {
0471             return previousThreadRoot == other.previousThreadRoot && thread == other.thread;
0472         }
0473     };
0474 
0475     /** @short Typedef for all threading data sent over ESEARCH */
0476     typedef QList<IncrementalThreadingItem_t> IncrementalThreadingData_t;
0477 
0478     /** @short The threading information, draft-imap-incthread */
0479     IncrementalThreadingData_t incThreadData;
0480 
0481     // Other forms of returned data are quite explicitly not supported.
0482 
0483     ESearch(const QByteArray &line, int &start);
0484     ESearch(const QByteArray &tag, const SequencesOrUids seqOrUids, const ListData_t &listData) :
0485         tag(tag), seqOrUids(seqOrUids), listData(listData) {}
0486     ESearch(const QByteArray &tag, const SequencesOrUids seqOrUids, const IncrementalContextData_t &incrementalContextData) :
0487         tag(tag), seqOrUids(seqOrUids), incrementalContextData(incrementalContextData) {}
0488     ESearch(const QByteArray &tag, const SequencesOrUids seqOrUids, const IncrementalThreadingData_t &incThreadData):
0489         tag(tag), seqOrUids(seqOrUids), incThreadData(incThreadData) {}
0490     QTextStream &dump(QTextStream &stream) const override;
0491     bool eq(const AbstractResponse &other) const override;
0492     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0493     bool plug(Imap::Mailbox::ImapTask *task) const override;
0494 };
0495 
0496 /** @short Structure storing a STATUS untagged response */
0497 class Status : public AbstractResponse
0498 {
0499 public:
0500     /** @short Indentifies type of status data */
0501     enum StateKind {
0502         MESSAGES,
0503         RECENT,
0504         UIDNEXT,
0505         UIDVALIDITY,
0506         UNSEEN
0507     };
0508 
0509     typedef QMap<StateKind,uint> stateDataType;
0510 
0511     /** @short Mailbox name */
0512     QString mailbox;
0513     /** @short Associative array of states */
0514     stateDataType states;
0515 
0516     Status(const QString &mailbox, const stateDataType &states) :
0517         mailbox(mailbox), states(states) {};
0518     Status(const QByteArray &line, int &start);
0519     QTextStream &dump(QTextStream &s) const override;
0520     bool eq(const AbstractResponse &other) const override;
0521     static StateKind stateKindFromStr(QString s);
0522     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0523     bool plug(Imap::Mailbox::ImapTask *task) const override;
0524 };
0525 
0526 /** @short FETCH response */
0527 class Fetch : public AbstractResponse
0528 {
0529 public:
0530     typedef QMap<QByteArray,QSharedPointer<AbstractData> > dataType;
0531 
0532     /** @short Sequence number of message that we're working with */
0533     uint number;
0534 
0535     /** @short Fetched items */
0536     dataType data;
0537 
0538     Fetch(const uint number, const QByteArray &line, int &start);
0539     Fetch(const uint number, const dataType &data);
0540     QTextStream &dump(QTextStream &s) const override;
0541     bool eq(const AbstractResponse &other) const override;
0542     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0543     bool plug(Imap::Mailbox::ImapTask *task) const override;
0544 private:
0545     static QDateTime dateify(QByteArray str, const QByteArray &line, const int start);
0546 };
0547 
0548 /** @short Structure storing a SORT untagged response */
0549 class Sort : public AbstractResponse
0550 {
0551 public:
0552     /** @short List of sequence/UID numbers as returned by the server */
0553     Uids numbers;
0554     Sort(const QByteArray &line, int &start);
0555     Sort(const Uids &items): numbers(items) {}
0556     QTextStream &dump(QTextStream &s) const override;
0557     bool eq(const AbstractResponse &other) const override;
0558     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0559     bool plug(Imap::Mailbox::ImapTask *task) const override;
0560 };
0561 
0562 /** @short Structure storing a THREAD untagged response */
0563 class Thread : public AbstractResponse
0564 {
0565 public:
0566     /** @short List of "top-level" messages */
0567     QVector<ThreadingNode> rootItems;
0568     Thread(const QByteArray &line, int &start);
0569     Thread(const QVector<ThreadingNode> &items): rootItems(items) {}
0570     QTextStream &dump(QTextStream &s) const override;
0571     bool eq(const AbstractResponse &other) const override;
0572     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0573     bool plug(Imap::Mailbox::ImapTask *task) const override;
0574 };
0575 
0576 /** @short Structure storing the result of the ID command */
0577 class Id : public AbstractResponse
0578 {
0579 public:
0580     /** @short List of sequence/UID numbers as returned by the server */
0581     QMap<QByteArray,QByteArray> data;
0582     Id(const QByteArray &line, int &start);
0583     Id(const QMap<QByteArray,QByteArray> &items): data(items) {}
0584     QTextStream &dump(QTextStream &s) const override;
0585     bool eq(const AbstractResponse &other) const override;
0586     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0587     bool plug(Imap::Mailbox::ImapTask *task) const override;
0588 };
0589 
0590 /** @short Structure storing each enabled extension */
0591 class Enabled: public AbstractResponse
0592 {
0593 public:
0594     QList<QByteArray> extensions;
0595     Enabled(const QByteArray &line, int &start);
0596     Enabled(const QList<QByteArray> &extensions): extensions(extensions) {}
0597     QTextStream &dump(QTextStream &s) const override;
0598     bool eq(const AbstractResponse &other) const override;
0599     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0600     bool plug(Imap::Mailbox::ImapTask *task) const override;
0601 };
0602 
0603 /** @short VANISHED contains information about UIDs of removed messages */
0604 class Vanished: public AbstractResponse
0605 {
0606 public:
0607     typedef enum {EARLIER, NOT_EARLIER} EarlierOrNow;
0608     EarlierOrNow earlier;
0609     Uids uids;
0610     Vanished(const QByteArray &line, int &start);
0611     Vanished(EarlierOrNow earlier, const Uids &uids): earlier(earlier), uids(uids) {}
0612     QTextStream &dump(QTextStream &s) const override;
0613     bool eq(const AbstractResponse &other) const override;
0614     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0615     bool plug(Imap::Mailbox::ImapTask *task) const override;
0616 };
0617 
0618 /** @short The GENURLAUTH response */
0619 class GenUrlAuth: public AbstractResponse
0620 {
0621 public:
0622     QString url;
0623     GenUrlAuth(const QByteArray &line, int &start);
0624     GenUrlAuth(const QString &url): url(url) {}
0625     QTextStream &dump(QTextStream &s) const override;
0626     bool eq(const AbstractResponse &other) const override;
0627     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0628     bool plug(Imap::Mailbox::ImapTask *task) const override;
0629 };
0630 
0631 /** @short A fake response for passing along the SSL state */
0632 class SocketEncryptedResponse : public AbstractResponse
0633 {
0634 public:
0635     QList<QSslCertificate> sslChain;
0636     QList<QSslError> sslErrors;
0637     /** @short List of sequence/UID numbers as returned by the server */
0638     SocketEncryptedResponse(const QList<QSslCertificate> &certificateChain, const QList<QSslError> &sslErrors);
0639     QTextStream &dump(QTextStream &s) const override;
0640     bool eq(const AbstractResponse &other) const override;
0641     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0642     bool plug(Imap::Mailbox::ImapTask *task) const override;
0643 };
0644 
0645 /** @short A fake response saying that the socket got disconnected */
0646 class SocketDisconnectedResponse : public AbstractResponse
0647 {
0648 public:
0649     QString message;
0650     explicit SocketDisconnectedResponse(const QString &message): message(message) {}
0651     QTextStream &dump(QTextStream &s) const override;
0652     bool eq(const AbstractResponse &other) const override;
0653     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0654     bool plug(Imap::Mailbox::ImapTask *task) const override;
0655 };
0656 
0657 /** @short A fake response about a parsing error */
0658 class ParseErrorResponse : public AbstractResponse
0659 {
0660 public:
0661     QString message;
0662     QString exceptionClass;
0663     QByteArray line;
0664     int offset;
0665     explicit ParseErrorResponse(const ImapException &e);
0666     QTextStream &dump(QTextStream &s) const override;
0667     bool eq(const AbstractResponse &other) const override;
0668     void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const override;
0669     bool plug(Imap::Mailbox::ImapTask *task) const override;
0670 };
0671 
0672 QTextStream &operator<<(QTextStream &stream, const Code &r);
0673 QTextStream &operator<<(QTextStream &stream, const Kind &res);
0674 QTextStream &operator<<(QTextStream &stream, const Status::StateKind &kind);
0675 QTextStream &operator<<(QTextStream &stream, const AbstractResponse &res);
0676 QTextStream &operator<<(QTextStream &stream, const NamespaceData &res);
0677 
0678 inline bool operator==(const AbstractResponse &first, const AbstractResponse &other)
0679 {
0680     return first.eq(other);
0681 }
0682 
0683 inline bool operator!=(const AbstractResponse &first, const AbstractResponse &other)
0684 {
0685     return !first.eq(other);
0686 }
0687 
0688 /** @short Build Responses::Kind from textual value */
0689 Kind kindFromString(QByteArray str);
0690 
0691 }
0692 
0693 }
0694 
0695 #endif // IMAP_RESPONSE_H