bool CreateMailboxTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) return false; if (resp->tag == tagCreate) { if (resp->kind == Responses::OK) { EMIT_LATER(model, mailboxCreationSucceded, Q_ARG(QString, mailbox)); if (_dead) { // Got to check if we're still allowed to execute before launching yet another command _failed("Asked to die"); return true; } tagList = parser->list(QLatin1String(""), mailbox); // Don't call _completed() yet, we're going to update mbox list before that } else { EMIT_LATER(model, mailboxCreationFailed, Q_ARG(QString, mailbox), Q_ARG(QString, resp->message)); _failed("Cannot create mailbox"); } return true; } else if (resp->tag == tagList) { if (resp->kind == Responses::OK) { model->finalizeIncrementalList(parser, mailbox); _completed(); } else { _failed("Error with the LIST command after the CREATE"); } return true; } else { return false; } }
bool SubscribeUnsubscribeTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) return false; if (resp->tag == tag) { if (resp->kind == Responses::OK) { TreeItemMailbox *mailbox = dynamic_cast<TreeItemMailbox *>(static_cast<TreeItem *>(mailboxIndex.internalPointer())); QString subscribed = QLatin1String("\\SUBSCRIBED"); switch (operation) { case SUBSCRIBE: if (mailbox && !mailbox->m_metadata.flags.contains(subscribed)) { mailbox->m_metadata.flags.append(subscribed); } break; case UNSUBSCRIBE: if (mailbox) { mailbox->m_metadata.flags.removeOne(subscribed); } } _completed(); } else { _failed("SUBSCRIBE/UNSUBSCRIBE has failed"); // FIXME: error handling } return true; } else { return false; } }
// Initial Sync Status DatabasesCloner::start() { _active = true; if (!_status.isOK() && _status.code() != ErrorCodes::NotYetInitialized) { return _status; } _status = Status::OK(); log() << "starting cloning of all databases"; // Schedule listDatabase command which will kick off the database cloner per result db. Request listDBsReq(_source, "admin", BSON("listDatabases" << true), rpc::ServerSelectionMetadata(true, boost::none).toBSON()); CBHStatus s = _exec->scheduleRemoteCommand( listDBsReq, stdx::bind(&DatabasesCloner::_onListDatabaseFinish, this, stdx::placeholders::_1)); if (!s.isOK()) { _setStatus(s); _failed(); } _doNextActions(); return _status; }
bool AppendTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) return false; if (resp->tag == tag) { if (resp->kind == Responses::OK) { if (resp->respCode == Responses::APPENDUID) { const Responses::RespData<QPair<uint, Sequence> > *const respData = dynamic_cast<const Responses::RespData<QPair<uint, Sequence> >* const>(resp->respCodeData.data()); Q_ASSERT(respData); auto uids = respData->data.second.toVector(); if (uids.size() != 1) { log(QLatin1String("APPENDUID: malformed data, cannot extract a single UID")); } else { emit appendUid(respData->data.first, uids.front()); } } // nothing should be needed here _completed(); } else { _failed(resp->message); } return true; } else { return false; } }
bool SubscribeUnsubscribeTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) return false; if (resp->tag == tag) { if (resp->kind == Responses::OK) { TreeItemMailbox *mailbox = dynamic_cast<TreeItemMailbox *>(model->findMailboxByName(mailboxName)); QString subscribed = QStringLiteral("\\SUBSCRIBED"); switch (operation) { case SUBSCRIBE: if (mailbox && !mailbox->m_metadata.flags.contains(subscribed)) { mailbox->m_metadata.flags.append(subscribed); } break; case UNSUBSCRIBE: if (mailbox) { mailbox->m_metadata.flags.removeOne(subscribed); } } if (mailbox) { auto index = mailbox->toIndex(model); emit model->dataChanged(index, index); } _completed(); } else { _failed(tr("SUBSCRIBE/UNSUBSCRIBE has failed")); // FIXME: error handling } return true; } else { return false; } }
void SortTask::perform() { parser = conn->parser; markAsActiveTask(); IMAP_TASK_CHECK_ABORT_DIE; if (! mailboxIndex.isValid()) { _failed(tr("Mailbox vanished before we could ask for threading info")); return; } // We can be killed when appropriate KeepMailboxOpenTask *keepTask = dynamic_cast<KeepMailboxOpenTask*>(conn); Q_ASSERT(keepTask); keepTask->feelFreeToAbortCaller(this); if (sortCriteria.isEmpty()) { if (model->accessParser(parser).capabilitiesFresh && model->accessParser(parser).capabilities.contains(QLatin1String("ESEARCH"))) { // We always prefer ESEARCH over SEARCH, if only for its embedded reference to the command tag if (model->accessParser(parser).capabilities.contains(QLatin1String("CONTEXT=SEARCH"))) { // Hurray, this IMAP server supports incremental ESEARCH updates m_persistentSearch = true; sortTag = parser->uidESearch("utf-8", searchConditions, QStringList() << QLatin1String("ALL") << QLatin1String("UPDATE")); } else { // ESORT without CONTEXT is still worth the effort, if only for the tag reference sortTag = parser->uidESearch("utf-8", searchConditions, QStringList() << QLatin1String("ALL")); } } else { // Plain "old" SORT sortTag = parser->uidSearch(searchConditions, // It looks that Exchange 2003 does not support the UTF-8 charset in searches. // That is, of course, insane, and only illustrates how useless its support of IMAP really is. model->m_capabilitiesBlacklist.contains(QLatin1String("X-NO-UTF8-SEARCH")) ? QByteArray() : "utf-8" ); } } else { // SEARCH and SORT combined if (model->accessParser(parser).capabilitiesFresh && model->accessParser(parser).capabilities.contains(QLatin1String("ESORT"))) { // ESORT's better than regular SORT, if only for its embedded reference to the command tag if (model->accessParser(parser).capabilities.contains(QLatin1String("CONTEXT=SORT"))) { // Hurray, this IMAP server supports incremental SORT updates m_persistentSearch = true; sortTag = parser->uidESort(sortCriteria, "utf-8", searchConditions, QStringList() << QLatin1String("ALL") << QLatin1String("UPDATE")); } else { // ESORT without CONTEXT is still worth the effort, if only for the tag reference sortTag = parser->uidESort(sortCriteria, "utf-8", searchConditions, QStringList() << QLatin1String("ALL")); } } else { // Plain "old" SORT sortTag = parser->uidSort(sortCriteria, "utf-8", searchConditions); } } }
bool SortTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) { if (resp->kind == Responses::NO && resp->respCode == Responses::NOUPDATE) { // * NO [NOUPDATE "tag"] means that the server won't be providing further updates for our SEARCH/SORT criteria const Responses::RespData<QString> *const untaggedTag = dynamic_cast<const Responses::RespData<QString>* const>( resp->respCodeData.data()); Q_ASSERT(untaggedTag); if (untaggedTag->data.toUtf8() == sortTag) { m_persistentSearch = false; model->m_taskModel->slotTaskMighHaveChanged(this); if (m_firstCommandCompleted) { // The server decided that it will no longer inform us about the updated SORT order, and the original // response has been already received and processed. That means that we're done here and shall declare // ourselves as completed. _completed(); } // We actually support even more benevolent mode of operation where the server can tell us at any time that // this context updating is no longer supported. Yay for that; let's hope that it's reasonably bug-free now. return true; } } return false; } if (resp->tag == sortTag) { m_firstCommandCompleted = true; if (resp->kind == Responses::OK) { emit sortingAvailable(sortResult); if (!m_persistentSearch || _aborted) { // This is a one-shot operation, we shall not remain as an active task, listening for further updates _completed(); } else { // got to prod the TaskPresentationModel model->m_taskModel->slotTaskMighHaveChanged(this); // Even though we aren't "finished" at this point, the KeepMailboxOpenTask is now free to issue its IDLE thing, // as that won't interfere with our mode of operation. Let's kick it around. KeepMailboxOpenTask *keepTask = dynamic_cast<KeepMailboxOpenTask*>(conn); Q_ASSERT(keepTask); keepTask->activateTasks(); } } else { _failed(tr("Sorting command has failed")); } return true; } else if (resp->tag == cancelUpdateTag) { m_persistentSearch = false; model->m_taskModel->slotTaskMighHaveChanged(this); _completed(); return true; } else { return false; } }
bool FetchMsgMetadataTask::handleFetch(const Imap::Responses::Fetch *const resp) { if (! mailbox.isValid()) { _failed("handleFetch: mailbox disappeared"); // FIXME: nice error handling return false; } TreeItemMailbox *mailboxPtr = dynamic_cast<TreeItemMailbox *>(static_cast<TreeItemMailbox *>(mailbox.internalPointer())); Q_ASSERT(mailboxPtr); model->genericHandleFetch(mailboxPtr, resp); return true; }
void UnSelectTask::doFakeSelect() { if (_dead) { _failed(tr("Asked to die")); return; } // Again, ignoring abort() if (model->accessParser(parser).maintainingTask) { model->accessParser(parser).maintainingTask->breakOrCancelPossibleIdle(); } // The server does not support UNSELECT. Let's construct an unlikely-to-exist mailbox, then. selectMissingTag = parser->examine(QLatin1String("trojita non existing ") + QUuid::createUuid().toString()); }
bool NumberOfMessagesTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) return false; if (resp->tag == tag) { if (resp->kind == Responses::OK) { _completed(); } else { _failed(tr("STATUS has failed")); // FIXME: error handling } return true; } else { return false; } }
bool FetchMsgMetadataTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) return false; if (resp->tag == tag) { if (resp->kind == Responses::OK) { _completed(); } else { _failed("UID FETCH failed"); // FIXME: error handling } return true; } else { return false; } }
bool GenUrlAuthTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) return false; if (resp->tag == tag) { if (resp->kind == Responses::OK) { // nothing should be needed here _completed(); } else { _failed(resp->message); } return true; } else { return false; } }
bool IdTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) return false; if (resp->tag == tag) { if (resp->kind == Responses::OK) { // nothing should be needed here _completed(); } else { _failed(tr("ID failed, strange")); // But hey, we can just ignore this one } return true; } else { return false; } }
void ThreadTask::perform() { parser = conn->parser; markAsActiveTask(); IMAP_TASK_CHECK_ABORT_DIE; if (! mailboxIndex.isValid()) { _failed("Mailbox vanished before we could ask for threading info"); return; } if (m_incrementalMode) { tag = parser->uidEThread(algorithm, "utf-8", searchCriteria, QStringList() << "INCTHREAD"); } else { tag = parser->uidThread(algorithm, "utf-8", searchCriteria); } }
bool NoopTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) return false; if (resp->tag == tag) { if (resp->kind == Responses::OK) { // nothing should be needed here _completed(); } else { _failed("NOOP failed, strange"); // FIXME: error handling } return true; } else { return false; } }
void UnSelectTask::perform() { markAsActiveTask(TASK_PREPEND); if (_dead) { _failed(tr("Asked to die")); return; } // We really should ignore abort() -- we're a very important task if (model->accessParser(parser).maintainingTask) { model->accessParser(parser).maintainingTask->breakOrCancelPossibleIdle(); } if (model->accessParser(parser).capabilities.contains(QStringLiteral("UNSELECT"))) { unSelectTag = parser->unSelect(); } else { doFakeSelect(); } }
bool ThreadTask::handleStateHelper(const Imap::Responses::State *const resp) { if (resp->tag.isEmpty()) return false; if (resp->tag == tag) { if (resp->kind == Responses::OK) { if (!m_incrementalMode) emit model->threadingAvailable(mailboxIndex, algorithm, searchCriteria, mapping); _completed(); } else { _failed("Threading command has failed"); } mapping.clear(); return true; } else { return false; } }