data/MailAddressIndex.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "MailAddressIndex.h" | ||
| 2 | |||
| 3 | #include <QRegularExpression> | ||
| 4 | #include <QSet> | ||
| 5 | #include <QUrl> | ||
| 6 | |||
| 7 | namespace MailAddressIndex { | ||
| 8 | |||
| 9 | 667111 | QString normalize(const QString &address) { | |
| 10 |
1/1✓ Branch 2 → 3 taken 667111 times.
|
667111 | QString text = address.trimmed(); |
| 11 |
4/7✓ Branch 3 → 4 taken 49 times.
✓ Branch 3 → 16 taken 667062 times.
✓ Branch 5 → 6 taken 49 times.
✗ Branch 5 → 16 not taken.
✓ Branch 10 → 11 taken 49 times.
✗ Branch 111 → 112 not taken.
✗ Branch 111 → 113 not taken.
|
667160 | static const QRegularExpression angle(QStringLiteral("<([^<>\\s]+@[^<>\\s]+)>")); |
| 12 |
5/5✓ Branch 17 → 18 taken 667111 times.
✓ Branch 18 → 19 taken 667111 times.
✓ Branch 19 → 20 taken 1 time.
✓ Branch 19 → 24 taken 667110 times.
✓ Branch 20 → 21 taken 1 time.
|
667111 | if (const auto match = angle.match(text); match.hasMatch()) text = match.captured(1); |
| 13 |
4/4✓ Branch 26 → 27 taken 667111 times.
✓ Branch 27 → 28 taken 1 time.
✓ Branch 27 → 32 taken 667110 times.
✓ Branch 28 → 29 taken 1 time.
|
667111 | if (text.startsWith(QLatin1String("mailto:"), Qt::CaseInsensitive)) text = text.mid(7); |
| 14 | 667111 | const qsizetype at = text.lastIndexOf(QLatin1Char('@')); | |
| 15 |
8/8✓ Branch 35 → 36 taken 667109 times.
✓ Branch 35 → 42 taken 2 times.
✓ Branch 37 → 38 taken 667108 times.
✓ Branch 37 → 42 taken 1 time.
✓ Branch 41 → 42 taken 1 time.
✓ Branch 41 → 43 taken 667107 times.
✓ Branch 44 → 45 taken 4 times.
✓ Branch 44 → 46 taken 667107 times.
|
667111 | if (at <= 0 || at == text.size() - 1 || text.indexOf(QLatin1Char('@')) != at) return {}; |
| 16 |
2/2✓ Branch 46 → 47 taken 667107 times.
✓ Branch 47 → 48 taken 667107 times.
|
667107 | const QString local = text.left(at).toLower(); |
| 17 |
2/2✓ Branch 49 → 50 taken 667107 times.
✓ Branch 50 → 51 taken 667107 times.
|
667107 | const QString domain = text.mid(at + 1).toLower(); |
| 18 |
8/16✓ Branch 56 → 57 taken 667107 times.
✓ Branch 57 → 58 taken 667107 times.
✓ Branch 58 → 59 taken 667106 times.
✓ Branch 58 → 66 taken 1 time.
✓ Branch 76 → 77 taken 667107 times.
✗ Branch 76 → 78 not taken.
✓ Branch 78 → 79 taken 667107 times.
✗ Branch 78 → 80 not taken.
✓ Branch 80 → 81 taken 1 time.
✓ Branch 80 → 82 taken 667106 times.
✗ Branch 140 → 141 not taken.
✗ Branch 140 → 142 not taken.
✗ Branch 144 → 145 not taken.
✗ Branch 144 → 146 not taken.
✗ Branch 148 → 149 not taken.
✗ Branch 148 → 150 not taken.
|
2668427 | if (local.contains(QRegularExpression(QStringLiteral("[\\s<>,;]"))) || |
| 19 |
10/18✓ Branch 63 → 64 taken 667106 times.
✓ Branch 64 → 65 taken 667106 times.
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 67 taken 667106 times.
✓ Branch 68 → 69 taken 667106 times.
✓ Branch 68 → 70 taken 1 time.
✓ Branch 70 → 71 taken 667106 times.
✓ Branch 70 → 72 taken 1 time.
✓ Branch 72 → 73 taken 667106 times.
✓ Branch 72 → 74 taken 1 time.
✓ Branch 74 → 75 taken 667107 times.
✗ Branch 74 → 76 not taken.
✗ Branch 127 → 128 not taken.
✗ Branch 127 → 129 not taken.
✗ Branch 131 → 132 not taken.
✗ Branch 131 → 133 not taken.
✗ Branch 135 → 136 not taken.
✗ Branch 135 → 137 not taken.
|
1334213 | domain.contains(QRegularExpression(QStringLiteral("[\\s<>,;@]")))) |
| 20 | 1 | return {}; | |
| 21 | // IDNA: "bücher.example" and "xn--bcher-kva.example" are one domain. | ||
| 22 |
1/1✓ Branch 83 → 84 taken 667106 times.
|
667106 | const QByteArray ace = QUrl::toAce(domain); |
| 23 |
4/8✗ Branch 85 → 86 not taken.
✓ Branch 85 → 87 taken 667106 times.
✓ Branch 87 → 88 taken 667106 times.
✓ Branch 88 → 89 taken 667106 times.
✓ Branch 89 → 90 taken 667106 times.
✗ Branch 89 → 91 not taken.
✗ Branch 154 → 155 not taken.
✗ Branch 154 → 156 not taken.
|
667106 | const QString asciiDomain = ace.isEmpty() ? domain : QString::fromLatin1(ace).toLower(); |
| 24 |
2/2✓ Branch 93 → 94 taken 667106 times.
✓ Branch 94 → 95 taken 667106 times.
|
667106 | return local + QLatin1Char('@') + asciiDomain; |
| 25 | 667111 | } | |
| 26 | |||
| 27 | 1251931 | QStringList parse(const QString &headerValue) { | |
| 28 | // Split on commas outside quotes; then take <addr> or a bare address. | ||
| 29 |
4/7✓ Branch 2 → 3 taken 64 times.
✓ Branch 2 → 15 taken 1251867 times.
✓ Branch 4 → 5 taken 64 times.
✗ Branch 4 → 15 not taken.
✓ Branch 9 → 10 taken 64 times.
✗ Branch 59 → 60 not taken.
✗ Branch 59 → 61 not taken.
|
1251995 | static const QRegularExpression angle(QStringLiteral("<([^<>\\s]+@[^<>\\s]+)>")); |
| 30 |
4/7✓ Branch 15 → 16 taken 64 times.
✓ Branch 15 → 28 taken 1251867 times.
✓ Branch 17 → 18 taken 64 times.
✗ Branch 17 → 28 not taken.
✓ Branch 22 → 23 taken 64 times.
✗ Branch 69 → 70 not taken.
✗ Branch 69 → 71 not taken.
|
1251995 | static const QRegularExpression bare(QStringLiteral("([^\\s<>,;\"']+@[^\\s<>,;\"']+)")); |
| 31 | 1251931 | QStringList result; | |
| 32 | 1251931 | QString current; | |
| 33 | 1251931 | bool quoted = false; | |
| 34 | 1253742 | const auto flush = [&] { | |
| 35 |
1/1✓ Branch 3 → 4 taken 1253742 times.
|
1253742 | const QRegularExpressionMatch inAngle = angle.match(current); |
| 36 |
5/5✓ Branch 4 → 5 taken 1253742 times.
✓ Branch 5 → 6 taken 37047 times.
✓ Branch 5 → 7 taken 1216695 times.
✓ Branch 6 → 9 taken 37047 times.
✓ Branch 8 → 9 taken 1216695 times.
|
2470437 | const QRegularExpressionMatch plain = inAngle.hasMatch() ? inAngle : bare.match(current); |
| 37 |
3/3✓ Branch 9 → 10 taken 1253742 times.
✓ Branch 10 → 11 taken 666931 times.
✓ Branch 10 → 19 taken 586811 times.
|
1253742 | if (plain.hasMatch()) { |
| 38 |
2/2✓ Branch 11 → 12 taken 666931 times.
✓ Branch 12 → 13 taken 666931 times.
|
666931 | const QString address = normalize(plain.captured(1)); |
| 39 |
2/3✓ Branch 15 → 16 taken 666931 times.
✗ Branch 15 → 17 not taken.
✓ Branch 16 → 17 taken 666931 times.
|
666931 | if (!address.isEmpty()) result.append(address); |
| 40 | 666931 | } | |
| 41 | 1253742 | current.clear(); | |
| 42 | 1253742 | }; | |
| 43 |
2/2✓ Branch 47 → 30 taken 14503400 times.
✓ Branch 47 → 48 taken 1251931 times.
|
15755331 | for (const QChar c : headerValue) { |
| 44 |
2/2✓ Branch 33 → 34 taken 926 times.
✓ Branch 33 → 35 taken 14502474 times.
|
14503400 | if (c == QLatin1Char('"')) quoted = !quoted; |
| 45 |
6/6✓ Branch 38 → 39 taken 2274 times.
✓ Branch 38 → 41 taken 14501126 times.
✓ Branch 39 → 40 taken 1811 times.
✓ Branch 39 → 41 taken 463 times.
✓ Branch 42 → 43 taken 1811 times.
✓ Branch 42 → 45 taken 14501589 times.
|
14503400 | if (c == QLatin1Char(',') && !quoted) { |
| 46 |
1/1✓ Branch 43 → 44 taken 1811 times.
|
1811 | flush(); |
| 47 | 1811 | continue; | |
| 48 | } | ||
| 49 |
1/1✓ Branch 45 → 46 taken 14501589 times.
|
14501589 | current.append(c); |
| 50 | } | ||
| 51 |
1/1✓ Branch 48 → 49 taken 1251931 times.
|
1251931 | flush(); |
| 52 | 1251931 | return result; | |
| 53 | 1251931 | } | |
| 54 | |||
| 55 | 411375 | QList<Entry> entriesOf(const MailHeader &header) { | |
| 56 | 411375 | QList<Entry> entries; | |
| 57 | 411375 | QSet<QString> seen; | |
| 58 | 1234125 | const auto add = [&](const QString &field, int role) { | |
| 59 |
5/5✓ Branch 2 → 3 taken 1234125 times.
✓ Branch 3 → 4 taken 1234125 times.
✓ Branch 4 → 5 taken 1234125 times.
✓ Branch 29 → 6 taken 654266 times.
✓ Branch 29 → 30 taken 1234124 times.
|
1888390 | for (const QString &address : parse(field)) { |
| 60 |
2/2✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 654265 times.
|
654266 | if (entries.size() >= MaxEntries) return; |
| 61 |
2/2✓ Branch 10 → 11 taken 654265 times.
✓ Branch 11 → 12 taken 654265 times.
|
654265 | const QString key = QString::number(role) + address; |
| 62 |
2/2✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 16 taken 654264 times.
|
654265 | if (seen.contains(key)) continue; |
| 63 |
1/1✓ Branch 16 → 17 taken 654264 times.
|
654264 | seen.insert(key); |
| 64 | 654264 | entries.append({address, role}); | |
| 65 | 1888390 | } | |
| 66 |
1/3✓ Branch 18 → 19 taken 654264 times.
✗ Branch 43 → 44 not taken.
✗ Branch 43 → 45 not taken.
|
654264 | }; |
| 67 |
1/1✓ Branch 3 → 4 taken 411375 times.
|
411375 | add(header.from, From); |
| 68 |
1/1✓ Branch 4 → 5 taken 411375 times.
|
411375 | add(header.to, To); |
| 69 |
1/1✓ Branch 5 → 6 taken 411375 times.
|
411375 | add(header.cc, Cc); |
| 70 | 411375 | return entries; | |
| 71 | 411375 | } | |
| 72 | |||
| 73 | } // namespace MailAddressIndex | ||
| 74 |