1 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net> 2 3 This file is part of the Trojita Qt IMAP e-mail client, 4 http://trojita.flaska.net/ 5 6 This program is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License as 8 published by the Free Software Foundation; either version 2 of 9 the License or (at your option) version 3 or any later version 10 accepted by the membership of KDE e.V. (or its successor approved 11 by the membership of KDE e.V.), which shall act as a proxy 12 defined in Section 14 of version 3 of the license. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 #ifndef IMAP_RESPONSE_H 23 #define IMAP_RESPONSE_H 24 25 #include <QMap> 26 #include <QPair> 27 #include <QSharedPointer> 28 #include <QStringList> 29 #include <QTextStream> 30 #include <QVariantList> 31 #include <QVector> 32 #include "Command.h" 33 #include "../Exceptions.h" 34 #include "Data.h" 35 #include "ThreadingNode.h" 36 #include "Uids.h" 37 38 #ifdef _MSC_VER 39 // Disable warnings about throw/nothrow 40 #pragma warning(disable: 4290) 41 #endif 42 43 class QSslCertificate; 44 class QSslError; 45 46 /** 47 * @file 48 * @short Various data structures related to IMAP responses 49 * 50 * @author Jan Kundrát <jkt@flaska.net> 51 */ 52 53 /** @short Namespace for IMAP interaction */ 54 namespace Imap 55 { 56 57 namespace Mailbox 58 { 59 class Model; 60 class ImapTask; 61 } 62 63 class Parser; 64 65 /** @short IMAP server responses 66 * 67 * @ref AbstractResponse is an abstact parent of all classes. Each response 68 * that might be received from the server is a child of this one. 69 * */ 70 namespace Responses 71 { 72 73 /** @short Result of a command */ 74 enum Kind { 75 OK /**< @short OK */, 76 NO /**< @short NO */, 77 BAD /**< @short BAD */, 78 BYE, 79 PREAUTH, 80 EXPUNGE, 81 FETCH, 82 EXISTS, 83 RECENT, 84 CAPABILITY, 85 LIST, 86 LSUB, 87 FLAGS, 88 SEARCH, 89 ESEARCH, /**< @short RFC 4731 ESEARCH */ 90 STATUS, 91 NAMESPACE, 92 SORT, 93 THREAD, 94 ID, 95 ENABLED, /**< @short RFC 5161 ENABLE */ 96 VANISHED, /**< @short RFC 5162 VANISHED (for QRESYNC) */ 97 GENURLAUTH /**< @short GENURLAUTH, RFC 4467 */ 98 }; // aren't those comments just sexy? :) 99 100 /** @short Response Code */ 101 enum Code { 102 NONE /**< @short No response code specified */, 103 ATOM /**< @short Not recognized */, 104 ALERT /**< @short ALERT */, 105 BADCHARSET /**< @short BADCHARSET */, 106 /** @short CAPABILITY. 107 * 108 * Yeah, it's different than the RFC3501 name for it. 109 * Responses::Kind already defines a CAPABILITY and we aren't using 110 * C++0x yet. 111 * 112 * */ 113 CAPABILITIES, 114 PARSE /**< @short PARSE */, 115 PERMANENTFLAGS /**< @short PERMANENTFLAGS */, 116 READ_ONLY /**< @short READ-ONLY */, 117 READ_WRITE /**< @short READ-WRITE */, 118 TRYCREATE /**< @short TRYCREATE */, 119 UIDNEXT /**< @short UIDNEXT */, 120 UIDVALIDITY /**< @short UIDVALIDITY */, 121 UNSEEN /**< @short UNSEEN */, 122 123 // obsolete from RFC 2060 124 NEWNAME /**< Obsolete NEWNAME from RFC 2060 */, 125 126 // RFC 2221 127 REFERRAL /**< REFERRAL from RFC 2221 */, 128 129 // RFC 3516 130 UNKNOWN_CTE /**< UNKNOWN-CTE from RFC 3516 */, 131 132 // RFC 4315 133 UIDNOTSTICKY /**< UIDNOTSTICKY from RFC 4315 */, 134 APPENDUID /**< APPENDUID from RFC 4315 */, 135 COPYUID /**< COPYUID from RFC 4315 */, 136 137 // RFC 4467 138 URLMECH /**< URLMECH from RFC 4467 */, 139 140 // RFC 4469 141 TOOBIG /**< RFC 4469's TOOBIG */, 142 BADURL /**< BADURL from RFC 4469 */, 143 144 // RFC 4551 145 HIGHESTMODSEQ /**< HIGHESTMODSEQ from RFC 4451 */, 146 NOMODSEQ /**< NOMODSEQ from RFC 4551 */, 147 MODIFIED /**< MODIFIED from RFC 4551 */, 148 149 // RFC 4978 150 COMPRESSIONACTIVE /**< COMPRESSIONACTIVE from RFC 4978 */, 151 152 // RFC 5162 153 CLOSED /**< CLOSED from the QRESYNC RFC 5162 */, 154 155 // RFC 5182 156 NOTSAVED /**< NOTSAVED from RFC 5182 */, 157 158 // RFC 5255 159 BADCOMPARATOR /**< BADCOMPARATOR from RFC 5255 */, 160 161 // RFC 5257 162 ANNOTATE /**< ANNOTATE from RFC 5257 */, 163 ANNOTATIONS /**< ANNOTATIONS from RFC 5257 */, 164 165 // RFC 5259 166 TEMPFAIL /**< TEMPFAIL from RFC 5259 */, 167 MAXCONVERTMESSAGES /**< MAXCONVERTMESSAGES from RFC 5259 */, 168 MAXCONVERTPARTS /**< MAXCONVERTPARTS from RFC 5259 */, 169 170 // RFC 5267 171 NOUPDATE /**< NOUPDATE from RFC 5267 */, 172 173 // RFC 5464 174 METADATA /**< METADATA from RFC 5464 */, 175 176 // RFC 5465 177 NOTIFICATIONOVERFLOW /**< NOTIFICATIONOVERFLOW from RFC 5465 */, 178 BADEVENT /**< BADEVENT from RFC 5465 */, 179 180 // RFC 5466 181 UNDEFINED_FILTER /**< UNDEFINED-FILTER from RFC 5466 */, 182 183 // RFC5530 184 UNAVAILABLE /**< UNAVAILABLE from RFC 5530 */, 185 AUTHENTICATIONFAILED /**< AUTHENTICATIONFAILED from RFC 5530 */, 186 AUTHORIZATIONFAILED /**< AUTHORIZATIONFAILED from RFC 5530 */, 187 EXPIRED /**< EXPIRED from RFC 5530 */, 188 PRIVACYREQUIRED /**< PRIVACYREQUIRED from RFC 5530 */, 189 CONTACTADMIN /**< CONTACTADMIN from RFC 5530 */, 190 NOPERM /**< NOPERM from RFC 5530 */, 191 INUSE /**< INUSE from RFC 5530 */, 192 EXPUNGEISSUED /**< EXPUNGEISSUED from RFC 5530 */, 193 CORRUPTION /**< CORRUPTION from RFC 5530 */, 194 SERVERBUG /**< SERVERBUG from RFC 5530 */, 195 CLIENTBUG /**< CLIENTBUG from RFC 5530 */, 196 CANNOT /**< CANNOT from RFC 5530 */, 197 LIMIT /**< LIMIT from RFC 5530 */, 198 OVERQUOTA /**< OVERQUOTA from RFC 5530 */, 199 ALREADYEXISTS /**< ALREADYEXISTS from RFC 5530 */, 200 NONEXISTENT /**< NONEXISTENT from RFC 5530 */, 201 202 // draft-imap-sendmail by yours truly 203 POLICYDENIED, 204 SUBMISSIONRACE 205 206 }; // luvly comments, huh? :) 207 208 /** @short Parent class for all server responses */ 209 class AbstractResponse 210 { 211 public: AbstractResponse()212 AbstractResponse() {} 213 virtual ~AbstractResponse(); 214 /** @short Helper for operator<<() */ 215 virtual QTextStream &dump(QTextStream &) const = 0; 216 /** @short Helper for operator==() */ 217 virtual bool eq(const AbstractResponse &other) const = 0; 218 /** @short Helper for Imap::Mailbox::MailboxModel to prevent ugly 219 * dynamic_cast<>s */ 220 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const = 0; 221 virtual bool plug(Imap::Mailbox::ImapTask *task) const = 0; 222 }; 223 224 /** @short Structure storing OK/NO/BAD/PREAUTH/BYE responses */ 225 class State : public AbstractResponse 226 { 227 public: 228 /** @short Tag name or QString::null if untagged */ 229 QByteArray tag; 230 231 /** @short Kind of response 232 * 233 * A tagged status response might be either OK, NO or BAD. 234 * Untagged status response might be either te same as tagged or BYE or 235 * PREAUTH. 236 * */ 237 Kind kind; 238 239 /** @short Textual information embedded in the response 240 * 241 * While this information might be handy for correct understanding of 242 * what happens at ther server, its value is not standardized so the 243 * meaning is usually either duplicate to what's already said elsewhere 244 * or only a hint to the user. Nevertheless, we decode and store it. 245 * */ 246 QString message; 247 248 /** @short Kind of optional Response Code 249 * 250 * For each supported value, type of ResponseCodeData stored in the 251 * respCodeData is defined as follows: 252 * 253 * ALERT, PARSE, READ_ONLY, READ_WRITE, TRYCREATE: 254 * Nothing else should be included, ie. void 255 * 256 * UIDNEXT, UIDVALIDITY, UNSEEN: 257 * Only number, ie. unsigned int 258 * 259 * BADCHARSET, PERMANENTFLAGS: 260 * List of strings, ie. QStringList 261 * 262 * default: 263 * Any data, ie. QString 264 * */ 265 Code respCode; 266 267 /** @short Response Code Data 268 * 269 * Format is explained in the respCode documentation. 270 * We have to use pointer indirection because virtual methods wouldn't 271 * work otherwise. 272 * */ 273 QSharedPointer<AbstractData> respCodeData; 274 275 /** @short Default constructor 276 * 277 * No error checking takes place, we assume _respCodeData's type 278 * actually corresponds to all invariants we declare as per respCode's 279 * documentation. 280 * */ State(const QByteArray & tag,const Kind kind,const QString & message,const Code respCode,const QSharedPointer<AbstractData> respCodeData)281 State(const QByteArray &tag, const Kind kind, const QString &message, const Code respCode, const QSharedPointer<AbstractData> respCodeData): 282 tag(tag), kind(kind), message(message), respCode(respCode), respCodeData(respCodeData) {} 283 284 /** @short "Smart" constructor that parses a response out of a QByteArray */ 285 State(const QByteArray &tag, const Kind kind, const QByteArray &line, int &start); 286 287 /** @short Default destructor that makes containers and QtTest happy */ State()288 State(): respCode(NONE) {} 289 290 /** @short helper for operator<<( QTextStream& ) */ 291 virtual QTextStream &dump(QTextStream &s) const; 292 virtual bool eq(const AbstractResponse &other) const; 293 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 294 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 295 }; 296 297 /** @short Structure storing a CAPABILITY untagged response */ 298 class Capability : public AbstractResponse 299 { 300 public: 301 /** @short List of capabilities */ 302 QStringList capabilities; Capability(const QStringList & capabilities)303 Capability(const QStringList &capabilities): capabilities(capabilities) {} 304 virtual QTextStream &dump(QTextStream &s) const; 305 virtual bool eq(const AbstractResponse &other) const; 306 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 307 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 308 }; 309 310 /** @short Structure for EXISTS/EXPUNGE/RECENT responses */ 311 class NumberResponse : public AbstractResponse 312 { 313 public: 314 Kind kind; 315 /** @short Number that we're storing */ 316 uint number; 317 NumberResponse(const Kind kind, const uint number) throw(UnexpectedHere); 318 virtual QTextStream &dump(QTextStream &s) const; 319 virtual bool eq(const AbstractResponse &other) const; 320 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 321 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 322 }; 323 324 /** @short Structure storing a LIST untagged response */ 325 class List : public AbstractResponse 326 { 327 public: 328 /** @short LIST or LSUB */ 329 Kind kind; 330 /** @short Flags for this particular mailbox */ 331 QStringList flags; 332 /** @short Hierarchy separator 333 * 334 * QString::null in case original response containded NIL 335 * */ 336 QString separator; 337 /** @short Mailbox name */ 338 QString mailbox; 339 340 /** @short Extended LIST data (mbox-list-extended from RFC5258) */ 341 QMap<QByteArray, QVariant> extendedData; 342 343 /** @short Parse line and construct List object from it */ 344 List(const Kind kind, const QByteArray &line, int &start); List(const Kind kind,const QStringList & flags,const QString & separator,const QString & mailbox,const QMap<QByteArray,QVariant> & extendedData)345 List(const Kind kind, const QStringList &flags, const QString &separator, const QString &mailbox, 346 const QMap<QByteArray, QVariant> &extendedData): 347 kind(kind), flags(flags), separator(separator), mailbox(mailbox), extendedData(extendedData) {} 348 virtual QTextStream &dump(QTextStream &s) const; 349 virtual bool eq(const AbstractResponse &other) const; 350 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 351 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 352 }; 353 354 struct NamespaceData { 355 QString prefix; 356 QString separator; NamespaceDataNamespaceData357 NamespaceData(const QString &prefix, const QString &separator): prefix(prefix), separator(separator) {}; 358 bool operator==(const NamespaceData &other) const; 359 bool operator!=(const NamespaceData &other) const; 360 static QList<NamespaceData> listFromLine(const QByteArray &line, int &start); 361 }; 362 363 /** @short Structure storing a NAMESPACE untagged response */ 364 class Namespace : public AbstractResponse 365 { 366 public: 367 QList<NamespaceData> personal, users, other; 368 /** @short Parse line and construct List object from it */ 369 Namespace(const QByteArray &line, int &start); Namespace(const QList<NamespaceData> & personal,const QList<NamespaceData> & users,const QList<NamespaceData> & other)370 Namespace(const QList<NamespaceData> &personal, const QList<NamespaceData> &users, 371 const QList<NamespaceData> &other): 372 personal(personal), users(users), other(other) {}; 373 virtual QTextStream &dump(QTextStream &s) const; 374 virtual bool eq(const AbstractResponse &other) const; 375 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 376 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 377 }; 378 379 380 /** @short Structure storing a FLAGS untagged response */ 381 class Flags : public AbstractResponse 382 { 383 public: 384 /** @short List of flags */ 385 QStringList flags; Flags(const QStringList & flags)386 Flags(const QStringList &flags) : flags(flags) {}; 387 Flags(const QByteArray &line, int &start); 388 virtual QTextStream &dump(QTextStream &s) const; 389 virtual bool eq(const AbstractResponse &other) const; 390 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 391 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 392 }; 393 394 /** @short Structure storing a SEARCH untagged response */ 395 class Search : public AbstractResponse 396 { 397 public: 398 /** @short List of matching messages */ 399 Uids items; 400 Search(const QByteArray &line, int &start); Search(const Uids & items)401 Search(const Uids &items) : items(items) {}; 402 virtual QTextStream &dump(QTextStream &s) const; 403 virtual bool eq(const AbstractResponse &other) const; 404 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 405 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 406 }; 407 408 /** @short Structure storing an ESEARCH untagged response */ 409 class ESearch : public AbstractResponse 410 { 411 public: 412 /** @short Is the response given in UIDs, or just in sequence numbers */ 413 typedef enum { 414 SEQUENCE, /**< @short In sequence numbers */ 415 UIDS /**< @short In UIDs */ 416 } SequencesOrUids; 417 418 /** @short Convenience typedef for the received data of the list type */ 419 typedef QVector<QPair<QByteArray, Uids>> ListData_t; 420 421 /** @short Compare identifiers of the ListData_t list */ 422 template <typename T> 423 class CompareListDataIdentifier: public std::unary_function<const typename T::value_type&, bool> { 424 QByteArray keyOne; 425 QByteArray keyTwo; 426 bool hasKeyTwo; 427 public: 428 /** @short Find a record which matches the given key */ CompareListDataIdentifier(const QByteArray & key)429 explicit CompareListDataIdentifier(const QByteArray &key): keyOne(key), hasKeyTwo(false) {} 430 431 /** @short Find a record matching any of the two passed keys */ CompareListDataIdentifier(const QByteArray & keyOne,const QByteArray & keyTwo)432 explicit CompareListDataIdentifier(const QByteArray &keyOne, const QByteArray &keyTwo): 433 keyOne(keyOne), keyTwo(keyTwo), hasKeyTwo(true) {} 434 operator()435 bool operator() (const typename T::value_type & item) { 436 if (hasKeyTwo) { 437 return item.first == keyOne || item.first == keyTwo; 438 } else { 439 return item.first == keyOne; 440 } 441 } 442 }; 443 444 /** @short Represent one item to be added/removed by an incremental SEARCH/SORT response */ 445 struct ContextIncrementalItem { 446 447 /** @short Is this incremental update record about adding an item, or removing it? 448 449 These correspond to RFC 5267's ADDTO and REMOVEFROM identifiers. 450 */ 451 typedef enum { 452 ADDTO, /**< ADDTO, adding items to the search/sort criteria */ 453 REMOVEFROM /**< REMOVEFROM, removing items from the list of matches */ 454 } Modification; 455 456 /** @short Type of modification */ 457 Modification modification; 458 459 /** @short Offset at which the modification shall be performed */ 460 uint offset; 461 462 /** @short Sequence of UIDs to apply */ 463 Uids uids; 464 ContextIncrementalItemContextIncrementalItem465 ContextIncrementalItem(const Modification modification, const uint offset, const Uids &uids): 466 modification(modification), offset(offset), uids(uids) {} 467 468 bool operator==(const ContextIncrementalItem &other) const { 469 return modification == other.modification && offset == other.offset && uids == other.uids; 470 } 471 }; 472 473 typedef QList<ContextIncrementalItem> IncrementalContextData_t; 474 475 /** @short The tag of the command which requested in this operation */ 476 QByteArray tag; 477 478 /** @short Are the numbers given in UIDs, or as sequence numbers? */ 479 SequencesOrUids seqOrUids; 480 481 /** @short The received data: list of numbers */ 482 ListData_t listData; 483 484 /** @short The received data: incremental updates to SEARCH/SORT according to RFC 5267 */ 485 IncrementalContextData_t incrementalContextData; 486 487 /** @short Incremental threading information along its identifier and the preceding thread root in an ESEARCH response */ 488 struct IncrementalThreadingItem_t { 489 /** @short UID of the previous thread root's item or 0 if there's no previous item */ 490 uint previousThreadRoot; 491 492 /** @short A complete subthread */ 493 QVector<ThreadingNode> thread; 494 IncrementalThreadingItem_tIncrementalThreadingItem_t495 IncrementalThreadingItem_t(const uint previousThreadRoot, const QVector<ThreadingNode> &thread): 496 previousThreadRoot(previousThreadRoot), thread(thread) {} 497 498 bool operator==(const IncrementalThreadingItem_t &other) const { 499 return previousThreadRoot == other.previousThreadRoot && thread == other.thread; 500 } 501 }; 502 503 /** @short Typedef for all threading data sent over ESEARCH */ 504 typedef QList<IncrementalThreadingItem_t> IncrementalThreadingData_t; 505 506 /** @short The threading information, draft-imap-incthread */ 507 IncrementalThreadingData_t incThreadData; 508 509 // Other forms of returned data are quite explicitly not supported. 510 511 ESearch(const QByteArray &line, int &start); ESearch(const QByteArray & tag,const SequencesOrUids seqOrUids,const ListData_t & listData)512 ESearch(const QByteArray &tag, const SequencesOrUids seqOrUids, const ListData_t &listData) : 513 tag(tag), seqOrUids(seqOrUids), listData(listData) {} ESearch(const QByteArray & tag,const SequencesOrUids seqOrUids,const IncrementalContextData_t & incrementalContextData)514 ESearch(const QByteArray &tag, const SequencesOrUids seqOrUids, const IncrementalContextData_t &incrementalContextData) : 515 tag(tag), seqOrUids(seqOrUids), incrementalContextData(incrementalContextData) {} ESearch(const QByteArray & tag,const SequencesOrUids seqOrUids,const IncrementalThreadingData_t & incThreadData)516 ESearch(const QByteArray &tag, const SequencesOrUids seqOrUids, const IncrementalThreadingData_t &incThreadData): 517 tag(tag), seqOrUids(seqOrUids), incThreadData(incThreadData) {} 518 virtual QTextStream &dump(QTextStream &stream) const; 519 virtual bool eq(const AbstractResponse &other) const; 520 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 521 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 522 }; 523 524 /** @short Structure storing a STATUS untagged response */ 525 class Status : public AbstractResponse 526 { 527 public: 528 /** @short Indentifies type of status data */ 529 enum StateKind { 530 MESSAGES, 531 RECENT, 532 UIDNEXT, 533 UIDVALIDITY, 534 UNSEEN 535 }; 536 537 typedef QMap<StateKind,uint> stateDataType; 538 539 /** @short Mailbox name */ 540 QString mailbox; 541 /** @short Associative array of states */ 542 stateDataType states; 543 Status(const QString & mailbox,const stateDataType & states)544 Status(const QString &mailbox, const stateDataType &states) : 545 mailbox(mailbox), states(states) {}; 546 Status(const QByteArray &line, int &start); 547 virtual QTextStream &dump(QTextStream &s) const; 548 virtual bool eq(const AbstractResponse &other) const; 549 static StateKind stateKindFromStr(QString s); 550 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 551 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 552 }; 553 554 /** @short FETCH response */ 555 class Fetch : public AbstractResponse 556 { 557 public: 558 typedef QMap<QByteArray,QSharedPointer<AbstractData> > dataType; 559 560 /** @short Sequence number of message that we're working with */ 561 uint number; 562 563 /** @short Fetched items */ 564 dataType data; 565 566 Fetch(const uint number, const QByteArray &line, int &start); 567 Fetch(const uint number, const dataType &data); 568 virtual QTextStream &dump(QTextStream &s) const; 569 virtual bool eq(const AbstractResponse &other) const; 570 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 571 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 572 private: 573 static QDateTime dateify(QByteArray str, const QByteArray &line, const int start); 574 }; 575 576 /** @short Structure storing a SORT untagged response */ 577 class Sort : public AbstractResponse 578 { 579 public: 580 /** @short List of sequence/UID numbers as returned by the server */ 581 Uids numbers; 582 Sort(const QByteArray &line, int &start); Sort(const Uids & items)583 Sort(const Uids &items): numbers(items) {} 584 virtual QTextStream &dump(QTextStream &s) const; 585 virtual bool eq(const AbstractResponse &other) const; 586 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 587 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 588 }; 589 590 /** @short Structure storing a THREAD untagged response */ 591 class Thread : public AbstractResponse 592 { 593 public: 594 /** @short List of "top-level" messages */ 595 QVector<ThreadingNode> rootItems; 596 Thread(const QByteArray &line, int &start); Thread(const QVector<ThreadingNode> & items)597 Thread(const QVector<ThreadingNode> &items): rootItems(items) {} 598 virtual QTextStream &dump(QTextStream &s) const; 599 virtual bool eq(const AbstractResponse &other) const; 600 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 601 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 602 }; 603 604 /** @short Structure storing the result of the ID command */ 605 class Id : public AbstractResponse 606 { 607 public: 608 /** @short List of sequence/UID numbers as returned by the server */ 609 QMap<QByteArray,QByteArray> data; 610 Id(const QByteArray &line, int &start); Id(const QMap<QByteArray,QByteArray> & items)611 Id(const QMap<QByteArray,QByteArray> &items): data(items) {} 612 virtual QTextStream &dump(QTextStream &s) const; 613 virtual bool eq(const AbstractResponse &other) const; 614 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 615 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 616 }; 617 618 /** @short Structure storing each enabled extension */ 619 class Enabled: public AbstractResponse 620 { 621 public: 622 QList<QByteArray> extensions; 623 Enabled(const QByteArray &line, int &start); Enabled(const QList<QByteArray> & extensions)624 Enabled(const QList<QByteArray> &extensions): extensions(extensions) {} 625 virtual QTextStream &dump(QTextStream &s) const; 626 virtual bool eq(const AbstractResponse &other) const; 627 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 628 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 629 }; 630 631 /** @short VANISHED contains information about UIDs of removed messages */ 632 class Vanished: public AbstractResponse 633 { 634 public: 635 typedef enum {EARLIER, NOT_EARLIER} EarlierOrNow; 636 EarlierOrNow earlier; 637 Uids uids; 638 Vanished(const QByteArray &line, int &start); Vanished(EarlierOrNow earlier,const Uids & uids)639 Vanished(EarlierOrNow earlier, const Uids &uids): earlier(earlier), uids(uids) {} 640 virtual QTextStream &dump(QTextStream &s) const; 641 virtual bool eq(const AbstractResponse &other) const; 642 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 643 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 644 }; 645 646 /** @short The GENURLAUTH response */ 647 class GenUrlAuth: public AbstractResponse 648 { 649 public: 650 QString url; 651 GenUrlAuth(const QByteArray &line, int &start); GenUrlAuth(const QString & url)652 GenUrlAuth(const QString &url): url(url) {} 653 virtual QTextStream &dump(QTextStream &s) const; 654 virtual bool eq(const AbstractResponse &other) const; 655 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 656 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 657 }; 658 659 /** @short A fake response for passing along the SSL state */ 660 class SocketEncryptedResponse : public AbstractResponse 661 { 662 public: 663 QList<QSslCertificate> sslChain; 664 QList<QSslError> sslErrors; 665 /** @short List of sequence/UID numbers as returned by the server */ 666 SocketEncryptedResponse(const QList<QSslCertificate> &certificateChain, const QList<QSslError> &sslErrors); 667 virtual QTextStream &dump(QTextStream &s) const; 668 virtual bool eq(const AbstractResponse &other) const; 669 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 670 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 671 }; 672 673 /** @short A fake response saying that the socket got disconnected */ 674 class SocketDisconnectedResponse : public AbstractResponse 675 { 676 public: 677 QString message; SocketDisconnectedResponse(const QString & message)678 explicit SocketDisconnectedResponse(const QString &message): message(message) {} 679 virtual QTextStream &dump(QTextStream &s) const; 680 virtual bool eq(const AbstractResponse &other) const; 681 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 682 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 683 }; 684 685 /** @short A fake response about a parsing error */ 686 class ParseErrorResponse : public AbstractResponse 687 { 688 public: 689 QString message; 690 QString exceptionClass; 691 QByteArray line; 692 int offset; 693 explicit ParseErrorResponse(const ImapException &e); 694 virtual QTextStream &dump(QTextStream &s) const; 695 virtual bool eq(const AbstractResponse &other) const; 696 virtual void plug(Imap::Parser *parser, Imap::Mailbox::Model *model) const; 697 virtual bool plug(Imap::Mailbox::ImapTask *task) const; 698 }; 699 700 QTextStream &operator<<(QTextStream &stream, const Code &r); 701 QTextStream &operator<<(QTextStream &stream, const Kind &res); 702 QTextStream &operator<<(QTextStream &stream, const Status::StateKind &kind); 703 QTextStream &operator<<(QTextStream &stream, const AbstractResponse &res); 704 QTextStream &operator<<(QTextStream &stream, const NamespaceData &res); 705 706 inline bool operator==(const AbstractResponse &first, const AbstractResponse &other) 707 { 708 return first.eq(other); 709 } 710 711 inline bool operator!=(const AbstractResponse &first, const AbstractResponse &other) 712 { 713 return !first.eq(other); 714 } 715 716 /** @short Build Responses::Kind from textual value */ 717 Kind kindFromString(QByteArray str) throw(UnrecognizedResponseKind); 718 719 } 720 721 } 722 723 #endif // IMAP_RESPONSE_H 724