Example #1
0
Collection HandlerHelper::collectionFromIdOrName(const QByteArray &id)
{
    // id is a number
    bool ok = false;
    qint64 collectionId = id.toLongLong(&ok);
    if (ok) {
        return Collection::retrieveById(collectionId);
    }

    // id is a path
    QString path = QString::fromUtf8(id);   // ### should be UTF-7 for real IMAP compatibility

    const QStringList pathParts = path.split(QLatin1Char('/'), QString::SkipEmptyParts);
    Collection col;
    for (const QString &part : pathParts) {
        SelectQueryBuilder<Collection> qb;
        qb.addValueCondition(Collection::nameColumn(), Query::Equals, part);
        if (col.isValid()) {
            qb.addValueCondition(Collection::parentIdColumn(), Query::Equals, col.id());
        } else {
            qb.addValueCondition(Collection::parentIdColumn(), Query::Is, QVariant());
        }
        if (!qb.exec()) {
            return Collection();
        }
        Collection::List list = qb.result();
        if (list.count() != 1) {
            return Collection();
        }
        col = list.first();
    }
    return col;
}
Example #2
0
bool RelationFetch::parseStream()
{
    Protocol::FetchRelationsCommand cmd(m_command);

    SelectQueryBuilder<Relation> relationQuery;
    if (cmd.side() > 0) {
        Query::Condition c;
        c.setSubQueryMode(Query::Or);
        c.addValueCondition(Relation::leftIdFullColumnName(), Query::Equals, cmd.side());
        c.addValueCondition(Relation::rightIdFullColumnName(), Query::Equals, cmd.side());
        relationQuery.addCondition(c);
    } else {
        if (cmd.left() > 0) {
            relationQuery.addValueCondition(Relation::leftIdFullColumnName(), Query::Equals, cmd.left());
        }
        if (cmd.right() > 0) {
            relationQuery.addValueCondition(Relation::rightIdFullColumnName(), Query::Equals, cmd.right());
        }
    }
    if (!cmd.types().isEmpty()) {
        relationQuery.addJoin(QueryBuilder::InnerJoin, RelationType::tableName(), Relation::typeIdFullColumnName(), RelationType::idFullColumnName());
        QStringList types;
        types.reserve(cmd.types().size());
        Q_FOREACH (const QByteArray &type, cmd.types()) {
            types << QString::fromUtf8(type);
        }
        relationQuery.addValueCondition(RelationType::nameFullColumnName(), Query::In, types);
    }
Example #3
0
File: link.cpp Project: KDE/akonadi
bool Link::parseStream()
{
    Protocol::LinkItemsCommand cmd(m_command);

    const Collection collection = HandlerHelper::collectionFromScope(cmd.destination(), connection());
    if (!collection.isVirtual()) {
        return failureResponse("Can't link items to non-virtual collections");
    }

    /* FIXME BIN
    Resource originalContext;
    Scope::SelectionScope itemSelectionScope = Scope::selectionScopeFromByteArray(m_streamParser->peekString());
    if (itemSelectionScope != Scope::None) {
        m_streamParser->readString();
        // Unset Resource context if destination collection is specified using HRID/RID,
        // because otherwise the Resource context is relative to the destination collection
        // instead of the source collection (collection context)
        if ((mDestinationScope.scope() == Scope::HierarchicalRid || mDestinationScope.scope() == Scope::Rid) && itemSelectionScope == Scope::Rid) {
            originalContext = connection()->context()->resource();
            connection()->context()->setResource(Resource());
        }
    }
    Scope itemScope(itemSelectionScope);
    itemScope.parseScope(m_streamParser);
    */

    SelectQueryBuilder<PimItem> qb;
    ItemQueryHelper::scopeToQuery(cmd.items(), connection()->context(), qb);

    /*
    if (originalContext.isValid()) {
        connection()->context()->setResource(originalContext);
    }
    */

    if (!qb.exec()) {
        return failureResponse("Unable to execute item query");
    }

    const PimItem::List items = qb.result();

    DataStore *store = connection()->storageBackend();
    Transaction transaction(store);

    PimItem::List toLink, toUnlink;
    const bool createLinks = (cmd.action() == Protocol::LinkItemsCommand::Link);
    for (const PimItem &item : items) {
        const bool alreadyLinked = collection.relatesToPimItem(item);
        bool result = true;
        if (createLinks && !alreadyLinked) {
            result = collection.addPimItem(item);
            toLink << item;
        } else if (!createLinks && alreadyLinked) {
            result = collection.removePimItem(item);
            toUnlink << item;
        }
        if (!result) {
            return failureResponse("Failed to modify item reference");
        }
    }

    if (!toLink.isEmpty()) {
        store->notificationCollector()->itemsLinked(toLink, collection);
    } else if (!toUnlink.isEmpty()) {
        store->notificationCollector()->itemsUnlinked(toUnlink, collection);
    }

    if (!transaction.commit()) {
        return failureResponse("Cannot commit transaction.");
    }

    return successResponse<Protocol::LinkItemsResponse>();
}
Example #4
0
bool Store::parseStream()
{
    Protocol::ModifyItemsCommand cmd(m_command);

    //parseCommand();

    DataStore *store = connection()->storageBackend();
    Transaction transaction(store);
    ExternalPartStorageTransaction storageTrx;
    // Set the same modification time for each item.
    QDateTime modificationtime = QDateTime::currentDateTimeUtc();
    if (DbType::type(store->database()) != DbType::Sqlite) {
        // Remove milliseconds from the modificationtime. PSQL and MySQL don't
        // support milliseconds in DATETIME column, so FETCHed Items will report
        // time without milliseconds, while this command would return answer
        // with milliseconds
        modificationtime = modificationtime.addMSecs(-modificationtime.time().msec());
    }

    // retrieve selected items
    SelectQueryBuilder<PimItem> qb;
    ItemQueryHelper::scopeToQuery(cmd.items(), connection()->context(), qb);
    if (!qb.exec()) {
        return failureResponse("Unable to retrieve items");
    }
    PimItem::List pimItems = qb.result();
    if (pimItems.isEmpty()) {
        return failureResponse("No items found");
    }

    for (int i = 0; i < pimItems.size(); ++i) {
        if (cmd.oldRevision() > -1) {
            // check for conflicts if a resources tries to overwrite an item with dirty payload
            const PimItem &pimItem = pimItems.at(i);
            if (connection()->isOwnerResource(pimItem)) {
                if (pimItem.dirty()) {
                    const QString error = QStringLiteral("[LRCONFLICT] Resource %1 tries to modify item %2 (%3) (in collection %4) with dirty payload, aborting STORE.");
                    return failureResponse(
                        error.arg(pimItem.collection().resource().name())
                             .arg(pimItem.id())
                             .arg(pimItem.remoteId()).arg(pimItem.collectionId()));
                }
            }

            // check and update revisions
            if (pimItems.at(i).rev() != (int) cmd.oldRevision()) {
                return failureResponse("[LLCONFLICT] Item was modified elsewhere, aborting STORE.");
            }
        }
    }

    PimItem &item = pimItems.first();

    QSet<QByteArray> changes;
    qint64 partSizes = 0;
    qint64 size = 0;

    bool flagsChanged = false;
    bool tagsChanged = false;

    if (cmd.modifiedParts() & Protocol::ModifyItemsCommand::AddedFlags) {
        if (!addFlags(pimItems, cmd.addedFlags(), flagsChanged)) {
            return failureResponse("Unable to add item flags");
        }
    }

    if (cmd.modifiedParts() & Protocol::ModifyItemsCommand::RemovedFlags) {
        if (!deleteFlags(pimItems, cmd.removedFlags(), flagsChanged)) {
            return failureResponse("Unable to remove item flags");
        }
    }

    if (cmd.modifiedParts() & Protocol::ModifyItemsCommand::Flags) {
        if (!replaceFlags(pimItems, cmd.flags(), flagsChanged)) {
            return failureResponse("Unable to reset flags");
        }
    }

    if (flagsChanged) {
        changes << AKONADI_PARAM_FLAGS;
    }

    if (cmd.modifiedParts() & Protocol::ModifyItemsCommand::AddedTags) {
        if (!addTags(pimItems, cmd.addedTags(), tagsChanged)) {
            return failureResponse("Unable to add item tags");
        }
    }

    if (cmd.modifiedParts() & Protocol::ModifyItemsCommand::RemovedTags) {
        if (!deleteTags(pimItems, cmd.removedTags(), tagsChanged)) {
            return failureResponse("Unabel to remove item tags");
        }
    }

    if (cmd.modifiedParts() & Protocol::ModifyItemsCommand::Tags) {
        if (!replaceTags(pimItems, cmd.tags(), tagsChanged)) {
            return failureResponse("Unable to reset item tags");
        }
    }

    if (tagsChanged) {
        changes << AKONADI_PARAM_TAGS;
    }

    if (item.isValid() && cmd.modifiedParts() & Protocol::ModifyItemsCommand::RemoteID) {
        if (item.remoteId() != cmd.remoteId()) {
            if (!connection()->isOwnerResource(item)) {
                return failureResponse("Only resources can modify remote identifiers");
            }
            item.setRemoteId(cmd.remoteId());
            changes << AKONADI_PARAM_REMOTEID;
        }
    }

    if (item.isValid() && cmd.modifiedParts() & Protocol::ModifyItemsCommand::GID) {
        if (item.gid() != cmd.gid()) {
            item.setGid(cmd.gid());
        }
        changes << AKONADI_PARAM_GID;
    }

    if (item.isValid() && cmd.modifiedParts() & Protocol::ModifyItemsCommand::RemoteRevision) {
        if (item.remoteRevision() != cmd.remoteRevision()) {
            if (!connection()->isOwnerResource(item)) {
                return failureResponse("Only resources can modify remote revisions");
            }
            item.setRemoteRevision(cmd.remoteRevision());
            changes << AKONADI_PARAM_REMOTEREVISION;
        }
    }

    if (item.isValid() && !cmd.dirty()) {
        item.setDirty(false);
    }

    if (item.isValid() && cmd.modifiedParts() & Protocol::ModifyItemsCommand::Size) {
        size = cmd.itemSize();
        changes << AKONADI_PARAM_SIZE;
    }

    if (item.isValid() && cmd.modifiedParts() & Protocol::ModifyItemsCommand::RemovedParts) {
        if (!cmd.removedParts().isEmpty()) {
            if (!store->removeItemParts(item, cmd.removedParts())) {
                return failureResponse("Unable to remove item parts");
            }
            Q_FOREACH (const QByteArray &part, cmd.removedParts()) {
                changes.insert(part);
            }
        }
    }

    if (item.isValid() && cmd.modifiedParts() & Protocol::ModifyItemsCommand::Parts) {
        PartStreamer streamer(connection(), item, this);
        connect(&streamer, &PartStreamer::responseAvailable,
                this, static_cast<void(Handler::*)(const Protocol::Command &)>(&Handler::sendResponse));
        Q_FOREACH (const QByteArray &partName, cmd.parts()) {
            qint64 partSize = 0;
            if (!streamer.stream(true, partName, partSize)) {
                return failureResponse(streamer.error());
            }

            changes.insert(partName);
            partSizes += partSize;
        }
    }