File indexing completed on 2024-06-23 05:07:01
0001 /* 0002 SPDX-FileCopyrightText: 2008 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "itemcopyhandler.h" 0008 0009 #include "akonadi.h" 0010 #include "cachecleaner.h" 0011 #include "connection.h" 0012 #include "handlerhelper.h" 0013 #include "storage/datastore.h" 0014 #include "storage/itemqueryhelper.h" 0015 #include "storage/itemretriever.h" 0016 #include "storage/parthelper.h" 0017 #include "storage/selectquerybuilder.h" 0018 #include "storage/transaction.h" 0019 0020 #include "private/imapset_p.h" 0021 0022 using namespace Akonadi; 0023 using namespace Akonadi::Server; 0024 0025 ItemCopyHandler::ItemCopyHandler(AkonadiServer &akonadi) 0026 : Handler(akonadi) 0027 { 0028 } 0029 0030 bool ItemCopyHandler::copyItem(const PimItem &item, const Collection &target) 0031 { 0032 PimItem newItem = item; 0033 newItem.setId(-1); 0034 newItem.setRev(0); 0035 newItem.setDatetime(QDateTime::currentDateTimeUtc()); 0036 newItem.setAtime(QDateTime::currentDateTimeUtc()); 0037 newItem.setRemoteId(QString()); 0038 newItem.setRemoteRevision(QString()); 0039 newItem.setCollectionId(target.id()); 0040 Part::List newParts; 0041 const auto parts = item.parts(); 0042 newParts.reserve(parts.size()); 0043 for (const Part &part : parts) { 0044 Part newPart(part); 0045 newPart.setData(PartHelper::translateData(newPart.data(), part.storage())); 0046 newPart.setPimItemId(-1); 0047 newPart.setStorage(Part::Internal); 0048 newParts << newPart; 0049 } 0050 0051 DataStore *store = connection()->storageBackend(); 0052 return store->appendPimItem(newParts, item.flags(), item.mimeType(), target, QDateTime::currentDateTimeUtc(), QString(), QString(), item.gid(), newItem); 0053 } 0054 0055 void ItemCopyHandler::processItems(const QList<qint64> &ids) 0056 { 0057 SelectQueryBuilder<PimItem> qb; 0058 ItemQueryHelper::itemSetToQuery(ImapSet(ids), qb); 0059 if (!qb.exec()) { 0060 failureResponse(QStringLiteral("Unable to retrieve items")); 0061 return; 0062 } 0063 const PimItem::List items = qb.result(); 0064 qb.query().finish(); 0065 0066 DataStore *store = connection()->storageBackend(); 0067 Transaction transaction(store, QStringLiteral("COPY")); 0068 0069 for (const PimItem &item : items) { 0070 if (!copyItem(item, mTargetCollection)) { 0071 failureResponse(QStringLiteral("Unable to copy item")); 0072 return; 0073 } 0074 } 0075 0076 if (!transaction.commit()) { 0077 failureResponse(QStringLiteral("Cannot commit transaction.")); 0078 return; 0079 } 0080 } 0081 0082 bool ItemCopyHandler::parseStream() 0083 { 0084 const auto &cmd = Protocol::cmdCast<Protocol::CopyItemsCommand>(m_command); 0085 0086 if (!checkScopeConstraints(cmd.items(), Scope::Uid)) { 0087 return failureResponse(QStringLiteral("Only UID copy is allowed")); 0088 } 0089 0090 if (cmd.items().isEmpty()) { 0091 return failureResponse(QStringLiteral("No items specified")); 0092 } 0093 0094 mTargetCollection = HandlerHelper::collectionFromScope(cmd.destination(), connection()->context()); 0095 if (!mTargetCollection.isValid()) { 0096 return failureResponse(QStringLiteral("No valid target specified")); 0097 } 0098 if (mTargetCollection.isVirtual()) { 0099 return failureResponse(QStringLiteral("Copying items into virtual collections is not allowed")); 0100 } 0101 0102 CacheCleanerInhibitor inhibitor(akonadi()); 0103 0104 ItemRetriever retriever(akonadi().itemRetrievalManager(), connection(), connection()->context()); 0105 retriever.setItemSet(cmd.items().uidSet()); 0106 retriever.setRetrieveFullPayload(true); 0107 QObject::connect(&retriever, &ItemRetriever::itemsRetrieved, &retriever, [this](const QList<qint64> &ids) { 0108 processItems(ids); 0109 }); 0110 if (!retriever.exec()) { 0111 return failureResponse(retriever.lastError()); 0112 } 0113 0114 return successResponse<Protocol::CopyItemsResponse>(); 0115 }