app/core/CalendarSubscriptions.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "service/AuthenticatedRequest.h" | ||
| 2 | #include "CalendarSubscriptions.h" | ||
| 3 | |||
| 4 | #include "data/CalendarModels.h" | ||
| 5 | #include "data/CalendarStore.h" | ||
| 6 | #include "data/DavCredentials.h" | ||
| 7 | #include "data/IcsFile.h" | ||
| 8 | #include "service/DavNetworkLimits.h" | ||
| 9 | |||
| 10 | #include <QLoggingCategory> | ||
| 11 | #include <QNetworkAccessManager> | ||
| 12 | #include <QNetworkReply> | ||
| 13 | #include <QSettings> | ||
| 14 | #include <QUrl> | ||
| 15 | #include <QUuid> | ||
| 16 | |||
| 17 |
4/7✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 8 taken 11 times.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 1 time.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
12 | Q_LOGGING_CATEGORY(lcSubscriptions, "mailjd.calendar.subscriptions") |
| 18 | |||
| 19 | namespace { | ||
| 20 | const QString kPrefix = QStringLiteral("subscription:"); | ||
| 21 | constexpr int kMinimumIntervalMinutes = 15; | ||
| 22 | } // namespace | ||
| 23 | |||
| 24 | 948 | CalendarSubscriptions::CalendarSubscriptions(CalendarStore *store, QObject *parent) | |
| 25 |
1/1✓ Branch 9 → 10 taken 948 times.
|
948 | : QObject(parent), m_store(store) { |
| 26 | 948 | m_passwordReader = [](QObject *owner, const Subscription &entry, std::function<void(QByteArray, QString)> done) { | |
| 27 | ✗ | DavCredentials::readPasswordAsync(owner, accountIdFor(entry.id), entry.url, entry.username, std::move(done)); | |
| 28 | 948 | }; | |
| 29 | 948 | m_passwordWriter = [](const Subscription &entry, const QByteArray &password) { | |
| 30 | ✗ | return DavCredentials::writePasswordBlocking(accountIdFor(entry.id), entry.url, entry.username, password); | |
| 31 | 948 | }; | |
| 32 | // Due subscriptions are checked every 15 minutes besides every sync run. | ||
| 33 |
1/1✓ Branch 12 → 13 taken 948 times.
|
948 | m_timer.setInterval(kMinimumIntervalMinutes * 60 * 1000); |
| 34 |
1/1✓ Branch 13 → 14 taken 948 times.
|
948 | connect(&m_timer, &QTimer::timeout, this, [this] { refreshDue(false); }); |
| 35 |
1/1✓ Branch 15 → 16 taken 948 times.
|
948 | m_timer.start(); |
| 36 | 948 | } | |
| 37 | |||
| 38 |
2/2✓ Branch 3 → 4 taken 5 times.
✓ Branch 3 → 6 taken 1 time.
|
6 | qint64 CalendarSubscriptions::now() const { return m_clock ? m_clock() : QDateTime::currentSecsSinceEpoch(); } |
| 39 | |||
| 40 | 14 | QString CalendarSubscriptions::accountIdFor(const QString &subscriptionId) { return kPrefix + subscriptionId; } | |
| 41 | |||
| 42 | ✗ | bool CalendarSubscriptions::isSubscription(const QString &accountId) { return accountId.startsWith(kPrefix); } | |
| 43 | |||
| 44 | 181 | QList<CalendarSubscriptions::Subscription> CalendarSubscriptions::subscriptions() { | |
| 45 | 181 | QList<Subscription> list; | |
| 46 |
1/1✓ Branch 2 → 3 taken 181 times.
|
181 | QSettings settings; |
| 47 |
1/1✓ Branch 7 → 8 taken 181 times.
|
181 | const int count = settings.beginReadArray(QStringLiteral("calendar/subscriptions")); |
| 48 |
2/2✓ Branch 98 → 11 taken 32 times.
✓ Branch 98 → 99 taken 181 times.
|
213 | for (int i = 0; i < count; ++i) { |
| 49 |
1/1✓ Branch 11 → 12 taken 32 times.
|
32 | settings.setArrayIndex(i); |
| 50 | 32 | Subscription entry; | |
| 51 |
2/2✓ Branch 16 → 17 taken 32 times.
✓ Branch 17 → 18 taken 32 times.
|
32 | entry.id = settings.value(QStringLiteral("id")).toString(); |
| 52 |
2/2✓ Branch 27 → 28 taken 32 times.
✓ Branch 28 → 29 taken 32 times.
|
32 | entry.url = settings.value(QStringLiteral("url")).toString(); |
| 53 |
2/2✓ Branch 38 → 39 taken 32 times.
✓ Branch 39 → 40 taken 32 times.
|
32 | entry.name = settings.value(QStringLiteral("name")).toString(); |
| 54 |
2/2✓ Branch 50 → 51 taken 32 times.
✓ Branch 51 → 52 taken 32 times.
|
64 | entry.intervalMinutes = qMax(kMinimumIntervalMinutes, settings.value(QStringLiteral("interval"), 360).toInt()); |
| 55 |
2/2✓ Branch 61 → 62 taken 32 times.
✓ Branch 62 → 63 taken 32 times.
|
32 | entry.lastRefresh = settings.value(QStringLiteral("lastRefresh")).toLongLong(); |
| 56 |
2/2✓ Branch 70 → 71 taken 32 times.
✓ Branch 71 → 72 taken 32 times.
|
32 | entry.lastError = settings.value(QStringLiteral("lastError")).toString(); |
| 57 |
2/2✓ Branch 81 → 82 taken 32 times.
✓ Branch 82 → 83 taken 32 times.
|
32 | entry.username = settings.value(QStringLiteral("username")).toString(); |
| 58 |
4/7✓ Branch 89 → 90 taken 32 times.
✗ Branch 89 → 93 not taken.
✓ Branch 91 → 92 taken 32 times.
✗ Branch 91 → 93 not taken.
✓ Branch 94 → 95 taken 32 times.
✗ Branch 94 → 96 not taken.
✓ Branch 95 → 96 taken 32 times.
|
32 | if (!entry.id.isEmpty() && !entry.url.isEmpty()) list.append(entry); |
| 59 | 32 | } | |
| 60 |
1/1✓ Branch 99 → 100 taken 181 times.
|
181 | settings.endArray(); |
| 61 | 181 | return list; | |
| 62 | 181 | } | |
| 63 | |||
| 64 | 9 | void CalendarSubscriptions::save(const QList<Subscription> &list) { | |
| 65 |
1/1✓ Branch 2 → 3 taken 9 times.
|
9 | QSettings settings; |
| 66 |
1/1✓ Branch 7 → 8 taken 9 times.
|
9 | settings.remove(QStringLiteral("calendar/subscriptions")); |
| 67 |
1/1✓ Branch 15 → 16 taken 9 times.
|
18 | settings.beginWriteArray(QStringLiteral("calendar/subscriptions"), int(list.size())); |
| 68 |
2/2✓ Branch 92 → 19 taken 8 times.
✓ Branch 92 → 93 taken 9 times.
|
17 | for (int i = 0; i < list.size(); ++i) { |
| 69 |
1/1✓ Branch 19 → 20 taken 8 times.
|
8 | settings.setArrayIndex(i); |
| 70 |
1/1✓ Branch 26 → 27 taken 8 times.
|
16 | settings.setValue(QStringLiteral("id"), list.at(i).id); |
| 71 |
1/1✓ Branch 36 → 37 taken 8 times.
|
16 | settings.setValue(QStringLiteral("url"), list.at(i).url); |
| 72 |
1/1✓ Branch 46 → 47 taken 8 times.
|
16 | settings.setValue(QStringLiteral("name"), list.at(i).name); |
| 73 |
1/1✓ Branch 56 → 57 taken 8 times.
|
16 | settings.setValue(QStringLiteral("interval"), list.at(i).intervalMinutes); |
| 74 |
1/1✓ Branch 66 → 67 taken 8 times.
|
16 | settings.setValue(QStringLiteral("lastRefresh"), list.at(i).lastRefresh); |
| 75 |
1/1✓ Branch 76 → 77 taken 8 times.
|
16 | settings.setValue(QStringLiteral("lastError"), list.at(i).lastError); |
| 76 |
1/1✓ Branch 86 → 87 taken 8 times.
|
16 | settings.setValue(QStringLiteral("username"), list.at(i).username); |
| 77 | } | ||
| 78 |
1/1✓ Branch 93 → 94 taken 9 times.
|
9 | settings.endArray(); |
| 79 | 9 | } | |
| 80 | |||
| 81 | 6 | QString CalendarSubscriptions::add(const QString &url, const QString &name, int intervalMinutes, QString *error, | |
| 82 | const QString &username, const QByteArray &password) { | ||
| 83 |
2/2✓ Branch 4 → 5 taken 6 times.
✓ Branch 5 → 6 taken 6 times.
|
6 | QUrl parsed = QUrl::fromUserInput(url.trimmed()); |
| 84 |
10/16✓ Branch 9 → 10 taken 6 times.
✓ Branch 11 → 12 taken 5 times.
✓ Branch 11 → 16 taken 1 time.
✓ Branch 13 → 14 taken 5 times.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 5 times.
✓ Branch 18 → 19 taken 5 times.
✓ Branch 18 → 20 taken 1 time.
✓ Branch 20 → 21 taken 6 times.
✗ Branch 20 → 22 not taken.
✓ Branch 22 → 23 taken 1 time.
✓ Branch 22 → 30 taken 5 times.
✗ Branch 171 → 172 not taken.
✗ Branch 171 → 173 not taken.
✗ Branch 176 → 177 not taken.
✗ Branch 176 → 178 not taken.
|
6 | if (parsed.scheme() == QLatin1String("webcal") || parsed.scheme() == QLatin1String("webcals")) |
| 85 |
1/1✓ Branch 26 → 27 taken 1 time.
|
1 | parsed.setScheme(QStringLiteral("https")); |
| 86 |
12/19✓ Branch 30 → 31 taken 6 times.
✓ Branch 31 → 32 taken 6 times.
✗ Branch 31 → 44 not taken.
✓ Branch 33 → 34 taken 6 times.
✓ Branch 35 → 36 taken 3 times.
✓ Branch 35 → 40 taken 3 times.
✓ Branch 37 → 38 taken 3 times.
✓ Branch 39 → 40 taken 1 time.
✓ Branch 39 → 44 taken 2 times.
✗ Branch 43 → 44 not taken.
✓ Branch 43 → 45 taken 4 times.
✓ Branch 50 → 51 taken 6 times.
✗ Branch 50 → 52 not taken.
✓ Branch 52 → 53 taken 2 times.
✓ Branch 52 → 59 taken 4 times.
✗ Branch 192 → 193 not taken.
✗ Branch 192 → 194 not taken.
✗ Branch 197 → 198 not taken.
✗ Branch 197 → 199 not taken.
|
16 | if (!parsed.isValid() || (parsed.scheme() != QLatin1String("https") && parsed.scheme() != QLatin1String("http")) || |
| 87 |
5/7✓ Branch 41 → 42 taken 4 times.
✓ Branch 46 → 47 taken 4 times.
✓ Branch 46 → 48 taken 2 times.
✓ Branch 48 → 49 taken 3 times.
✓ Branch 48 → 50 taken 3 times.
✗ Branch 187 → 188 not taken.
✗ Branch 187 → 189 not taken.
|
10 | parsed.host().isEmpty()) { |
| 88 |
2/3✓ Branch 53 → 54 taken 2 times.
✗ Branch 53 → 58 not taken.
✓ Branch 54 → 55 taken 2 times.
|
2 | if (error) *error = tr("Enter an https:// or webcal:// address of a calendar file."); |
| 89 | 2 | return {}; | |
| 90 | } | ||
| 91 | // Credentials never live in the stored URL; a protected feed needs https | ||
| 92 | // (no password over plain HTTP). | ||
| 93 |
1/1✓ Branch 60 → 61 taken 4 times.
|
4 | parsed.setUserInfo({}); |
| 94 |
11/16✓ Branch 62 → 63 taken 4 times.
✓ Branch 64 → 65 taken 2 times.
✓ Branch 64 → 70 taken 2 times.
✓ Branch 66 → 67 taken 2 times.
✓ Branch 68 → 69 taken 1 time.
✓ Branch 68 → 70 taken 1 time.
✓ Branch 71 → 72 taken 2 times.
✓ Branch 71 → 73 taken 2 times.
✓ Branch 73 → 74 taken 4 times.
✗ Branch 73 → 75 not taken.
✓ Branch 75 → 76 taken 1 time.
✓ Branch 75 → 82 taken 3 times.
✗ Branch 206 → 207 not taken.
✗ Branch 206 → 208 not taken.
✗ Branch 211 → 212 not taken.
✗ Branch 211 → 213 not taken.
|
4 | if (!username.trimmed().isEmpty() && parsed.scheme() != QLatin1String("https")) { |
| 95 |
2/3✓ Branch 76 → 77 taken 1 time.
✗ Branch 76 → 81 not taken.
✓ Branch 77 → 78 taken 1 time.
|
1 | if (error) *error = tr("A calendar with a password needs an https:// or webcal:// address."); |
| 96 | 1 | return {}; | |
| 97 | } | ||
| 98 |
1/1✓ Branch 82 → 83 taken 3 times.
|
3 | QList<Subscription> list = subscriptions(); |
| 99 |
4/4✓ Branch 83 → 84 taken 3 times.
✓ Branch 84 → 85 taken 3 times.
✓ Branch 101 → 86 taken 1 time.
✓ Branch 101 → 102 taken 2 times.
|
3 | for (const Subscription &entry : list) |
| 100 |
2/3✓ Branch 88 → 89 taken 1 time.
✓ Branch 91 → 92 taken 1 time.
✗ Branch 91 → 99 not taken.
|
1 | if (entry.url == parsed.toString()) { |
| 101 |
2/3✓ Branch 92 → 93 taken 1 time.
✗ Branch 92 → 97 not taken.
✓ Branch 93 → 94 taken 1 time.
|
1 | if (error) *error = tr("This calendar is already subscribed."); |
| 102 | 1 | return {}; | |
| 103 | } | ||
| 104 | 2 | Subscription entry; | |
| 105 |
3/3✓ Branch 102 → 103 taken 2 times.
✓ Branch 103 → 104 taken 2 times.
✓ Branch 104 → 105 taken 2 times.
|
2 | entry.id = QUuid::createUuid().toString(QUuid::WithoutBraces).left(8); |
| 106 |
1/1✓ Branch 109 → 110 taken 2 times.
|
2 | entry.url = parsed.toString(); |
| 107 |
3/5✓ Branch 112 → 113 taken 2 times.
✗ Branch 114 → 115 not taken.
✓ Branch 114 → 117 taken 2 times.
✗ Branch 116 → 118 not taken.
✓ Branch 117 → 118 taken 2 times.
|
2 | entry.name = name.trimmed().isEmpty() ? parsed.host() : name.trimmed(); |
| 108 | 2 | entry.intervalMinutes = qMax(kMinimumIntervalMinutes, intervalMinutes); | |
| 109 |
1/1✓ Branch 122 → 123 taken 2 times.
|
2 | entry.username = username.trimmed(); |
| 110 |
5/7✓ Branch 126 → 127 taken 1 time.
✓ Branch 126 → 130 taken 1 time.
✓ Branch 127 → 128 taken 1 time.
✗ Branch 128 → 129 not taken.
✓ Branch 128 → 130 taken 1 time.
✗ Branch 131 → 132 not taken.
✓ Branch 131 → 138 taken 2 times.
|
2 | if (!entry.username.isEmpty() && !m_passwordWriter(entry, password)) { |
| 111 | ✗ | if (error) *error = tr("The password could not be stored in the keyring."); | |
| 112 | ✗ | return {}; | |
| 113 | } | ||
| 114 |
1/1✓ Branch 138 → 139 taken 2 times.
|
2 | list.append(entry); |
| 115 |
1/1✓ Branch 139 → 140 taken 2 times.
|
2 | save(list); |
| 116 |
1/1✓ Branch 140 → 141 taken 2 times.
|
2 | storeCalendar(entry); |
| 117 |
9/9✓ Branch 141 → 142 taken 2 times.
✓ Branch 145 → 146 taken 2 times.
✓ Branch 146 → 147 taken 2 times.
✓ Branch 147 → 148 taken 2 times.
✓ Branch 148 → 149 taken 2 times.
✓ Branch 149 → 150 taken 2 times.
✓ Branch 150 → 151 taken 2 times.
✓ Branch 154 → 143 taken 2 times.
✓ Branch 154 → 155 taken 2 times.
|
4 | qCInfo(lcSubscriptions) << "Subscribed" << entry.id << "every" << entry.intervalMinutes << "min"; |
| 118 |
1/1✓ Branch 155 → 156 taken 2 times.
|
2 | emit changed(); |
| 119 |
1/1✓ Branch 156 → 157 taken 2 times.
|
2 | emit storeChanged(); |
| 120 |
1/1✓ Branch 157 → 158 taken 2 times.
|
2 | refresh(entry.id); |
| 121 | 2 | return entry.id; | |
| 122 | 6 | } | |
| 123 | |||
| 124 | 1 | bool CalendarSubscriptions::remove(const QString &id) { | |
| 125 |
1/1✓ Branch 2 → 3 taken 1 time.
|
1 | QList<Subscription> list = subscriptions(); |
| 126 |
3/3✓ Branch 3 → 4 taken 1 time.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 5 → 6 taken 1 time.
|
2 | const auto found = std::find_if(list.begin(), list.end(), [&](const Subscription &entry) { return entry.id == id; }); |
| 127 |
2/3✓ Branch 6 → 7 taken 1 time.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1 time.
|
1 | if (found == list.end()) return false; |
| 128 |
1/2✗ Branch 12 → 13 not taken.
✓ Branch 12 → 23 taken 1 time.
|
1 | if (!found->username.isEmpty()) |
| 129 | ✗ | DavCredentials::deletePasswordAsync(this, accountIdFor(id), found->url, found->username, [](bool) {}); | |
| 130 |
2/2✓ Branch 25 → 26 taken 1 time.
✓ Branch 26 → 27 taken 1 time.
|
1 | m_store->removeStaleEvents(accountIdFor(id), found->url, {}, true); |
| 131 |
2/2✓ Branch 29 → 30 taken 1 time.
✓ Branch 30 → 31 taken 1 time.
|
1 | m_store->removeAccountCalendars(accountIdFor(id)); // one calendar per subscription account |
| 132 |
1/1✓ Branch 33 → 34 taken 1 time.
|
1 | list.erase(found); |
| 133 |
1/1✓ Branch 34 → 35 taken 1 time.
|
1 | save(list); |
| 134 |
6/6✓ Branch 35 → 36 taken 1 time.
✓ Branch 39 → 40 taken 1 time.
✓ Branch 40 → 41 taken 1 time.
✓ Branch 41 → 42 taken 1 time.
✓ Branch 45 → 37 taken 1 time.
✓ Branch 45 → 46 taken 1 time.
|
2 | qCInfo(lcSubscriptions) << "Unsubscribed" << id; |
| 135 |
1/1✓ Branch 46 → 47 taken 1 time.
|
1 | emit changed(); |
| 136 |
1/1✓ Branch 47 → 48 taken 1 time.
|
1 | emit storeChanged(); |
| 137 | 1 | return true; | |
| 138 | 1 | } | |
| 139 | |||
| 140 | // The subscription's read-only calendar in the store (name and address). | ||
| 141 | 2 | void CalendarSubscriptions::storeCalendar(const Subscription &entry) { | |
| 142 | 2 | CalendarInfo calendar; | |
| 143 |
1/1✓ Branch 2 → 3 taken 2 times.
|
2 | calendar.accountId = accountIdFor(entry.id); |
| 144 | 2 | calendar.path = entry.url; | |
| 145 | 2 | calendar.displayName = entry.name; | |
| 146 | 2 | calendar.readOnly = true; | |
| 147 |
1/1✓ Branch 7 → 8 taken 2 times.
|
2 | m_store->upsertCalendar(calendar, calendar.accountId); |
| 148 | 2 | } | |
| 149 | |||
| 150 | ✗ | bool CalendarSubscriptions::update(const QString &id, const QString &name, int intervalMinutes) { | |
| 151 | ✗ | QList<Subscription> list = subscriptions(); | |
| 152 | ✗ | const auto found = std::find_if(list.begin(), list.end(), [&](const Subscription &entry) { return entry.id == id; }); | |
| 153 | ✗ | if (found == list.end() || name.trimmed().isEmpty()) return false; | |
| 154 | ✗ | found->name = name.trimmed(); | |
| 155 | ✗ | found->intervalMinutes = qMax(kMinimumIntervalMinutes, intervalMinutes); | |
| 156 | ✗ | save(list); | |
| 157 | ✗ | storeCalendar(*found); | |
| 158 | ✗ | qCInfo(lcSubscriptions) << "Updated" << id << "every" << found->intervalMinutes << "min"; | |
| 159 | ✗ | emit changed(); | |
| 160 | ✗ | emit storeChanged(); | |
| 161 | ✗ | return true; | |
| 162 | ✗ | } | |
| 163 | |||
| 164 | 87 | void CalendarSubscriptions::refreshDue(bool force) { | |
| 165 |
5/5✓ Branch 2 → 3 taken 87 times.
✓ Branch 3 → 4 taken 87 times.
✓ Branch 4 → 5 taken 87 times.
✓ Branch 16 → 6 taken 3 times.
✓ Branch 16 → 17 taken 87 times.
|
90 | for (const Subscription &entry : subscriptions()) |
| 166 |
7/8✓ Branch 7 → 8 taken 3 times.
✗ Branch 7 → 10 not taken.
✓ Branch 8 → 9 taken 3 times.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 11 taken 1 time.
✓ Branch 12 → 13 taken 2 times.
✓ Branch 12 → 14 taken 1 time.
✓ Branch 13 → 14 taken 2 times.
|
90 | if (force || now() - entry.lastRefresh >= qint64(entry.intervalMinutes) * 60) refresh(entry.id); |
| 167 | 87 | } | |
| 168 | |||
| 169 | 6 | void CalendarSubscriptions::refresh(const QString &id) { | |
| 170 |
3/9✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 8 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 9 taken 6 times.
✗ Branch 6 → 7 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 9 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 6 times.
|
9 | if (m_running.contains(id) || (m_networkGate && !m_networkGate())) return; |
| 171 |
1/1✓ Branch 12 → 13 taken 6 times.
|
6 | const auto list = subscriptions(); |
| 172 |
1/1✓ Branch 15 → 16 taken 6 times.
|
12 | const auto found = std::find_if(list.begin(), list.end(), [&](const Subscription &entry) { return entry.id == id; }); |
| 173 |
1/2✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 6 times.
|
6 | if (found == list.end()) return; |
| 174 |
1/1✓ Branch 20 → 21 taken 6 times.
|
6 | m_running.insert(id); |
| 175 |
1/1✓ Branch 21 → 22 taken 6 times.
|
6 | emit changed(); |
| 176 |
2/2✓ Branch 24 → 25 taken 3 times.
✓ Branch 24 → 30 taken 3 times.
|
6 | if (found->username.isEmpty()) { |
| 177 |
1/1✓ Branch 27 → 28 taken 3 times.
|
3 | download(*found, {}); |
| 178 | 3 | return; | |
| 179 | } | ||
| 180 | 3 | const Subscription entry = *found; | |
| 181 |
2/2✓ Branch 33 → 34 taken 3 times.
✓ Branch 34 → 35 taken 3 times.
|
3 | m_passwordReader(this, entry, [this, entry](QByteArray password, QString error) { |
| 182 |
2/2✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 23 taken 2 times.
|
3 | if (password.isEmpty()) { |
| 183 |
8/8✓ Branch 4 → 5 taken 1 time.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 16 → 6 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
|
2 | qCWarning(lcSubscriptions) << "Subscription" << entry.id << "has no readable password:" << error; |
| 184 |
2/2✓ Branch 17 → 18 taken 1 time.
✓ Branch 19 → 20 taken 1 time.
|
1 | finished(entry.id, {}, tr("The password of this calendar is missing in the keyring.")); |
| 185 | 1 | return; | |
| 186 | } | ||
| 187 | 2 | download(entry, password); | |
| 188 | }); | ||
| 189 | 6 | } | |
| 190 | |||
| 191 | 5 | void CalendarSubscriptions::download(const Subscription &subscription, const QByteArray &password) { | |
| 192 | 5 | const QString id = subscription.id; | |
| 193 |
3/13✓ Branch 4 → 5 taken 5 times.
✗ Branch 4 → 7 not taken.
✓ Branch 5 → 6 taken 5 times.
✗ Branch 7 → 8 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 13 taken 5 times.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 13 not taken.
✗ Branch 53 → 54 not taken.
✗ Branch 53 → 56 not taken.
✗ Branch 54 → 55 not taken.
✗ Branch 54 → 56 not taken.
|
5 | auto *nam = m_namFactory ? m_namFactory(this) : new QNetworkAccessManager(this); |
| 194 |
2/2✓ Branch 13 → 14 taken 5 times.
✓ Branch 14 → 15 taken 5 times.
|
5 | QNetworkRequest request{QUrl(subscription.url)}; |
| 195 |
3/3✓ Branch 16 → 17 taken 5 times.
✓ Branch 17 → 18 taken 5 times.
✓ Branch 18 → 19 taken 5 times.
|
5 | request.setRawHeader("Accept", "text/calendar, */*;q=0.5"); |
| 196 | 5 | const QByteArray authorization = subscription.username.isEmpty() ? QByteArray() | |
| 197 |
15/23✓ Branch 22 → 23 taken 3 times.
✓ Branch 22 → 24 taken 2 times.
✓ Branch 24 → 25 taken 2 times.
✓ Branch 25 → 26 taken 2 times.
✓ Branch 26 → 27 taken 2 times.
✓ Branch 28 → 29 taken 2 times.
✓ Branch 29 → 30 taken 2 times.
✓ Branch 30 → 31 taken 2 times.
✓ Branch 30 → 32 taken 3 times.
✓ Branch 32 → 33 taken 2 times.
✓ Branch 32 → 34 taken 3 times.
✓ Branch 34 → 35 taken 2 times.
✓ Branch 34 → 36 taken 3 times.
✓ Branch 36 → 37 taken 2 times.
✓ Branch 36 → 38 taken 3 times.
✗ Branch 66 → 67 not taken.
✗ Branch 66 → 68 not taken.
✗ Branch 71 → 72 not taken.
✗ Branch 71 → 73 not taken.
✗ Branch 75 → 76 not taken.
✗ Branch 75 → 77 not taken.
✗ Branch 79 → 80 not taken.
✗ Branch 79 → 81 not taken.
|
5 | : "Basic " + (subscription.username.toUtf8() + ':' + password).toBase64(); |
| 198 |
3/3✓ Branch 39 → 40 taken 5 times.
✓ Branch 42 → 43 taken 5 times.
✓ Branch 43 → 44 taken 5 times.
|
5 | AuthenticatedRequest::start(this, nam, request, authorization, {}, false, |
| 199 | AuthenticatedRequest::ForeignRedirect::FollowWithoutCredentials, | ||
| 200 | 10 | [this, nam, id](AuthenticatedRequest::Result result) { | |
| 201 |
1/1✓ Branch 2 → 3 taken 5 times.
|
5 | nam->deleteLater(); |
| 202 |
3/4✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 2 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 3 times.
|
5 | const bool failed = result.outcome != AuthenticatedRequest::Outcome::Ok || result.status != 200; |
| 203 |
2/2✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 20 taken 3 times.
|
5 | if (failed) |
| 204 |
6/6✓ Branch 8 → 9 taken 2 times.
✓ Branch 12 → 13 taken 2 times.
✓ Branch 13 → 14 taken 2 times.
✓ Branch 14 → 15 taken 2 times.
✓ Branch 18 → 10 taken 2 times.
✓ Branch 18 → 19 taken 2 times.
|
4 | qCWarning(lcSubscriptions) << "Subscription download failed: HTTP" << result.status; |
| 205 |
1/2✗ Branch 21 → 22 not taken.
✓ Branch 21 → 28 taken 1 time.
|
1 | const QString message = result.outcome == AuthenticatedRequest::Outcome::Unauthorized && result.leftOrigin |
| 206 |
1/8✗ Branch 22 → 23 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 33 taken 5 times.
✗ Branch 51 → 52 not taken.
✗ Branch 51 → 53 not taken.
✗ Branch 57 → 58 not taken.
✗ Branch 57 → 59 not taken.
|
5 | ? tr("This calendar moved to another server (%1). Update its address.").arg(result.url.host()) |
| 207 | 5 | : result.outcome == AuthenticatedRequest::Outcome::Unauthorized | |
| 208 |
2/2✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 30 taken 4 times.
|
5 | ? tr("The calendar refused the user name or password.") |
| 209 |
5/7✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 28 taken 4 times.
✗ Branch 26 → 27 not taken.
✓ Branch 29 → 31 taken 1 time.
✓ Branch 30 → 31 taken 4 times.
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 5 times.
|
15 | : tr("The calendar could not be downloaded from this address."); |
| 210 |
5/5✓ Branch 35 → 36 taken 2 times.
✓ Branch 35 → 37 taken 3 times.
✓ Branch 38 → 39 taken 2 times.
✓ Branch 38 → 40 taken 3 times.
✓ Branch 41 → 42 taken 5 times.
|
5 | finished(id, failed ? QByteArray() : result.body, failed ? message : QString()); |
| 211 | 5 | }); | |
| 212 | 5 | } | |
| 213 | |||
| 214 | 6 | void CalendarSubscriptions::finished(const QString &id, const QByteArray &body, const QString &error) { | |
| 215 |
1/1✓ Branch 2 → 3 taken 6 times.
|
6 | m_running.remove(id); |
| 216 |
1/1✓ Branch 3 → 4 taken 6 times.
|
6 | QList<Subscription> list = subscriptions(); |
| 217 |
3/3✓ Branch 4 → 5 taken 6 times.
✓ Branch 5 → 6 taken 6 times.
✓ Branch 6 → 7 taken 6 times.
|
12 | const auto found = std::find_if(list.begin(), list.end(), [&](const Subscription &entry) { return entry.id == id; }); |
| 218 |
2/4✓ Branch 7 → 8 taken 6 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 12 taken 6 times.
✗ Branch 10 → 11 not taken.
|
6 | if (found == list.end()) { emit changed(); return; } // removed meanwhile |
| 219 | 6 | QString problem = error; | |
| 220 | 6 | QList<IcsFile::Entry> entries; | |
| 221 |
2/2✓ Branch 14 → 15 taken 3 times.
✓ Branch 14 → 34 taken 3 times.
|
6 | if (problem.isEmpty()) { |
| 222 | 3 | QString parseError; | |
| 223 |
2/2✓ Branch 15 → 16 taken 3 times.
✓ Branch 16 → 17 taken 3 times.
|
3 | entries = IcsFile::read(QString::fromUtf8(body), &parseError); |
| 224 |
2/7✗ Branch 21 → 22 not taken.
✓ Branch 21 → 26 taken 3 times.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 26 not taken.
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 32 taken 3 times.
✗ Branch 28 → 29 not taken.
|
3 | if (entries.isEmpty() && !body.contains("BEGIN:VCALENDAR")) problem = tr("The address is not a calendar file."); |
| 225 | 3 | } | |
| 226 |
2/2✓ Branch 35 → 36 taken 3 times.
✓ Branch 35 → 54 taken 3 times.
|
6 | if (!problem.isEmpty()) { |
| 227 | // The last copy stays; the error is shown in the calendar's options. | ||
| 228 |
8/8✓ Branch 36 → 37 taken 3 times.
✓ Branch 40 → 41 taken 3 times.
✓ Branch 41 → 42 taken 3 times.
✓ Branch 42 → 43 taken 3 times.
✓ Branch 43 → 44 taken 3 times.
✓ Branch 44 → 45 taken 3 times.
✓ Branch 48 → 38 taken 3 times.
✓ Branch 48 → 49 taken 3 times.
|
6 | qCWarning(lcSubscriptions) << "Subscription" << id << "not refreshed:" << problem; |
| 229 | 3 | found->lastError = problem; | |
| 230 |
1/1✓ Branch 51 → 52 taken 3 times.
|
3 | save(list); |
| 231 |
1/1✓ Branch 52 → 53 taken 3 times.
|
3 | emit changed(); |
| 232 | 3 | return; | |
| 233 | } | ||
| 234 |
1/1✓ Branch 54 → 55 taken 3 times.
|
3 | const QString accountId = accountIdFor(id); |
| 235 |
1/1✓ Branch 56 → 57 taken 3 times.
|
3 | const QString color = m_store->calendarColor(accountId, found->url); |
| 236 | 3 | QStringList uids; | |
| 237 |
1/1✓ Branch 57 → 58 taken 3 times.
|
3 | m_store->beginTransaction(); |
| 238 |
4/4✓ Branch 58 → 59 taken 3 times.
✓ Branch 59 → 60 taken 3 times.
✓ Branch 82 → 61 taken 5 times.
✓ Branch 82 → 83 taken 3 times.
|
8 | for (const IcsFile::Entry &entry : entries) { |
| 239 |
1/1✓ Branch 62 → 63 taken 5 times.
|
5 | uids << entry.uid; |
| 240 |
1/1✓ Branch 65 → 66 taken 5 times.
|
5 | m_store->deleteEvent(entry.uid, accountId, found->url); |
| 241 |
2/2✓ Branch 79 → 69 taken 5 times.
✓ Branch 79 → 80 taken 5 times.
|
10 | for (CalendarEvent row : entry.rows) { |
| 242 | 5 | row.accountId = accountId; | |
| 243 | 5 | row.calendarPath = found->url; | |
| 244 | 5 | row.color = color; | |
| 245 |
1/1✓ Branch 75 → 76 taken 5 times.
|
5 | m_store->upsertEvent(row); |
| 246 | 5 | } | |
| 247 | } | ||
| 248 |
1/1✓ Branch 83 → 84 taken 3 times.
|
3 | m_store->commitTransaction(); |
| 249 |
1/1✓ Branch 85 → 86 taken 3 times.
|
3 | m_store->removeStaleEvents(accountId, found->url, uids, true); |
| 250 |
1/1✓ Branch 86 → 87 taken 3 times.
|
3 | found->lastRefresh = now(); |
| 251 | 3 | found->lastError.clear(); | |
| 252 |
1/1✓ Branch 90 → 91 taken 3 times.
|
3 | save(list); |
| 253 |
9/9✓ Branch 91 → 92 taken 3 times.
✓ Branch 95 → 96 taken 3 times.
✓ Branch 96 → 97 taken 3 times.
✓ Branch 97 → 98 taken 3 times.
✓ Branch 98 → 99 taken 3 times.
✓ Branch 100 → 101 taken 3 times.
✓ Branch 101 → 102 taken 3 times.
✓ Branch 105 → 93 taken 3 times.
✓ Branch 105 → 106 taken 3 times.
|
6 | qCInfo(lcSubscriptions) << "Subscription" << id << "refreshed with" << entries.size() << "appointments"; |
| 254 |
1/1✓ Branch 106 → 107 taken 3 times.
|
3 | emit changed(); |
| 255 |
1/1✓ Branch 107 → 108 taken 3 times.
|
3 | emit storeChanged(); |
| 256 | 12 | } | |
| 257 |