Messagelib

autocryptstorage.cpp
1 /*
2  SPDX-FileCopyrightText: 2020 Sandro Kanuß <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "autocryptstorage.h"
8 #include "autocryptrecipient_p.h"
9 #include "autocryptstorage_p.h"
10 
11 #include <QDir>
12 #include <QFile>
13 #include <QStandardPaths>
14 #include <QTemporaryFile>
15 #include <QUrl>
16 #include <autocrypt_debug.h>
17 
18 using namespace MessageCore;
19 
20 AutocryptStoragePrivate::AutocryptStoragePrivate()
21  : basePath(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/autocrypt"))
22 {
23 }
24 
25 AutocryptStorage::Ptr AutocryptStorage::mSelf = nullptr;
26 
27 AutocryptStorage::Ptr AutocryptStorage::self()
28 {
29  if (!mSelf) {
30  mSelf = AutocryptStorage::Ptr(new AutocryptStorage());
31  }
32 
33  return mSelf;
34 }
35 
36 QString address2Filename(const QByteArray &addr)
37 {
38  const auto url = QUrl::toPercentEncoding(QString::fromUtf8(addr));
39  return QString::fromLatin1(url + ".json");
40 }
41 
42 AutocryptStorage::AutocryptStorage()
43  : d_ptr(new AutocryptStoragePrivate())
44 {
45 }
46 
47 AutocryptRecipient::Ptr AutocryptStorage::getRecipient(const QByteArray &addr)
48 {
49  Q_D(AutocryptStorage);
50  if (d->recipients.contains(addr)) {
51  return d->recipients.value(addr);
52  }
53 
54  const QString fileName(address2Filename(addr));
55  if (d->basePath.exists(fileName)) {
56  QFile file(d->basePath.filePath(fileName));
57  auto recipient = AutocryptRecipient::Ptr(new AutocryptRecipient);
58  if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
59  return nullptr;
60  }
61  recipient->fromJson(file.readAll());
62  d->recipients[addr] = recipient;
63  return recipient;
64  }
65  return nullptr;
66 }
67 
68 AutocryptRecipient::Ptr AutocryptStorage::addRecipient(const QByteArray &addr)
69 {
70  Q_D(AutocryptStorage);
71 
72  auto recipient = getRecipient(addr);
73  if (recipient) {
74  return recipient;
75  }
76 
77  recipient = AutocryptRecipient::Ptr(new AutocryptRecipient);
78  recipient->d_func()->addr = addr;
79  d->recipients[addr] = recipient;
80  return recipient;
81 }
82 
83 void AutocryptStorage::deleteRecipient(const QByteArray &addr)
84 {
85  Q_D(AutocryptStorage);
86  const QString fileName(address2Filename(addr));
87  d->basePath.remove(fileName);
88  d->recipients.remove(addr);
89 }
90 
91 void AutocryptStorage::save()
92 {
93  Q_D(AutocryptStorage);
94  if (!d->basePath.exists()) {
95  QDir parent = d->basePath;
96  if (!parent.cdUp()) {
97  qCWarning(AUTOCRYPT_LOG) << parent.absolutePath() << "does not exist. Cancel saving Autocrypt storage.";
98  return;
99  }
100 
101  if (!parent.mkdir(d->basePath.dirName())) {
102  qCWarning(AUTOCRYPT_LOG) << "Cancel saving Autocrypt storage, because failed to create" << d->basePath.absolutePath();
103  return;
104  }
105  }
106  const auto keys = d->recipients.keys();
107  for (const auto &addr : keys) {
108  const auto recipient = d->recipients.value(addr);
109  const QString fileName(address2Filename(addr));
110  if (recipient->hasChanged() || !d->basePath.exists(fileName)) {
111  QTemporaryFile file(d->basePath.path() + QLatin1Char('/'));
112  if (!file.open()) {
113  continue;
114  }
115  file.write(recipient->toJson(QJsonDocument::Compact));
116  file.close();
117  d->basePath.remove(fileName);
118  file.rename(d->basePath.filePath(fileName));
119  file.setAutoRemove(false);
120  recipient->setChangedFlag(false);
121  }
122  }
123 }
bool cdUp()
QString fromUtf8(const char *str, int size)
bool mkdir(const QString &dirName) const const
QByteArray toPercentEncoding(const QString &input, const QByteArray &exclude, const QByteArray &include)
QString absolutePath() const const
QString fromLatin1(const char *str, int size)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Dec 3 2023 03:57:06 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.