data/VCardExportFilter.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "VCardExportFilter.h" | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | |||
| 5 | #include "VCardCodec.h" | ||
| 6 | |||
| 7 | #include <QSet> | ||
| 8 | |||
| 9 | namespace VCardExportFilter { | ||
| 10 | |||
| 11 | namespace { | ||
| 12 | |||
| 13 | const QSet<QString> kPersonal{ | ||
| 14 | QStringLiteral("RELATED"), QStringLiteral("X-ABRELATEDNAMES"), QStringLiteral("NOTE"), | ||
| 15 | QStringLiteral("CATEGORIES"), QStringLiteral("INTEREST"), QStringLiteral("HOBBY"), | ||
| 16 | QStringLiteral("EXPERTISE"), QStringLiteral("X-ABDATE"), QStringLiteral("BIRTHPLACE"), | ||
| 17 | QStringLiteral("GEO"), QStringLiteral("X-EVOLUTION-SPOUSE"), QStringLiteral("X-EVOLUTION-MANAGER"), | ||
| 18 | QStringLiteral("X-EVOLUTION-ASSISTANT"), QStringLiteral("X-KADDRESSBOOK-X-SPOUSESNAME"), | ||
| 19 | QStringLiteral("X-KADDRESSBOOK-X-MANAGERSNAME"), QStringLiteral("X-KADDRESSBOOK-X-ASSISTANTSNAME"), | ||
| 20 | }; | ||
| 21 | |||
| 22 | 2203 | bool personal(const ICal::Property &property, bool groupCard) { | |
| 23 |
1/1✓ Branch 2 → 3 taken 2203 times.
|
2203 | const QString name = VCardCodec::baseName(property); |
| 24 |
7/7✓ Branch 4 → 5 taken 1531 times.
✓ Branch 4 → 8 taken 672 times.
✓ Branch 6 → 7 taken 1531 times.
✓ Branch 7 → 8 taken 25 times.
✓ Branch 7 → 9 taken 1506 times.
✓ Branch 10 → 11 taken 697 times.
✓ Branch 10 → 12 taken 1506 times.
|
2203 | if (kPersonal.contains(name) || name.startsWith(QLatin1String("X-MAILJD-"))) |
| 25 | 697 | return true; | |
| 26 |
8/8✓ Branch 12 → 13 taken 45 times.
✓ Branch 12 → 20 taken 1461 times.
✓ Branch 15 → 16 taken 41 times.
✓ Branch 15 → 19 taken 4 times.
✓ Branch 18 → 19 taken 2 times.
✓ Branch 18 → 20 taken 39 times.
✓ Branch 21 → 22 taken 6 times.
✓ Branch 21 → 23 taken 1500 times.
|
1506 | if (groupCard && (name == QLatin1String("MEMBER") || name == QLatin1String("X-ADDRESSBOOKSERVER-MEMBER"))) |
| 27 | 6 | return true; | |
| 28 |
8/13✓ Branch 25 → 26 taken 30 times.
✓ Branch 25 → 32 taken 1470 times.
✓ Branch 29 → 30 taken 30 times.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 30 times.
✓ Branch 34 → 35 taken 30 times.
✓ Branch 34 → 36 taken 1470 times.
✓ Branch 36 → 37 taken 30 times.
✓ Branch 36 → 38 taken 1470 times.
✗ Branch 43 → 44 not taken.
✗ Branch 43 → 45 not taken.
✗ Branch 47 → 48 not taken.
✗ Branch 47 → 49 not taken.
|
1530 | return name == QLatin1String("ADR") && property.hasParameter(QStringLiteral("GEO")); |
| 29 | 2203 | } | |
| 30 | |||
| 31 | 232 | bool isGroupCard(const ICal::Component &card) { | |
| 32 |
2/2✓ Branch 29 → 4 taken 2841 times.
✓ Branch 29 → 30 taken 225 times.
|
3066 | for (const ICal::Property &property : card.properties) { |
| 33 |
1/1✓ Branch 5 → 6 taken 2841 times.
|
2841 | const QString name = VCardCodec::baseName(property); |
| 34 |
6/6✓ Branch 8 → 9 taken 2834 times.
✓ Branch 8 → 12 taken 7 times.
✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 17 taken 2832 times.
✓ Branch 15 → 16 taken 7 times.
✓ Branch 15 → 17 taken 2 times.
|
2850 | if ((name == QLatin1String("KIND") || name == QLatin1String("X-ADDRESSBOOKSERVER-KIND")) && |
| 35 |
5/7✓ Branch 12 → 13 taken 9 times.
✓ Branch 18 → 19 taken 9 times.
✓ Branch 18 → 20 taken 2832 times.
✓ Branch 20 → 21 taken 7 times.
✓ Branch 20 → 22 taken 2834 times.
✗ Branch 33 → 34 not taken.
✗ Branch 33 → 35 not taken.
|
2850 | property.value.trimmed().compare(QLatin1String("group"), Qt::CaseInsensitive) == 0) |
| 36 | 7 | return true; | |
| 37 | 2841 | } | |
| 38 | 225 | return false; | |
| 39 | } | ||
| 40 | |||
| 41 | } // namespace | ||
| 42 | |||
| 43 | namespace { | ||
| 44 | |||
| 45 | // S106-163: nested cards (a 2.1 AGENT) are checked and filtered like the | ||
| 46 | // card itself; they used to pass the D-22 filter verbatim. | ||
| 47 | 140 | bool containsPersonal(const ICal::Component &card) { | |
| 48 | 140 | const bool group = isGroupCard(card); | |
| 49 |
2/2✓ Branch 11 → 5 taken 926 times.
✓ Branch 11 → 12 taken 88 times.
|
1014 | for (const ICal::Property &property : card.properties) |
| 50 |
3/3✓ Branch 6 → 7 taken 926 times.
✓ Branch 7 → 8 taken 52 times.
✓ Branch 7 → 9 taken 874 times.
|
926 | if (personal(property, group)) |
| 51 | 52 | return true; | |
| 52 | 88 | return std::any_of(card.components.cbegin(), card.components.cend(), containsPersonal); | |
| 53 | } | ||
| 54 | |||
| 55 | 92 | void filterCard(ICal::Component *card) { | |
| 56 |
1/1✓ Branch 2 → 3 taken 92 times.
|
92 | const bool group = isGroupCard(*card); |
| 57 | 92 | QSet<QString> droppedGroups; | |
| 58 | 92 | QList<ICal::Property> kept; | |
| 59 |
4/4✓ Branch 4 → 5 taken 92 times.
✓ Branch 5 → 6 taken 92 times.
✓ Branch 53 → 7 taken 1279 times.
✓ Branch 53 → 54 taken 92 times.
|
1371 | for (ICal::Property property : card->properties) { |
| 60 |
13/20✓ Branch 10 → 11 taken 1279 times.
✓ Branch 12 → 13 taken 14 times.
✓ Branch 12 → 19 taken 1265 times.
✓ Branch 16 → 17 taken 14 times.
✓ Branch 17 → 18 taken 2 times.
✓ Branch 17 → 19 taken 12 times.
✓ Branch 20 → 21 taken 14 times.
✓ Branch 20 → 22 taken 1265 times.
✓ Branch 22 → 23 taken 14 times.
✓ Branch 22 → 24 taken 1265 times.
✓ Branch 24 → 25 taken 1279 times.
✗ Branch 24 → 26 not taken.
✓ Branch 26 → 27 taken 2 times.
✓ Branch 26 → 35 taken 1277 times.
✗ Branch 91 → 92 not taken.
✗ Branch 91 → 93 not taken.
✗ Branch 95 → 96 not taken.
✗ Branch 95 → 97 not taken.
✗ Branch 99 → 100 not taken.
✗ Branch 99 → 101 not taken.
|
1293 | if (VCardCodec::baseName(property) == QLatin1String("ADR") && property.hasParameter(QStringLiteral("GEO"))) { |
| 61 | // The address stays, only its pinned position goes. | ||
| 62 |
1/1✓ Branch 30 → 31 taken 2 times.
|
2 | property.removeParameter(QStringLiteral("GEO")); |
| 63 |
1/1✓ Branch 33 → 34 taken 2 times.
|
2 | kept.append(property); |
| 64 | 2 | continue; | |
| 65 | } | ||
| 66 |
3/3✓ Branch 35 → 36 taken 1277 times.
✓ Branch 36 → 37 taken 651 times.
✓ Branch 36 → 46 taken 626 times.
|
1277 | if (personal(property, group)) { |
| 67 |
3/3✓ Branch 37 → 38 taken 651 times.
✓ Branch 39 → 40 taken 35 times.
✓ Branch 39 → 44 taken 616 times.
|
651 | if (const QString g = VCardCodec::groupOf(property); !g.isEmpty()) |
| 68 |
2/2✓ Branch 40 → 41 taken 35 times.
✓ Branch 41 → 42 taken 35 times.
|
651 | droppedGroups.insert(g.toUpper()); |
| 69 | 651 | continue; | |
| 70 | 651 | } | |
| 71 |
1/1✓ Branch 46 → 47 taken 626 times.
|
626 | kept.append(property); |
| 72 | 1279 | } | |
| 73 | // Labels (X-ABLabel and other X-AB companions) of removed values go too. | ||
| 74 |
1/1✓ Branch 54 → 55 taken 92 times.
|
92 | card->properties.clear(); |
| 75 |
4/4✓ Branch 55 → 56 taken 92 times.
✓ Branch 56 → 57 taken 92 times.
✓ Branch 79 → 58 taken 628 times.
✓ Branch 79 → 80 taken 92 times.
|
720 | for (const ICal::Property &property : kept) { |
| 76 |
2/2✓ Branch 59 → 60 taken 628 times.
✓ Branch 60 → 61 taken 628 times.
|
628 | const QString g = VCardCodec::groupOf(property).toUpper(); |
| 77 |
6/6✓ Branch 63 → 64 taken 49 times.
✓ Branch 63 → 67 taken 579 times.
✓ Branch 65 → 66 taken 35 times.
✓ Branch 65 → 67 taken 14 times.
✓ Branch 68 → 69 taken 35 times.
✓ Branch 68 → 70 taken 593 times.
|
628 | if (!g.isEmpty() && droppedGroups.contains(g)) |
| 78 | 35 | continue; | |
| 79 |
1/1✓ Branch 70 → 71 taken 593 times.
|
593 | card->properties.append(property); |
| 80 | 628 | } | |
| 81 |
4/4✓ Branch 80 → 81 taken 92 times.
✓ Branch 81 → 82 taken 92 times.
✓ Branch 87 → 83 taken 2 times.
✓ Branch 87 → 88 taken 92 times.
|
94 | for (ICal::Component &child : card->components) |
| 82 |
1/1✓ Branch 84 → 85 taken 2 times.
|
2 | filterCard(&child); |
| 83 | 92 | } | |
| 84 | |||
| 85 | } // namespace | ||
| 86 | |||
| 87 | 140 | bool hasPersonalDetails(const QString &raw) { | |
| 88 | 140 | ICal::Component card; | |
| 89 | 140 | QString error; | |
| 90 | 140 | int skipped = 0; | |
| 91 |
2/3✓ Branch 2 → 3 taken 140 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 140 times.
|
140 | if (!VCardCodec::parseTree(raw, &card, &error, &skipped)) |
| 92 | ✗ | return false; | |
| 93 | // Unreadable lines may hold anything: the export sheet asks (S106-163). | ||
| 94 |
5/5✓ Branch 5 → 6 taken 138 times.
✓ Branch 5 → 8 taken 2 times.
✓ Branch 6 → 7 taken 138 times.
✓ Branch 7 → 8 taken 52 times.
✓ Branch 7 → 9 taken 86 times.
|
140 | return skipped > 0 || containsPersonal(card); |
| 95 | 140 | } | |
| 96 | |||
| 97 | 90 | QString withoutPersonalDetails(const QString &raw) { | |
| 98 | 90 | ICal::Component card; | |
| 99 | 90 | QString error; | |
| 100 | 90 | int skipped = 0; | |
| 101 |
2/3✓ Branch 2 → 3 taken 90 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 90 times.
|
90 | if (!VCardCodec::parseTree(raw, &card, &error, &skipped)) |
| 102 | ✗ | return raw; | |
| 103 | // A card with unreadable lines is exported filtered without them — the | ||
| 104 | // private direction — instead of verbatim with them (S106-163). | ||
| 105 |
1/1✓ Branch 5 → 6 taken 90 times.
|
90 | filterCard(&card); |
| 106 |
1/1✓ Branch 6 → 7 taken 90 times.
|
90 | return ICal::serialize(card); |
| 107 | 90 | } | |
| 108 | |||
| 109 | 82 | QString filterAll(const QString &vcf, bool includePersonal) { | |
| 110 |
1/2✓ Branch 2 → 3 taken 82 times.
✗ Branch 2 → 4 not taken.
|
82 | if (includePersonal) |
| 111 | 82 | return vcf; | |
| 112 | ✗ | QString out; | |
| 113 | ✗ | for (const QString &card : VCardCodec::splitCards(vcf)) | |
| 114 | ✗ | out += withoutPersonalDetails(card); | |
| 115 | ✗ | return out; | |
| 116 | ✗ | } | |
| 117 | |||
| 118 | } // namespace VCardExportFilter | ||
| 119 |