diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | common/CMakeLists.txt | 3 | ||||
-rw-r--r-- | common/mailpreprocessor.cpp | 117 | ||||
-rw-r--r-- | common/mailpreprocessor.h | 45 | ||||
-rw-r--r-- | common/pipeline.cpp | 36 | ||||
-rw-r--r-- | common/pipeline.h | 6 | ||||
-rw-r--r-- | examples/imapresource/imapresource.cpp | 95 |
7 files changed, 199 insertions, 105 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index c53075d..1eb16a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -20,7 +20,7 @@ include(ECMSetupVersion) | |||
20 | include(KDEInstallDirs) | 20 | include(KDEInstallDirs) |
21 | 21 | ||
22 | find_package(Qt5 COMPONENTS REQUIRED Core Widgets Network) | 22 | find_package(Qt5 COMPONENTS REQUIRED Core Widgets Network) |
23 | find_package(KF5 COMPONENTS REQUIRED Async) | 23 | find_package(KF5 COMPONENTS REQUIRED Async Mime) |
24 | find_package(FlatBuffers REQUIRED) | 24 | find_package(FlatBuffers REQUIRED) |
25 | 25 | ||
26 | #Clang-format support | 26 | #Clang-format support |
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 752e4e4..3083a2e 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt | |||
@@ -73,6 +73,7 @@ set(command_SRCS | |||
73 | remoteidmap.cpp | 73 | remoteidmap.cpp |
74 | sourcewriteback.cpp | 74 | sourcewriteback.cpp |
75 | entityreader.cpp | 75 | entityreader.cpp |
76 | mailpreprocessor.cpp | ||
76 | ${storage_SRCS}) | 77 | ${storage_SRCS}) |
77 | 78 | ||
78 | add_library(${PROJECT_NAME} SHARED ${command_SRCS}) | 79 | add_library(${PROJECT_NAME} SHARED ${command_SRCS}) |
@@ -108,7 +109,7 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} | |||
108 | EXPORT_NAME ${PROJECT_NAME} | 109 | EXPORT_NAME ${PROJECT_NAME} |
109 | ) | 110 | ) |
110 | qt5_use_modules(${PROJECT_NAME} Network) | 111 | qt5_use_modules(${PROJECT_NAME} Network) |
111 | target_link_libraries(${PROJECT_NAME} ${storage_LIBS} KF5::Async) | 112 | target_link_libraries(${PROJECT_NAME} ${storage_LIBS} KF5::Async KF5::Mime) |
112 | install(TARGETS ${PROJECT_NAME} | 113 | install(TARGETS ${PROJECT_NAME} |
113 | EXPORT SinkTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ${LIBRARY_NAMELINK} ) | 114 | EXPORT SinkTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ${LIBRARY_NAMELINK} ) |
114 | 115 | ||
diff --git a/common/mailpreprocessor.cpp b/common/mailpreprocessor.cpp new file mode 100644 index 0000000..64cb3d9 --- /dev/null +++ b/common/mailpreprocessor.cpp | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | |||
20 | #include "mailpreprocessor.h" | ||
21 | |||
22 | #include <QFile> | ||
23 | #include <QDir> | ||
24 | #include <KMime/KMime/KMimeMessage> | ||
25 | |||
26 | #include "pipeline.h" | ||
27 | #include "definitions.h" | ||
28 | #include "applicationdomaintype.h" | ||
29 | |||
30 | using namespace Sink; | ||
31 | |||
32 | void MailPropertyExtractor::updatedIndexedProperties(Sink::ApplicationDomain::Mail &mail) | ||
33 | { | ||
34 | const auto mimeMessagePath = mail.getMimeMessagePath(); | ||
35 | Trace() << "Updating indexed properties " << mimeMessagePath; | ||
36 | QFile f(mimeMessagePath); | ||
37 | if (!f.open(QIODevice::ReadOnly)) { | ||
38 | Warning() << "Failed to open the file: " << mimeMessagePath; | ||
39 | return; | ||
40 | } | ||
41 | if (!f.size()) { | ||
42 | Warning() << "The file is empty."; | ||
43 | return; | ||
44 | } | ||
45 | const auto mappedSize = qMin((qint64)8000, f.size()); | ||
46 | auto mapped = f.map(0, mappedSize); | ||
47 | if (!mapped) { | ||
48 | Warning() << "Failed to map the file: " << f.errorString(); | ||
49 | return; | ||
50 | } | ||
51 | |||
52 | KMime::Message *msg = new KMime::Message; | ||
53 | msg->setHead(KMime::CRLFtoLF(QByteArray::fromRawData(reinterpret_cast<const char*>(mapped), mappedSize))); | ||
54 | msg->parse(); | ||
55 | |||
56 | mail.setExtractedSubject(msg->subject(true)->asUnicodeString()); | ||
57 | mail.setExtractedSender(msg->from(true)->asUnicodeString()); | ||
58 | mail.setExtractedSenderName(msg->from(true)->asUnicodeString()); | ||
59 | mail.setExtractedDate(msg->date(true)->dateTime()); | ||
60 | } | ||
61 | |||
62 | void MailPropertyExtractor::newEntity(Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) | ||
63 | { | ||
64 | updatedIndexedProperties(mail); | ||
65 | } | ||
66 | |||
67 | void MailPropertyExtractor::modifiedEntity(const Sink::ApplicationDomain::Mail &oldMail, Sink::ApplicationDomain::Mail &newMail,Sink::Storage::Transaction &transaction) | ||
68 | { | ||
69 | updatedIndexedProperties(newMail); | ||
70 | } | ||
71 | |||
72 | |||
73 | MimeMessageMover::MimeMessageMover() : Sink::EntityPreprocessor<ApplicationDomain::Mail>() | ||
74 | { | ||
75 | } | ||
76 | |||
77 | QString MimeMessageMover::moveMessage(const QString &oldPath, const Sink::ApplicationDomain::Mail &mail) | ||
78 | { | ||
79 | const auto directory = Sink::resourceStorageLocation(resourceInstanceIdentifier()); | ||
80 | const auto filePath = directory + "/" + mail.identifier(); | ||
81 | if (oldPath != filePath) { | ||
82 | if (!QDir().mkpath(directory)) { | ||
83 | Warning() << "Failed to create the directory: " << directory; | ||
84 | } | ||
85 | QFile::remove(filePath); | ||
86 | QFile origFile(oldPath); | ||
87 | if (!origFile.open(QIODevice::ReadWrite)) { | ||
88 | Warning() << "Failed to open the original file with write rights: " << origFile.errorString(); | ||
89 | } | ||
90 | if (!origFile.rename(filePath)) { | ||
91 | Warning() << "Failed to move the file from: " << oldPath << " to " << filePath << ". " << origFile.errorString(); | ||
92 | } | ||
93 | origFile.close(); | ||
94 | return filePath; | ||
95 | } | ||
96 | return oldPath; | ||
97 | } | ||
98 | |||
99 | void MimeMessageMover::newEntity(Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) | ||
100 | { | ||
101 | if (!mail.getMimeMessagePath().isEmpty()) { | ||
102 | mail.setMimeMessagePath(moveMessage(mail.getMimeMessagePath(), mail)); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | void MimeMessageMover::modifiedEntity(const Sink::ApplicationDomain::Mail &oldMail, Sink::ApplicationDomain::Mail &newMail, Sink::Storage::Transaction &transaction) | ||
107 | { | ||
108 | if (!newMail.getMimeMessagePath().isEmpty()) { | ||
109 | newMail.setMimeMessagePath(moveMessage(newMail.getMimeMessagePath(), newMail)); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | void MimeMessageMover::deletedEntity(const Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) | ||
114 | { | ||
115 | QFile::remove(mail.getMimeMessagePath()); | ||
116 | } | ||
117 | |||
diff --git a/common/mailpreprocessor.h b/common/mailpreprocessor.h new file mode 100644 index 0000000..715e336 --- /dev/null +++ b/common/mailpreprocessor.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | #include "sink_export.h" | ||
20 | |||
21 | #include "pipeline.h" | ||
22 | |||
23 | class SINK_EXPORT MailPropertyExtractor : public Sink::EntityPreprocessor<Sink::ApplicationDomain::Mail> | ||
24 | { | ||
25 | public: | ||
26 | virtual ~MailPropertyExtractor(){} | ||
27 | virtual void newEntity(Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE; | ||
28 | virtual void modifiedEntity(const Sink::ApplicationDomain::Mail &oldMail, Sink::ApplicationDomain::Mail &newMail,Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE; | ||
29 | private: | ||
30 | void updatedIndexedProperties(Sink::ApplicationDomain::Mail &mail); | ||
31 | }; | ||
32 | |||
33 | class SINK_EXPORT MimeMessageMover : public Sink::EntityPreprocessor<Sink::ApplicationDomain::Mail> | ||
34 | { | ||
35 | public: | ||
36 | MimeMessageMover(); | ||
37 | virtual ~MimeMessageMover(){} | ||
38 | |||
39 | void newEntity(Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE; | ||
40 | void modifiedEntity(const Sink::ApplicationDomain::Mail &oldMail, Sink::ApplicationDomain::Mail &newMail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE; | ||
41 | void deletedEntity(const Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE; | ||
42 | |||
43 | private: | ||
44 | QString moveMessage(const QString &oldPath, const Sink::ApplicationDomain::Mail &mail); | ||
45 | }; | ||
diff --git a/common/pipeline.cpp b/common/pipeline.cpp index 5d8a34c..63a60ce 100644 --- a/common/pipeline.cpp +++ b/common/pipeline.cpp | |||
@@ -46,7 +46,7 @@ namespace Sink { | |||
46 | class Pipeline::Private | 46 | class Pipeline::Private |
47 | { | 47 | { |
48 | public: | 48 | public: |
49 | Private(const QString &resourceName) : storage(Sink::storageLocation(), resourceName, Storage::ReadWrite), revisionChanged(false) | 49 | Private(const QString &resourceName) : storage(Sink::storageLocation(), resourceName, Storage::ReadWrite), revisionChanged(false), resourceInstanceIdentifier(resourceName.toUtf8()) |
50 | { | 50 | { |
51 | } | 51 | } |
52 | 52 | ||
@@ -58,6 +58,7 @@ public: | |||
58 | QTime transactionTime; | 58 | QTime transactionTime; |
59 | int transactionItemCount; | 59 | int transactionItemCount; |
60 | QByteArray resourceType; | 60 | QByteArray resourceType; |
61 | QByteArray resourceInstanceIdentifier; | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | void Pipeline::Private::storeNewRevision(qint64 newRevision, const flatbuffers::FlatBufferBuilder &fbb, const QByteArray &bufferType, const QByteArray &uid) | 64 | void Pipeline::Private::storeNewRevision(qint64 newRevision, const flatbuffers::FlatBufferBuilder &fbb, const QByteArray &bufferType, const QByteArray &uid) |
@@ -82,6 +83,9 @@ Pipeline::~Pipeline() | |||
82 | 83 | ||
83 | void Pipeline::setPreprocessors(const QString &entityType, const QVector<Preprocessor *> &processors) | 84 | void Pipeline::setPreprocessors(const QString &entityType, const QVector<Preprocessor *> &processors) |
84 | { | 85 | { |
86 | for (auto p : processors) { | ||
87 | p->setup(d->resourceType, d->resourceInstanceIdentifier, this); | ||
88 | } | ||
85 | d->processors[entityType] = processors; | 89 | d->processors[entityType] = processors; |
86 | } | 90 | } |
87 | 91 | ||
@@ -191,8 +195,6 @@ KAsync::Job<qint64> Pipeline::newEntity(void const *command, size_t size) | |||
191 | auto adaptor = adaptorFactory->createAdaptor(*entity); | 195 | auto adaptor = adaptorFactory->createAdaptor(*entity); |
192 | auto memoryAdaptor = QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create(*(adaptor), adaptor->availableProperties()); | 196 | auto memoryAdaptor = QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create(*(adaptor), adaptor->availableProperties()); |
193 | for (auto processor : d->processors[bufferType]) { | 197 | for (auto processor : d->processors[bufferType]) { |
194 | processor->resourceType = d->resourceType; | ||
195 | processor->pipeline = this; | ||
196 | processor->newEntity(key, Storage::maxRevision(d->transaction) + 1, *memoryAdaptor, d->transaction); | 198 | processor->newEntity(key, Storage::maxRevision(d->transaction) + 1, *memoryAdaptor, d->transaction); |
197 | } | 199 | } |
198 | //The maxRevision may have changed meanwhile if the entity created sub-entities | 200 | //The maxRevision may have changed meanwhile if the entity created sub-entities |
@@ -303,8 +305,6 @@ KAsync::Job<qint64> Pipeline::modifiedEntity(void const *command, size_t size) | |||
303 | } | 305 | } |
304 | 306 | ||
305 | for (auto processor : d->processors[bufferType]) { | 307 | for (auto processor : d->processors[bufferType]) { |
306 | processor->resourceType = d->resourceType; | ||
307 | processor->pipeline = this; | ||
308 | processor->modifiedEntity(key, Storage::maxRevision(d->transaction) + 1, *current, *newAdaptor, d->transaction); | 308 | processor->modifiedEntity(key, Storage::maxRevision(d->transaction) + 1, *current, *newAdaptor, d->transaction); |
309 | } | 309 | } |
310 | //The maxRevision may have changed meanwhile if the entity created sub-entities | 310 | //The maxRevision may have changed meanwhile if the entity created sub-entities |
@@ -452,12 +452,27 @@ qint64 Pipeline::cleanedUpRevision() | |||
452 | return Storage::cleanedUpRevision(d->transaction); | 452 | return Storage::cleanedUpRevision(d->transaction); |
453 | } | 453 | } |
454 | 454 | ||
455 | Preprocessor::Preprocessor() : d(0) | 455 | class Preprocessor::Private { |
456 | public: | ||
457 | QByteArray resourceType; | ||
458 | QByteArray resourceInstanceIdentifier; | ||
459 | Pipeline *pipeline; | ||
460 | }; | ||
461 | |||
462 | Preprocessor::Preprocessor() : d(new Preprocessor::Private) | ||
456 | { | 463 | { |
457 | } | 464 | } |
458 | 465 | ||
459 | Preprocessor::~Preprocessor() | 466 | Preprocessor::~Preprocessor() |
460 | { | 467 | { |
468 | delete d; | ||
469 | } | ||
470 | |||
471 | void Preprocessor::setup(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier, Pipeline *pipeline) | ||
472 | { | ||
473 | d->resourceType = resourceType; | ||
474 | d->resourceInstanceIdentifier = resourceInstanceIdentifier; | ||
475 | d->pipeline = pipeline; | ||
461 | } | 476 | } |
462 | 477 | ||
463 | void Preprocessor::startBatch() | 478 | void Preprocessor::startBatch() |
@@ -468,10 +483,15 @@ void Preprocessor::finalize() | |||
468 | { | 483 | { |
469 | } | 484 | } |
470 | 485 | ||
486 | QByteArray Preprocessor::resourceInstanceIdentifier() const | ||
487 | { | ||
488 | return d->resourceInstanceIdentifier; | ||
489 | } | ||
490 | |||
471 | void Preprocessor::createEntity(const Sink::ApplicationDomain::ApplicationDomainType &entity, const QByteArray &typeName) | 491 | void Preprocessor::createEntity(const Sink::ApplicationDomain::ApplicationDomainType &entity, const QByteArray &typeName) |
472 | { | 492 | { |
473 | flatbuffers::FlatBufferBuilder entityFbb; | 493 | flatbuffers::FlatBufferBuilder entityFbb; |
474 | auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(resourceType, typeName); | 494 | auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(d->resourceType, typeName); |
475 | adaptorFactory->createBuffer(entity, entityFbb); | 495 | adaptorFactory->createBuffer(entity, entityFbb); |
476 | const auto entityBuffer = BufferUtils::extractBuffer(entityFbb); | 496 | const auto entityBuffer = BufferUtils::extractBuffer(entityFbb); |
477 | 497 | ||
@@ -484,7 +504,7 @@ void Preprocessor::createEntity(const Sink::ApplicationDomain::ApplicationDomain | |||
484 | Sink::Commands::FinishCreateEntityBuffer(fbb, location); | 504 | Sink::Commands::FinishCreateEntityBuffer(fbb, location); |
485 | 505 | ||
486 | const auto data = BufferUtils::extractBuffer(fbb); | 506 | const auto data = BufferUtils::extractBuffer(fbb); |
487 | pipeline->newEntity(data, data.size()).exec(); | 507 | d->pipeline->newEntity(data, data.size()).exec(); |
488 | } | 508 | } |
489 | 509 | ||
490 | } // namespace Sink | 510 | } // namespace Sink |
diff --git a/common/pipeline.h b/common/pipeline.h index 1afda21..d04d795 100644 --- a/common/pipeline.h +++ b/common/pipeline.h | |||
@@ -88,6 +88,8 @@ public: | |||
88 | virtual void deletedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, Sink::Storage::Transaction &transaction) {}; | 88 | virtual void deletedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, Sink::Storage::Transaction &transaction) {}; |
89 | virtual void finalize(); | 89 | virtual void finalize(); |
90 | 90 | ||
91 | void setup(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier, Pipeline *); | ||
92 | |||
91 | protected: | 93 | protected: |
92 | template <typename DomainType> | 94 | template <typename DomainType> |
93 | void createEntity(const DomainType &entity) | 95 | void createEntity(const DomainType &entity) |
@@ -96,12 +98,12 @@ protected: | |||
96 | } | 98 | } |
97 | void createEntity(const Sink::ApplicationDomain::ApplicationDomainType &entity, const QByteArray &type); | 99 | void createEntity(const Sink::ApplicationDomain::ApplicationDomainType &entity, const QByteArray &type); |
98 | 100 | ||
101 | QByteArray resourceInstanceIdentifier() const; | ||
102 | |||
99 | private: | 103 | private: |
100 | friend class Pipeline; | 104 | friend class Pipeline; |
101 | class Private; | 105 | class Private; |
102 | Private *const d; | 106 | Private *const d; |
103 | Pipeline *pipeline; | ||
104 | QByteArray resourceType; | ||
105 | }; | 107 | }; |
106 | 108 | ||
107 | template<typename DomainType> | 109 | template<typename DomainType> |
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp index 7226fd5..f9168e4 100644 --- a/examples/imapresource/imapresource.cpp +++ b/examples/imapresource/imapresource.cpp | |||
@@ -47,6 +47,7 @@ | |||
47 | 47 | ||
48 | #include "imapserverproxy.h" | 48 | #include "imapserverproxy.h" |
49 | #include "entityreader.h" | 49 | #include "entityreader.h" |
50 | #include "mailpreprocessor.h" | ||
50 | 51 | ||
51 | //This is the resources entity type, and not the domain type | 52 | //This is the resources entity type, and not the domain type |
52 | #define ENTITY_TYPE_MAIL "mail" | 53 | #define ENTITY_TYPE_MAIL "mail" |
@@ -136,98 +137,6 @@ public: | |||
136 | QByteArray mResourceInstanceIdentifier; | 137 | QByteArray mResourceInstanceIdentifier; |
137 | }; | 138 | }; |
138 | 139 | ||
139 | class MailPropertyExtractor : public Sink::EntityPreprocessor<ApplicationDomain::Mail> | ||
140 | { | ||
141 | public: | ||
142 | |||
143 | void updatedIndexedProperties(Sink::ApplicationDomain::Mail &mail) | ||
144 | { | ||
145 | const auto mimeMessagePath = mail.getMimeMessagePath(); | ||
146 | Trace() << "Updating indexed properties " << mimeMessagePath; | ||
147 | QFile f(mimeMessagePath); | ||
148 | if (!f.open(QIODevice::ReadOnly)) { | ||
149 | Warning() << "Failed to open the file: " << mimeMessagePath; | ||
150 | return; | ||
151 | } | ||
152 | if (!f.size()) { | ||
153 | Warning() << "The file is empty."; | ||
154 | return; | ||
155 | } | ||
156 | const auto mappedSize = qMin((qint64)8000, f.size()); | ||
157 | auto mapped = f.map(0, mappedSize); | ||
158 | if (!mapped) { | ||
159 | Warning() << "Failed to map the file: " << f.errorString(); | ||
160 | return; | ||
161 | } | ||
162 | |||
163 | KMime::Message *msg = new KMime::Message; | ||
164 | msg->setHead(KMime::CRLFtoLF(QByteArray::fromRawData(reinterpret_cast<const char*>(mapped), mappedSize))); | ||
165 | msg->parse(); | ||
166 | |||
167 | mail.setExtractedSubject(msg->subject(true)->asUnicodeString()); | ||
168 | mail.setExtractedSender(msg->from(true)->asUnicodeString()); | ||
169 | mail.setExtractedSenderName(msg->from(true)->asUnicodeString()); | ||
170 | mail.setExtractedDate(msg->date(true)->dateTime()); | ||
171 | } | ||
172 | |||
173 | void newEntity(Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
174 | { | ||
175 | updatedIndexedProperties(mail); | ||
176 | } | ||
177 | |||
178 | void modifiedEntity(const Sink::ApplicationDomain::Mail &oldMail, Sink::ApplicationDomain::Mail &newMail,Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
179 | { | ||
180 | updatedIndexedProperties(newMail); | ||
181 | } | ||
182 | }; | ||
183 | |||
184 | class MimeMessageMover : public Sink::EntityPreprocessor<ApplicationDomain::Mail> | ||
185 | { | ||
186 | public: | ||
187 | MimeMessageMover(const QByteArray &resourceInstanceIdentifier) : Sink::EntityPreprocessor<ApplicationDomain::Mail>(), mResourceInstanceIdentifier(resourceInstanceIdentifier) {} | ||
188 | |||
189 | QString moveMessage(const QString &oldPath, const Sink::ApplicationDomain::Mail &mail) | ||
190 | { | ||
191 | const auto directory = Sink::resourceStorageLocation(mResourceInstanceIdentifier); | ||
192 | const auto filePath = directory + "/" + mail.identifier(); | ||
193 | if (oldPath != filePath) { | ||
194 | if (!QDir().mkpath(directory)) { | ||
195 | Warning() << "Failed to create the directory: " << directory; | ||
196 | } | ||
197 | QFile::remove(filePath); | ||
198 | QFile origFile(oldPath); | ||
199 | if (!origFile.open(QIODevice::ReadWrite)) { | ||
200 | Warning() << "Failed to open the original file with write rights: " << origFile.errorString(); | ||
201 | } | ||
202 | if (!origFile.rename(filePath)) { | ||
203 | Warning() << "Failed to move the file from: " << oldPath << " to " << filePath << ". " << origFile.errorString(); | ||
204 | } | ||
205 | origFile.close(); | ||
206 | return filePath; | ||
207 | } | ||
208 | return oldPath; | ||
209 | } | ||
210 | |||
211 | void newEntity(Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
212 | { | ||
213 | if (!mail.getMimeMessagePath().isEmpty()) { | ||
214 | mail.setMimeMessagePath(moveMessage(mail.getMimeMessagePath(), mail)); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | void modifiedEntity(const Sink::ApplicationDomain::Mail &oldMail, Sink::ApplicationDomain::Mail &newMail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
219 | { | ||
220 | if (!newMail.getMimeMessagePath().isEmpty()) { | ||
221 | newMail.setMimeMessagePath(moveMessage(newMail.getMimeMessagePath(), newMail)); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | void deletedEntity(const Sink::ApplicationDomain::Mail &mail, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
226 | { | ||
227 | QFile::remove(mail.getMimeMessagePath()); | ||
228 | } | ||
229 | QByteArray mResourceInstanceIdentifier; | ||
230 | }; | ||
231 | 140 | ||
232 | static qint64 uidFromMailRid(const QByteArray &remoteId) | 141 | static qint64 uidFromMailRid(const QByteArray &remoteId) |
233 | { | 142 | { |
@@ -651,7 +560,7 @@ ImapResource::ImapResource(const QByteArray &instanceIdentifier, const QSharedPo | |||
651 | changereplay->mPassword = mPassword; | 560 | changereplay->mPassword = mPassword; |
652 | setupChangereplay(changereplay); | 561 | setupChangereplay(changereplay); |
653 | 562 | ||
654 | setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new SpecialPurposeProcessor(mResourceType, mResourceInstanceIdentifier) << new MimeMessageMover(mResourceInstanceIdentifier) << new MailPropertyExtractor << new DefaultIndexUpdater<Sink::ApplicationDomain::Mail>); | 563 | setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new SpecialPurposeProcessor(mResourceType, mResourceInstanceIdentifier) << new MimeMessageMover << new MailPropertyExtractor << new DefaultIndexUpdater<Sink::ApplicationDomain::Mail>); |
655 | setupPreprocessors(ENTITY_TYPE_FOLDER, QVector<Sink::Preprocessor*>() << new DefaultIndexUpdater<Sink::ApplicationDomain::Folder>); | 564 | setupPreprocessors(ENTITY_TYPE_FOLDER, QVector<Sink::Preprocessor*>() << new DefaultIndexUpdater<Sink::ApplicationDomain::Folder>); |
656 | } | 565 | } |
657 | 566 | ||