diff options
Diffstat (limited to 'examples/davresource/davresource.cpp')
-rw-r--r-- | examples/davresource/davresource.cpp | 374 |
1 files changed, 44 insertions, 330 deletions
diff --git a/examples/davresource/davresource.cpp b/examples/davresource/davresource.cpp index df2c4b4..3d23a04 100644 --- a/examples/davresource/davresource.cpp +++ b/examples/davresource/davresource.cpp | |||
@@ -21,10 +21,8 @@ | |||
21 | 21 | ||
22 | #include "facade.h" | 22 | #include "facade.h" |
23 | #include "resourceconfig.h" | 23 | #include "resourceconfig.h" |
24 | #include "index.h" | ||
25 | #include "log.h" | 24 | #include "log.h" |
26 | #include "definitions.h" | 25 | #include "definitions.h" |
27 | #include "inspection.h" | ||
28 | #include "synchronizer.h" | 26 | #include "synchronizer.h" |
29 | #include "inspector.h" | 27 | #include "inspector.h" |
30 | 28 | ||
@@ -40,181 +38,14 @@ | |||
40 | #include <KDAV/DavItemFetchJob> | 38 | #include <KDAV/DavItemFetchJob> |
41 | #include <KDAV/EtagCache> | 39 | #include <KDAV/EtagCache> |
42 | 40 | ||
43 | #include <QDir> | ||
44 | #include <QDirIterator> | ||
45 | |||
46 | //This is the resources entity type, and not the domain type | 41 | //This is the resources entity type, and not the domain type |
47 | #define ENTITY_TYPE_CONTACT "contact" | 42 | #define ENTITY_TYPE_CONTACT "contact" |
48 | #define ENTITY_TYPE_ADDRESSBOOK "folder" | 43 | #define ENTITY_TYPE_ADDRESSBOOK "addressbook" |
49 | 44 | ||
50 | SINK_DEBUG_AREA("davresource") | 45 | SINK_DEBUG_AREA("davresource") |
51 | 46 | ||
52 | using namespace Sink; | 47 | using namespace Sink; |
53 | 48 | ||
54 | /*static QString getFilePathFromMimeMessagePath(const QString &mimeMessagePath) | ||
55 | { | ||
56 | auto parts = mimeMessagePath.split('/'); | ||
57 | const auto key = parts.takeLast(); | ||
58 | const auto path = parts.join("/") + "/cur/"; | ||
59 | |||
60 | QDir dir(path); | ||
61 | const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files); | ||
62 | if (list.size() != 1) { | ||
63 | SinkWarning() << "Failed to find message " << mimeMessagePath; | ||
64 | SinkWarning() << "Failed to find message " << path; | ||
65 | return QString(); | ||
66 | } | ||
67 | return list.first().filePath(); | ||
68 | } | ||
69 | |||
70 | class MaildirMailPropertyExtractor : public MailPropertyExtractor | ||
71 | { | ||
72 | protected: | ||
73 | virtual QString getFilePathFromMimeMessagePath(const QString &mimeMessagePath) const Q_DECL_OVERRIDE | ||
74 | { | ||
75 | return ::getFilePathFromMimeMessagePath(mimeMessagePath); | ||
76 | } | ||
77 | }; | ||
78 | |||
79 | class MaildirMimeMessageMover : public Sink::Preprocessor | ||
80 | { | ||
81 | public: | ||
82 | MaildirMimeMessageMover(const QByteArray &resourceInstanceIdentifier, const QString &maildirPath) : mResourceInstanceIdentifier(resourceInstanceIdentifier), mMaildirPath(maildirPath) {} | ||
83 | |||
84 | QString getPath(const QByteArray &folderIdentifier) | ||
85 | { | ||
86 | if (folderIdentifier.isEmpty()) { | ||
87 | return mMaildirPath; | ||
88 | } | ||
89 | QString folderPath; | ||
90 | const auto folder = entityStore().readLatest<ApplicationDomain::Folder>(folderIdentifier); | ||
91 | if (mMaildirPath.endsWith(folder.getName())) { | ||
92 | folderPath = mMaildirPath; | ||
93 | } else { | ||
94 | auto folderName = folder.getName(); | ||
95 | //FIXME handle non toplevel folders | ||
96 | folderPath = mMaildirPath + "/" + folderName; | ||
97 | } | ||
98 | return folderPath; | ||
99 | } | ||
100 | |||
101 | QString moveMessage(const QString &oldPath, const QByteArray &folder) | ||
102 | { | ||
103 | if (oldPath.startsWith(Sink::temporaryFileLocation())) { | ||
104 | const auto path = getPath(folder); | ||
105 | KPIM::Contactdir maildir(path, false); | ||
106 | if (!maildir.isValid(true)) { | ||
107 | SinkWarning() << "Maildir is not existing: " << path; | ||
108 | } | ||
109 | auto identifier = maildir.addEntryFromPath(oldPath); | ||
110 | return path + "/" + identifier; | ||
111 | } else { | ||
112 | //Handle moves | ||
113 | const auto path = getPath(folder); | ||
114 | KPIM::Contactdir maildir(path, false); | ||
115 | if (!maildir.isValid(true)) { | ||
116 | SinkWarning() << "Maildir is not existing: " << path; | ||
117 | } | ||
118 | auto oldIdentifier = KPIM::Contactdir::getKeyFromFile(oldPath); | ||
119 | auto pathParts = oldPath.split('/'); | ||
120 | pathParts.takeLast(); | ||
121 | auto oldDirectory = pathParts.join('/'); | ||
122 | if (oldDirectory == path) { | ||
123 | return oldPath; | ||
124 | } | ||
125 | KPIM::Contactdir oldMaildir(oldDirectory, false); | ||
126 | if (!oldMaildir.isValid(false)) { | ||
127 | SinkWarning() << "Maildir is not existing: " << path; | ||
128 | } | ||
129 | auto identifier = oldMaildir.moveEntryTo(oldIdentifier, maildir); | ||
130 | return path + "/" + identifier; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | void newEntity(Sink::ApplicationDomain::ApplicationDomainType &newEntity) Q_DECL_OVERRIDE | ||
135 | { | ||
136 | auto mail = newEntity.cast<ApplicationDomain::Contact>(); | ||
137 | const auto mimeMessage = mail.getMimeMessagePath(); | ||
138 | if (!mimeMessage.isNull()) { | ||
139 | const auto path = moveMessage(mimeMessage, mail.getFolder()); | ||
140 | auto blob = ApplicationDomain::BLOB{path}; | ||
141 | blob.isExternal = false; | ||
142 | mail.setProperty(ApplicationDomain::Contact::MimeMessage::name, QVariant::fromValue(blob)); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | void modifiedEntity(const Sink::ApplicationDomain::ApplicationDomainType &oldEntity, Sink::ApplicationDomain::ApplicationDomainType &newEntity) Q_DECL_OVERRIDE | ||
147 | { | ||
148 | auto newMail = newEntity.cast<ApplicationDomain::Contact>(); | ||
149 | const ApplicationDomain::Contact oldMail{oldEntity}; | ||
150 | const auto mimeMessage = newMail.getMimeMessagePath(); | ||
151 | const auto newFolder = newMail.getFolder(); | ||
152 | const bool mimeMessageChanged = !mimeMessage.isNull() && mimeMessage != oldMail.getMimeMessagePath(); | ||
153 | const bool folderChanged = !newFolder.isNull() && newFolder != oldMail.getFolder(); | ||
154 | if (mimeMessageChanged || folderChanged) { | ||
155 | SinkTrace() << "Moving mime message: " << mimeMessageChanged << folderChanged; | ||
156 | auto newPath = moveMessage(mimeMessage, newMail.getFolder()); | ||
157 | if (newPath != oldMail.getMimeMessagePath()) { | ||
158 | const auto oldPath = getFilePathFromMimeMessagePath(oldMail.getMimeMessagePath()); | ||
159 | auto blob = ApplicationDomain::BLOB{newPath}; | ||
160 | blob.isExternal = false; | ||
161 | newMail.setProperty(ApplicationDomain::Contact::MimeMessage::name, QVariant::fromValue(blob)); | ||
162 | //Remove the olde mime message if there is a new one | ||
163 | QFile::remove(oldPath); | ||
164 | } | ||
165 | } | ||
166 | |||
167 | auto mimeMessagePath = newMail.getMimeMessagePath(); | ||
168 | const auto maildirPath = getPath(newMail.getFolder()); | ||
169 | KPIM::Contactdir maildir(maildirPath, false); | ||
170 | const auto file = getFilePathFromMimeMessagePath(mimeMessagePath); | ||
171 | QString identifier = KPIM::Contactdir::getKeyFromFile(file); | ||
172 | |||
173 | //get flags from | ||
174 | KPIM::Contactdir::Flags flags; | ||
175 | if (!newMail.getUnread()) { | ||
176 | flags |= KPIM::Contactdir::Seen; | ||
177 | } | ||
178 | if (newMail.getImportant()) { | ||
179 | flags |= KPIM::Contactdir::Flagged; | ||
180 | } | ||
181 | |||
182 | maildir.changeEntryFlags(identifier, flags); | ||
183 | } | ||
184 | |||
185 | void deletedEntity(const Sink::ApplicationDomain::ApplicationDomainType &oldEntity) Q_DECL_OVERRIDE | ||
186 | { | ||
187 | const ApplicationDomain::Contact oldMail{oldEntity}; | ||
188 | const auto filePath = getFilePathFromMimeMessagePath(oldMail.getMimeMessagePath()); | ||
189 | QFile::remove(filePath); | ||
190 | } | ||
191 | QByteArray mResourceInstanceIdentifier; | ||
192 | QString mMaildirPath; | ||
193 | }; | ||
194 | |||
195 | class FolderPreprocessor : public Sink::Preprocessor | ||
196 | { | ||
197 | public: | ||
198 | FolderPreprocessor(const QString maildirPath) : mMaildirPath(maildirPath) {} | ||
199 | |||
200 | void newEntity(Sink::ApplicationDomain::ApplicationDomainType &newEntity) Q_DECL_OVERRIDE | ||
201 | { | ||
202 | auto folderName = Sink::ApplicationDomain::Folder{newEntity}.getName(); | ||
203 | const auto path = mMaildirPath + "/" + folderName; | ||
204 | KPIM::Contactdir maildir(path, false); | ||
205 | maildir.create(); | ||
206 | } | ||
207 | |||
208 | void modifiedEntity(const Sink::ApplicationDomain::ApplicationDomainType &oldEntity, Sink::ApplicationDomain::ApplicationDomainType &newEntity) Q_DECL_OVERRIDE | ||
209 | { | ||
210 | } | ||
211 | |||
212 | void deletedEntity(const Sink::ApplicationDomain::ApplicationDomainType &oldEntity) Q_DECL_OVERRIDE | ||
213 | { | ||
214 | } | ||
215 | QString mMaildirPath; | ||
216 | };*/ | ||
217 | |||
218 | static KAsync::Job<void> runJob(KJob *job) | 49 | static KAsync::Job<void> runJob(KJob *job) |
219 | { | 50 | { |
220 | return KAsync::start<void>([job](KAsync::Future<void> &future) { | 51 | return KAsync::start<void>([job](KAsync::Future<void> &future) { |
@@ -240,33 +71,33 @@ public: | |||
240 | 71 | ||
241 | } | 72 | } |
242 | 73 | ||
243 | QByteArray createAddressbook(const QString &folderName, const QString &folderPath, const QString &parentFolderRid, const QByteArray &icon) | 74 | QByteArray createAddressbook(const QString &addressbookName, const QString &addressbookPath, const QString &parentAddressbookRid) |
244 | { | 75 | { |
245 | SinkTrace() << "Creating addressbook: " << folderName << parentFolderRid; | 76 | SinkTrace() << "Creating addressbook: " << addressbookName << parentAddressbookRid; |
246 | const auto remoteId = folderPath.toUtf8(); | 77 | const auto remoteId = addressbookPath.toUtf8(); |
247 | const auto bufferType = ENTITY_TYPE_ADDRESSBOOK; | 78 | const auto bufferType = ENTITY_TYPE_ADDRESSBOOK; |
248 | Sink::ApplicationDomain::Folder folder; | 79 | Sink::ApplicationDomain::Addressbook addressbook; |
249 | folder.setName(folderName); | 80 | addressbook.setName(addressbookName); |
250 | folder.setIcon(icon); | ||
251 | QHash<QByteArray, Query::Comparator> mergeCriteria; | 81 | QHash<QByteArray, Query::Comparator> mergeCriteria; |
252 | 82 | ||
253 | if (!parentFolderRid.isEmpty()) { | 83 | if (!parentAddressbookRid.isEmpty()) { |
254 | folder.setParent(syncStore().resolveRemoteId(ENTITY_TYPE_ADDRESSBOOK, parentFolderRid.toUtf8())); | 84 | addressbook.setParent(syncStore().resolveRemoteId(ENTITY_TYPE_ADDRESSBOOK, parentAddressbookRid.toUtf8())); |
255 | } | 85 | } |
256 | createOrModify(bufferType, remoteId, folder, mergeCriteria); | 86 | createOrModify(bufferType, remoteId, addressbook, mergeCriteria); |
257 | return remoteId; | 87 | return remoteId; |
258 | } | 88 | } |
259 | 89 | ||
260 | void synchronizeAddressbooks(const KDAV::DavCollection::List &folderList) | 90 | void synchronizeAddressbooks(const KDAV::DavCollection::List &addressbookList) |
261 | { | 91 | { |
262 | const QByteArray bufferType = ENTITY_TYPE_ADDRESSBOOK; | 92 | const QByteArray bufferType = ENTITY_TYPE_ADDRESSBOOK; |
263 | SinkTrace() << "Found addressbooks " << folderList.size(); | 93 | SinkTrace() << "Found addressbooks " << addressbookList.size(); |
264 | 94 | ||
265 | QVector<QByteArray> ridList; | 95 | QVector<QByteArray> ridList; |
266 | for(const auto &f : folderList) { | 96 | for(const auto &f : addressbookList) { |
267 | const auto &rid = f.url().toDisplayString(); | 97 | const auto &rid = getRid(f); |
268 | ridList.append(rid.toUtf8()); | 98 | SinkTrace() << "Found addressbook:" << rid; |
269 | createAddressbook(f.displayName(), rid, "", "addressbook"); | 99 | ridList.append(rid); |
100 | createAddressbook(f.displayName(), rid, ""); | ||
270 | } | 101 | } |
271 | 102 | ||
272 | scanForRemovals(bufferType, | 103 | scanForRemovals(bufferType, |
@@ -284,21 +115,32 @@ public: | |||
284 | list << Synchronizer::SyncRequest{query}; | 115 | list << Synchronizer::SyncRequest{query}; |
285 | } else { | 116 | } else { |
286 | //We want to synchronize everything | 117 | //We want to synchronize everything |
287 | list << Synchronizer::SyncRequest{Sink::QueryBase(ApplicationDomain::getTypeName<ApplicationDomain::Folder>())}; | 118 | list << Synchronizer::SyncRequest{Sink::QueryBase(ApplicationDomain::getTypeName<ApplicationDomain::Addressbook>())}; |
288 | list << Synchronizer::SyncRequest{Sink::QueryBase(ApplicationDomain::getTypeName<ApplicationDomain::Contact>())}; | 119 | list << Synchronizer::SyncRequest{Sink::QueryBase(ApplicationDomain::getTypeName<ApplicationDomain::Contact>())}; |
289 | } | 120 | } |
290 | return list; | 121 | return list; |
291 | } | 122 | } |
292 | 123 | ||
124 | static QByteArray getRid(const KDAV::DavItem &item) | ||
125 | { | ||
126 | return item.url().toDisplayString().toUtf8(); | ||
127 | } | ||
128 | |||
129 | static QByteArray getRid(const KDAV::DavCollection &item) | ||
130 | { | ||
131 | return item.url().toDisplayString().toUtf8(); | ||
132 | } | ||
133 | |||
293 | KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE | 134 | KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE |
294 | { | 135 | { |
295 | if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Folder>()) { | 136 | if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Addressbook>()) { |
296 | SinkLogCtx(mLogCtx) << "Synchronizing folders:" << mResourceUrl.url(); | 137 | SinkLogCtx(mLogCtx) << "Synchronizing addressbooks:" << mResourceUrl.url(); |
297 | auto collectionsFetchJob = new KDAV::DavCollectionsFetchJob(mResourceUrl); | 138 | auto collectionsFetchJob = new KDAV::DavCollectionsFetchJob(mResourceUrl); |
298 | auto job = runJob(collectionsFetchJob).then([this, collectionsFetchJob] (const KAsync::Error &error) { | 139 | auto job = runJob(collectionsFetchJob).then([this, collectionsFetchJob] (const KAsync::Error &error) { |
299 | if (error) { | 140 | if (error) { |
300 | SinkWarningCtx(mLogCtx) << "Failed to synchronize folders." << collectionsFetchJob->errorString(); | 141 | SinkWarningCtx(mLogCtx) << "Failed to synchronize addressbooks." << collectionsFetchJob->errorString(); |
301 | } else { | 142 | } else { |
143 | SinkWarningCtx(mLogCtx) << "Fetched addressbooks." << collectionsFetchJob->errorString(); | ||
302 | synchronizeAddressbooks(collectionsFetchJob ->collections()); | 144 | synchronizeAddressbooks(collectionsFetchJob ->collections()); |
303 | } | 145 | } |
304 | }); | 146 | }); |
@@ -312,7 +154,8 @@ public: | |||
312 | return collectionsFetchJob->collections(); | 154 | return collectionsFetchJob->collections(); |
313 | }) | 155 | }) |
314 | .serialEach([this, ridList](const KDAV::DavCollection &collection) { | 156 | .serialEach([this, ridList](const KDAV::DavCollection &collection) { |
315 | auto collId = collection.url().toDisplayString().toLatin1(); | 157 | auto collId = getRid(collection); |
158 | const auto addressbookLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_ADDRESSBOOK, collId); | ||
316 | auto ctag = collection.CTag().toLatin1(); | 159 | auto ctag = collection.CTag().toLatin1(); |
317 | if (ctag != syncStore().readValue(collId + "_ctagXX")) { | 160 | if (ctag != syncStore().readValue(collId + "_ctagXX")) { |
318 | SinkTraceCtx(mLogCtx) << "Syncing " << collId; | 161 | SinkTraceCtx(mLogCtx) << "Syncing " << collId; |
@@ -323,22 +166,23 @@ public: | |||
323 | auto colljob = runJob(davItemsListJob).then([davItemsListJob] { | 166 | auto colljob = runJob(davItemsListJob).then([davItemsListJob] { |
324 | return KAsync::value(davItemsListJob->items()); | 167 | return KAsync::value(davItemsListJob->items()); |
325 | }) | 168 | }) |
326 | .serialEach([this, ridList, bufferType, mergeCriteria] (const KDAV::DavItem &item) { | 169 | .serialEach([=] (const KDAV::DavItem &item) { |
327 | QByteArray rid = item.url().toDisplayString().toUtf8(); | 170 | QByteArray rid = getRid(item); |
328 | if (item.etag().toLatin1() != syncStore().readValue(rid + "_etag")){ | 171 | if (item.etag().toLatin1() != syncStore().readValue(rid + "_etag")){ |
329 | SinkTrace() << "Updating " << rid; | 172 | SinkTrace() << "Updating " << rid; |
330 | auto davItemFetchJob = new KDAV::DavItemFetchJob(item); | 173 | auto davItemFetchJob = new KDAV::DavItemFetchJob(item); |
331 | auto itemjob = runJob(davItemFetchJob) | 174 | auto itemjob = runJob(davItemFetchJob) |
332 | .then([this, davItemFetchJob, bufferType, mergeCriteria] { | 175 | .then([=] { |
333 | const auto item = davItemFetchJob->item(); | 176 | const auto item = davItemFetchJob->item(); |
334 | const auto rid = item.url().toDisplayString().toUtf8(); | 177 | const auto rid = getRid(item); |
335 | Sink::ApplicationDomain::Contact contact; | 178 | Sink::ApplicationDomain::Contact contact; |
336 | contact.setVcard(item.data()); | 179 | contact.setVcard(item.data()); |
180 | contact.setAddressbook(addressbookLocalId); | ||
337 | createOrModify(bufferType, rid, contact, mergeCriteria); | 181 | createOrModify(bufferType, rid, contact, mergeCriteria); |
338 | return item; | 182 | return item; |
339 | }) | 183 | }) |
340 | .then([this, ridList] (const KDAV::DavItem &item) { | 184 | .then([this, ridList] (const KDAV::DavItem &item) { |
341 | const auto rid = item.url().toDisplayString().toUtf8(); | 185 | const auto rid = getRid(item); |
342 | syncStore().writeValue(rid + "_etag", item.etag().toLatin1()); | 186 | syncStore().writeValue(rid + "_etag", item.etag().toLatin1()); |
343 | ridList->append(rid); | 187 | ridList->append(rid); |
344 | return rid; | 188 | return rid; |
@@ -375,43 +219,11 @@ public: | |||
375 | 219 | ||
376 | KAsync::Job<QByteArray> replay(const ApplicationDomain::Contact &contact, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE | 220 | KAsync::Job<QByteArray> replay(const ApplicationDomain::Contact &contact, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE |
377 | { | 221 | { |
378 | /* | ||
379 | if (operation == Sink::Operation_Creation) { | ||
380 | const auto remoteId = getFilePathFromMimeMessagePath(mail.getMimeMessagePath()); | ||
381 | SinkTrace() << "Contact created: " << remoteId; | ||
382 | return KAsync::value(remoteId.toUtf8()); | ||
383 | } else if (operation == Sink::Operation_Removal) { | ||
384 | SinkTrace() << "Removing a contact " << oldRemoteId; | ||
385 | return KAsync::null<QByteArray>(); | ||
386 | } else if (operation == Sink::Operation_Modification) { | ||
387 | SinkTrace() << "Modifying a contact: " << oldRemoteId; | ||
388 | const auto remoteId = getFilePathFromMimeMessagePath(mail.getMimeMessagePath()); | ||
389 | return KAsync::value(remoteId.toUtf8()); | ||
390 | }*/ | ||
391 | return KAsync::null<QByteArray>(); | 222 | return KAsync::null<QByteArray>(); |
392 | } | 223 | } |
393 | 224 | ||
394 | KAsync::Job<QByteArray> replay(const ApplicationDomain::Folder &folder, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE | 225 | KAsync::Job<QByteArray> replay(const ApplicationDomain::Addressbook &addressbook, Sink::Operation operation, const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE |
395 | { | 226 | { |
396 | /* | ||
397 | if (operation == Sink::Operation_Creation) { | ||
398 | auto folderName = folder.getName(); | ||
399 | //FIXME handle non toplevel folders | ||
400 | auto path = mMaildirPath + "/" + folderName; | ||
401 | SinkTrace() << "Creating a new folder: " << path; | ||
402 | KPIM::Contactdir maildir(path, false); | ||
403 | maildir.create(); | ||
404 | return KAsync::value(path.toUtf8()); | ||
405 | } else if (operation == Sink::Operation_Removal) { | ||
406 | const auto path = oldRemoteId; | ||
407 | SinkTrace() << "Removing a folder: " << path; | ||
408 | KPIM::Contactdir maildir(path, false); | ||
409 | maildir.remove(); | ||
410 | return KAsync::null<QByteArray>(); | ||
411 | } else if (operation == Sink::Operation_Modification) { | ||
412 | SinkWarning() << "Folder modifications are not implemented"; | ||
413 | return KAsync::value(oldRemoteId); | ||
414 | }*/ | ||
415 | return KAsync::null<QByteArray>(); | 227 | return KAsync::null<QByteArray>(); |
416 | } | 228 | } |
417 | 229 | ||
@@ -419,103 +231,6 @@ public: | |||
419 | KDAV::DavUrl mResourceUrl; | 231 | KDAV::DavUrl mResourceUrl; |
420 | }; | 232 | }; |
421 | 233 | ||
422 | /* | ||
423 | class MaildirInspector : public Sink::Inspector { | ||
424 | public: | ||
425 | MaildirInspector(const Sink::ResourceContext &resourceContext) | ||
426 | : Sink::Inspector(resourceContext) | ||
427 | { | ||
428 | |||
429 | } | ||
430 | protected: | ||
431 | |||
432 | KAsync::Job<void> inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) Q_DECL_OVERRIDE { | ||
433 | auto synchronizationStore = QSharedPointer<Sink::Storage::DataStore>::create(Sink::storageLocation(), mResourceContext.instanceId() + ".synchronization", Sink::Storage::DataStore::ReadOnly); | ||
434 | auto synchronizationTransaction = synchronizationStore->createTransaction(Sink::Storage::DataStore::ReadOnly); | ||
435 | |||
436 | auto mainStore = QSharedPointer<Sink::Storage::DataStore>::create(Sink::storageLocation(), mResourceContext.instanceId(), Sink::Storage::DataStore::ReadOnly); | ||
437 | auto transaction = mainStore->createTransaction(Sink::Storage::DataStore::ReadOnly); | ||
438 | |||
439 | Sink::Storage::EntityStore entityStore(mResourceContext, {"maildirresource"}); | ||
440 | auto syncStore = QSharedPointer<SynchronizerStore>::create(synchronizationTransaction); | ||
441 | |||
442 | SinkTrace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue; | ||
443 | |||
444 | if (domainType == ENTITY_TYPE_MAIL) { | ||
445 | auto mail = entityStore.readLatest<Sink::ApplicationDomain::Contact>(entityId); | ||
446 | const auto filePath = getFilePathFromMimeMessagePath(mail.getMimeMessagePath()); | ||
447 | |||
448 | if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) { | ||
449 | if (property == "unread") { | ||
450 | const auto flags = KPIM::Contactdir::readEntryFlags(filePath.split('/').last()); | ||
451 | if (expectedValue.toBool() && (flags & KPIM::Contactdir::Seen)) { | ||
452 | return KAsync::error<void>(1, "Expected unread but couldn't find it."); | ||
453 | } | ||
454 | if (!expectedValue.toBool() && !(flags & KPIM::Contactdir::Seen)) { | ||
455 | return KAsync::error<void>(1, "Expected read but couldn't find it."); | ||
456 | } | ||
457 | return KAsync::null<void>(); | ||
458 | } | ||
459 | if (property == "subject") { | ||
460 | KMime::Message *msg = new KMime::Message; | ||
461 | msg->setHead(KMime::CRLFtoLF(KPIM::Contactdir::readEntryHeadersFromFile(filePath))); | ||
462 | msg->parse(); | ||
463 | |||
464 | if (msg->subject(true)->asUnicodeString() != expectedValue.toString()) { | ||
465 | return KAsync::error<void>(1, "Subject not as expected: " + msg->subject(true)->asUnicodeString()); | ||
466 | } | ||
467 | return KAsync::null<void>(); | ||
468 | } | ||
469 | } | ||
470 | if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) { | ||
471 | if (QFileInfo(filePath).exists() != expectedValue.toBool()) { | ||
472 | return KAsync::error<void>(1, "Wrong file existence: " + filePath); | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | if (domainType == ENTITY_TYPE_FOLDER) { | ||
477 | const auto remoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, entityId); | ||
478 | auto folder = entityStore.readLatest<Sink::ApplicationDomain::Folder>(entityId); | ||
479 | |||
480 | if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) { | ||
481 | SinkTrace() << "Inspecting cache integrity" << remoteId; | ||
482 | if (!QDir(remoteId).exists()) { | ||
483 | return KAsync::error<void>(1, "The directory is not existing: " + remoteId); | ||
484 | } | ||
485 | |||
486 | int expectedCount = 0; | ||
487 | Index index("mail.index.folder", transaction); | ||
488 | index.lookup(entityId, [&](const QByteArray &sinkId) { | ||
489 | expectedCount++; | ||
490 | }, | ||
491 | [&](const Index::Error &error) { | ||
492 | SinkWarning() << "Error in index: " << error.message << property; | ||
493 | }); | ||
494 | |||
495 | QDir dir(remoteId + "/cur"); | ||
496 | const QFileInfoList list = dir.entryInfoList(QDir::Files); | ||
497 | if (list.size() != expectedCount) { | ||
498 | for (const auto &fileInfo : list) { | ||
499 | SinkWarning() << "Found in cache: " << fileInfo.fileName(); | ||
500 | } | ||
501 | return KAsync::error<void>(1, QString("Wrong number of files; found %1 instead of %2.").arg(list.size()).arg(expectedCount)); | ||
502 | } | ||
503 | } | ||
504 | if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) { | ||
505 | if (!remoteId.endsWith(folder.getName().toUtf8())) { | ||
506 | return KAsync::error<void>(1, "Wrong folder name: " + remoteId); | ||
507 | } | ||
508 | //TODO we shouldn't use the remoteId here to figure out the path, it could be gone/changed already | ||
509 | if (QDir(remoteId).exists() != expectedValue.toBool()) { | ||
510 | return KAsync::error<void>(1, "Wrong folder existence: " + remoteId); | ||
511 | } | ||
512 | } | ||
513 | |||
514 | } | ||
515 | return KAsync::null<void>(); | ||
516 | } | ||
517 | };*/ | ||
518 | |||
519 | 234 | ||
520 | DavResource::DavResource(const Sink::ResourceContext &resourceContext) | 235 | DavResource::DavResource(const Sink::ResourceContext &resourceContext) |
521 | : Sink::GenericResource(resourceContext) | 236 | : Sink::GenericResource(resourceContext) |
@@ -530,7 +245,6 @@ DavResource::DavResource(const Sink::ResourceContext &resourceContext) | |||
530 | auto synchronizer = QSharedPointer<ContactSynchronizer>::create(resourceContext); | 245 | auto synchronizer = QSharedPointer<ContactSynchronizer>::create(resourceContext); |
531 | synchronizer->mResourceUrl = mResourceUrl; | 246 | synchronizer->mResourceUrl = mResourceUrl; |
532 | setupSynchronizer(synchronizer); | 247 | setupSynchronizer(synchronizer); |
533 | //setupInspector(QSharedPointer<MaildirInspector>::create(resourceContext)); | ||
534 | 248 | ||
535 | setupPreprocessors(ENTITY_TYPE_CONTACT, QVector<Sink::Preprocessor*>() << new ContactPropertyExtractor); | 249 | setupPreprocessors(ENTITY_TYPE_CONTACT, QVector<Sink::Preprocessor*>() << new ContactPropertyExtractor); |
536 | } | 250 | } |
@@ -539,8 +253,8 @@ DavResource::DavResource(const Sink::ResourceContext &resourceContext) | |||
539 | DavResourceFactory::DavResourceFactory(QObject *parent) | 253 | DavResourceFactory::DavResourceFactory(QObject *parent) |
540 | : Sink::ResourceFactory(parent, | 254 | : Sink::ResourceFactory(parent, |
541 | {Sink::ApplicationDomain::ResourceCapabilities::Contact::contact, | 255 | {Sink::ApplicationDomain::ResourceCapabilities::Contact::contact, |
542 | Sink::ApplicationDomain::ResourceCapabilities::Mail::folder, | 256 | Sink::ApplicationDomain::ResourceCapabilities::Contact::addressbook, |
543 | "-folder.rename"} | 257 | } |
544 | ) | 258 | ) |
545 | { | 259 | { |
546 | } | 260 | } |
@@ -553,13 +267,13 @@ Sink::Resource *DavResourceFactory::createResource(const ResourceContext &contex | |||
553 | void DavResourceFactory::registerFacades(const QByteArray &name, Sink::FacadeFactory &factory) | 267 | void DavResourceFactory::registerFacades(const QByteArray &name, Sink::FacadeFactory &factory) |
554 | { | 268 | { |
555 | factory.registerFacade<Sink::ApplicationDomain::Contact, DavResourceContactFacade>(name); | 269 | factory.registerFacade<Sink::ApplicationDomain::Contact, DavResourceContactFacade>(name); |
556 | factory.registerFacade<Sink::ApplicationDomain::Folder, DavResourceFolderFacade>(name); | 270 | factory.registerFacade<Sink::ApplicationDomain::Addressbook, DavResourceAddressbookFacade>(name); |
557 | } | 271 | } |
558 | 272 | ||
559 | void DavResourceFactory::registerAdaptorFactories(const QByteArray &name, Sink::AdaptorFactoryRegistry ®istry) | 273 | void DavResourceFactory::registerAdaptorFactories(const QByteArray &name, Sink::AdaptorFactoryRegistry ®istry) |
560 | { | 274 | { |
561 | registry.registerFactory<Sink::ApplicationDomain::Contact, ContactAdaptorFactory>(name); | 275 | registry.registerFactory<Sink::ApplicationDomain::Contact, ContactAdaptorFactory>(name); |
562 | registry.registerFactory<Sink::ApplicationDomain::Folder, AddressbookAdaptorFactory>(name); | 276 | registry.registerFactory<Sink::ApplicationDomain::Addressbook, AddressbookAdaptorFactory>(name); |
563 | } | 277 | } |
564 | 278 | ||
565 | void DavResourceFactory::removeDataFromDisk(const QByteArray &instanceIdentifier) | 279 | void DavResourceFactory::removeDataFromDisk(const QByteArray &instanceIdentifier) |