Пример #1
0
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;
    }
}
Пример #3
0
// 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;
}
Пример #4
0
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;
    }
}
Пример #6
0
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);
        }
    }
}
Пример #7
0
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;
    }
}
Пример #8
0
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;
}
Пример #9
0
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());
}
Пример #10
0
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;
    }
}
Пример #11
0
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;
    }
}
Пример #12
0
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;
    }
}
Пример #13
0
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;
    }
}
Пример #14
0
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);
    }
}
Пример #15
0
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;
    }
}
Пример #16
0
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();
    }
}
Пример #17
0
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;
    }
}