File indexing completed on 2024-06-23 05:21:16
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 0023 0024 #include "UnSelectTask.h" 0025 #include <QUuid> 0026 #include "Imap/Model/Model.h" 0027 #include "Imap/Model/MailboxTree.h" 0028 #include "KeepMailboxOpenTask.h" 0029 0030 namespace Imap 0031 { 0032 namespace Mailbox 0033 { 0034 0035 UnSelectTask::UnSelectTask(Model *model, ImapTask *parentTask) : 0036 ImapTask(model) 0037 { 0038 conn = parentTask; 0039 parser = conn->parser; 0040 Q_ASSERT(parser); 0041 connect(this, &ImapTask::completed, this, &UnSelectTask::resetConnectionState); 0042 } 0043 0044 void UnSelectTask::perform() 0045 { 0046 markAsActiveTask(TASK_PREPEND); 0047 0048 if (_dead) { 0049 _failed(tr("Asked to die")); 0050 return; 0051 } 0052 // We really should ignore abort() -- we're a very important task 0053 0054 if (model->accessParser(parser).maintainingTask) { 0055 model->accessParser(parser).maintainingTask->breakOrCancelPossibleIdle(); 0056 } 0057 if (model->accessParser(parser).capabilities.contains(QStringLiteral("UNSELECT"))) { 0058 unSelectTag = parser->unSelect(); 0059 } else { 0060 doFakeSelect(); 0061 } 0062 } 0063 0064 void UnSelectTask::doFakeSelect() 0065 { 0066 if (_dead) { 0067 _failed(tr("Asked to die")); 0068 return; 0069 } 0070 // Again, ignoring abort() 0071 0072 if (model->accessParser(parser).maintainingTask) { 0073 model->accessParser(parser).maintainingTask->breakOrCancelPossibleIdle(); 0074 } 0075 // The server does not support UNSELECT. Let's construct an unlikely-to-exist mailbox, then. 0076 selectMissingTag = parser->examine(QLatin1String("trojita non existing ") + QUuid::createUuid().toString()); 0077 } 0078 0079 bool UnSelectTask::handleStateHelper(const Imap::Responses::State *const resp) 0080 { 0081 if (resp->tag.isEmpty()) { 0082 switch (resp->respCode) { 0083 case Responses::UNSEEN: 0084 case Responses::PERMANENTFLAGS: 0085 case Responses::UIDNEXT: 0086 case Responses::UIDVALIDITY: 0087 case Responses::NOMODSEQ: 0088 case Responses::HIGHESTMODSEQ: 0089 case Responses::CLOSED: 0090 return true; 0091 default: 0092 break; 0093 } 0094 } 0095 if (!resp->tag.isEmpty()) { 0096 if (resp->tag == unSelectTag) { 0097 if (resp->kind == Responses::OK) { 0098 // nothing should be needed here 0099 _completed(); 0100 } else { 0101 // This is really bad. 0102 throw MailboxException("Attempted to unselect current mailbox, but the server denied our request. " 0103 "Can't continue, to avoid possible data corruption.", *resp); 0104 } 0105 return true; 0106 } else if (resp->tag == selectMissingTag) { 0107 if (resp->kind == Responses::OK) { 0108 QTimer::singleShot(0, this, SLOT(doFakeSelect())); 0109 log(QStringLiteral("The emergency EXAMINE command has unexpectedly succeeded, trying to get out of here..."), Common::LOG_MAILBOX_SYNC); 0110 } else { 0111 // This is very good :) 0112 _completed(); 0113 } 0114 return true; 0115 } 0116 } 0117 return false; 0118 } 0119 0120 bool UnSelectTask::handleNumberResponse(const Imap::Responses::NumberResponse *const resp) 0121 { 0122 Q_UNUSED(resp); 0123 log(QStringLiteral("UnSelectTask: ignoring numeric response"), Common::LOG_MAILBOX_SYNC); 0124 return true; 0125 } 0126 0127 bool UnSelectTask::handleFlags(const Imap::Responses::Flags *const resp) 0128 { 0129 Q_UNUSED(resp); 0130 log(QStringLiteral("UnSelectTask: ignoring FLAGS response"), Common::LOG_MAILBOX_SYNC); 0131 return true; 0132 } 0133 0134 bool UnSelectTask::handleSearch(const Imap::Responses::Search *const resp) 0135 { 0136 Q_UNUSED(resp); 0137 log(QStringLiteral("UnSelectTask: ignoring SEARCH response"), Common::LOG_MAILBOX_SYNC); 0138 return true; 0139 } 0140 0141 bool UnSelectTask::handleFetch(const Imap::Responses::Fetch *const resp) 0142 { 0143 Q_UNUSED(resp); 0144 log(QStringLiteral("UnSelectTask: ignoring FETCH response"), Common::LOG_MAILBOX_SYNC); 0145 return true; 0146 } 0147 0148 /** @short Internal task */ 0149 QVariant UnSelectTask::taskData(const int role) const 0150 { 0151 Q_UNUSED(role); 0152 return QVariant(); 0153 } 0154 0155 /** @short Reset the "waiting for [CLOSED]" state */ 0156 void UnSelectTask::resetConnectionState() 0157 { 0158 auto const state = model->accessParser(parser).connState; 0159 if (state > CONN_STATE_AUTHENTICATED && state < CONN_STATE_LOGOUT) { 0160 model->changeConnectionState(parser, CONN_STATE_AUTHENTICATED); 0161 } 0162 } 0163 0164 } 0165 }