data/MailAddressList.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "MailAddressList.h" | ||
| 2 | |||
| 3 | #include <QRegularExpression> | ||
| 4 | |||
| 5 | namespace MailAddressList { | ||
| 6 | |||
| 7 | 1363 | Mailbox parseMailbox(const QString &text) { | |
| 8 | 1363 | Mailbox mailbox; | |
| 9 |
1/1✓ Branch 2 → 3 taken 1363 times.
|
1363 | const QString trimmed = text.trimmed(); |
| 10 | 1363 | const int open = trimmed.lastIndexOf(QLatin1Char('<')); | |
| 11 | 1363 | const int close = trimmed.lastIndexOf(QLatin1Char('>')); | |
| 12 |
3/4✓ Branch 9 → 10 taken 307 times.
✓ Branch 9 → 22 taken 1056 times.
✓ Branch 10 → 11 taken 307 times.
✗ Branch 10 → 22 not taken.
|
1363 | if (open >= 0 && close > open) { |
| 13 |
2/2✓ Branch 11 → 12 taken 307 times.
✓ Branch 12 → 13 taken 307 times.
|
307 | mailbox.address = trimmed.mid(open + 1, close - open - 1).trimmed(); |
| 14 |
2/2✓ Branch 16 → 17 taken 307 times.
✓ Branch 17 → 18 taken 307 times.
|
307 | mailbox.name = trimmed.left(open).trimmed(); |
| 15 | } else { | ||
| 16 | 1056 | mailbox.address = trimmed; | |
| 17 | } | ||
| 18 |
9/10✓ Branch 24 → 25 taken 306 times.
✓ Branch 24 → 34 taken 1057 times.
✓ Branch 27 → 28 taken 306 times.
✓ Branch 28 → 29 taken 22 times.
✓ Branch 28 → 34 taken 284 times.
✓ Branch 31 → 32 taken 22 times.
✓ Branch 32 → 33 taken 22 times.
✗ Branch 32 → 34 not taken.
✓ Branch 35 → 36 taken 22 times.
✓ Branch 35 → 59 taken 1341 times.
|
1363 | if (mailbox.name.size() >= 2 && mailbox.name.startsWith(QLatin1Char('"')) && mailbox.name.endsWith(QLatin1Char('"'))) { |
| 19 | // A quoted-string: every backslash escapes the next character (RFC 5322 | ||
| 20 | // §3.2.4) — the counterpart of format() below. | ||
| 21 |
1/1✓ Branch 37 → 38 taken 22 times.
|
22 | const QString inner = mailbox.name.mid(1, mailbox.name.size() - 2); |
| 22 | 22 | QString unescaped; | |
| 23 |
2/2✓ Branch 54 → 39 taken 240 times.
✓ Branch 54 → 55 taken 22 times.
|
262 | for (int i = 0; i < inner.size(); ++i) { |
| 24 |
5/6✓ Branch 43 → 44 taken 5 times.
✓ Branch 43 → 47 taken 235 times.
✓ Branch 45 → 46 taken 5 times.
✗ Branch 45 → 47 not taken.
✓ Branch 48 → 49 taken 5 times.
✓ Branch 48 → 50 taken 235 times.
|
240 | if (inner.at(i) == QLatin1Char('\\') && i + 1 < inner.size()) |
| 25 | 5 | ++i; | |
| 26 |
1/1✓ Branch 51 → 52 taken 240 times.
|
240 | unescaped += inner.at(i); |
| 27 | } | ||
| 28 | 22 | mailbox.name = unescaped; | |
| 29 | 22 | } | |
| 30 |
1/2✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 1363 times.
|
1363 | if (mailbox.name == mailbox.address) |
| 31 | ✗ | mailbox.name.clear(); | |
| 32 | 1363 | return mailbox; | |
| 33 | 1363 | } | |
| 34 | |||
| 35 | 46 | QString format(const Mailbox &mailbox) { | |
| 36 |
1/1✓ Branch 2 → 3 taken 46 times.
|
46 | QString name = mailbox.name.trimmed(); |
| 37 |
3/6✓ Branch 4 → 5 taken 46 times.
✗ Branch 4 → 7 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 46 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 46 times.
|
46 | if (name.isEmpty() || name == mailbox.address) |
| 38 | ✗ | return mailbox.address; | |
| 39 |
4/7✓ Branch 11 → 12 taken 7 times.
✓ Branch 11 → 24 taken 39 times.
✓ Branch 13 → 14 taken 7 times.
✗ Branch 13 → 24 not taken.
✓ Branch 18 → 19 taken 7 times.
✗ Branch 76 → 77 not taken.
✗ Branch 76 → 78 not taken.
|
53 | static const QRegularExpression specials(QStringLiteral(R"([,;:<>@()\[\]".])")); |
| 40 |
3/3✓ Branch 24 → 25 taken 46 times.
✓ Branch 25 → 26 taken 4 times.
✓ Branch 25 → 52 taken 42 times.
|
46 | if (name.contains(specials)) |
| 41 | // S106-028: backslashes first, then quotes (RFC 5322 quoted-pair). | ||
| 42 | 4 | name = QLatin1Char('"') + | |
| 43 |
3/3✓ Branch 33 → 34 taken 4 times.
✓ Branch 39 → 40 taken 4 times.
✓ Branch 42 → 43 taken 4 times.
|
16 | name.replace(QLatin1Char('\\'), QStringLiteral("\\\\")).replace(QLatin1Char('"'), QStringLiteral("\\\"")) + |
| 44 |
1/1✓ Branch 43 → 44 taken 4 times.
|
12 | QLatin1Char('"'); |
| 45 |
3/3✓ Branch 57 → 58 taken 46 times.
✓ Branch 58 → 59 taken 46 times.
✓ Branch 59 → 60 taken 46 times.
|
138 | return name + QStringLiteral(" <") + mailbox.address + QLatin1Char('>'); |
| 46 | 46 | } | |
| 47 | |||
| 48 | 2197 | QList<Mailbox> parse(const QString &header) { | |
| 49 | 2197 | QList<Mailbox> result; | |
| 50 | 2197 | QString current; | |
| 51 | 2197 | bool quoted = false; | |
| 52 | 2197 | int angle = 0; | |
| 53 | 2217 | const auto flush = [&] { | |
| 54 |
1/1✓ Branch 2 → 3 taken 2217 times.
|
2217 | QString part = current.trimmed(); |
| 55 | 2217 | current.clear(); | |
| 56 | // A group "Team: a@x, b@y;" — its display name goes, its members stay. | ||
| 57 | // S106-027: only a colon outside a quoted display name starts a group | ||
| 58 | // ("Check https://x" <a@b> is one mailbox). | ||
| 59 | 2217 | int colon = -1; | |
| 60 | 2217 | bool inQuote = false; | |
| 61 |
6/6✓ Branch 33 → 34 taken 28371 times.
✓ Branch 33 → 36 taken 2216 times.
✓ Branch 34 → 35 taken 28370 times.
✓ Branch 34 → 36 taken 1 time.
✓ Branch 37 → 5 taken 28370 times.
✓ Branch 37 → 38 taken 2217 times.
|
30587 | for (int i = 0; i < part.size() && colon < 0; ++i) { |
| 62 | 28370 | const QChar c = part.at(i); | |
| 63 |
5/6✓ Branch 9 → 10 taken 5 times.
✓ Branch 9 → 12 taken 28365 times.
✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 12 not taken.
✓ Branch 13 → 14 taken 5 times.
✓ Branch 13 → 15 taken 28365 times.
|
28370 | if (c == QLatin1Char('\\') && inQuote) { ++i; continue; } |
| 64 |
2/2✓ Branch 18 → 19 taken 44 times.
✓ Branch 18 → 20 taken 28321 times.
|
28365 | if (c == QLatin1Char('"')) inQuote = !inQuote; |
| 65 |
6/6✓ Branch 23 → 24 taken 2 times.
✓ Branch 23 → 26 taken 28319 times.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 24 → 26 taken 1 time.
✓ Branch 27 → 28 taken 1 time.
✓ Branch 27 → 29 taken 28320 times.
|
28321 | else if (c == QLatin1Char(':') && !inQuote) colon = i; |
| 66 | } | ||
| 67 |
14/20✓ Branch 38 → 39 taken 1 time.
✓ Branch 38 → 50 taken 2216 times.
✓ Branch 39 → 40 taken 1 time.
✓ Branch 42 → 43 taken 1 time.
✓ Branch 43 → 44 taken 1 time.
✗ Branch 43 → 50 not taken.
✓ Branch 44 → 45 taken 1 time.
✓ Branch 47 → 48 taken 1 time.
✓ Branch 48 → 49 taken 1 time.
✗ Branch 48 → 50 not taken.
✓ Branch 51 → 52 taken 1 time.
✓ Branch 51 → 53 taken 2216 times.
✓ Branch 53 → 54 taken 1 time.
✓ Branch 53 → 55 taken 2216 times.
✓ Branch 55 → 56 taken 1 time.
✓ Branch 55 → 62 taken 2216 times.
✗ Branch 86 → 87 not taken.
✗ Branch 86 → 88 not taken.
✗ Branch 92 → 93 not taken.
✗ Branch 92 → 94 not taken.
|
2217 | if (colon >= 0 && !part.left(colon).contains(QLatin1Char('<')) && !part.left(colon).contains(QLatin1Char('@'))) |
| 68 |
2/2✓ Branch 56 → 57 taken 1 time.
✓ Branch 57 → 58 taken 1 time.
|
1 | part = part.mid(colon + 1).trimmed(); |
| 69 |
3/3✓ Branch 64 → 65 taken 2217 times.
✓ Branch 65 → 66 taken 1 time.
✓ Branch 65 → 67 taken 2216 times.
|
2217 | if (part.endsWith(QLatin1Char(';'))) |
| 70 |
1/1✓ Branch 66 → 67 taken 1 time.
|
1 | part.chop(1); |
| 71 |
2/2✓ Branch 68 → 69 taken 855 times.
✓ Branch 68 → 70 taken 1362 times.
|
2217 | if (part.isEmpty()) |
| 72 | 855 | return; | |
| 73 |
1/1✓ Branch 70 → 71 taken 1362 times.
|
1362 | const Mailbox mailbox = parseMailbox(part); |
| 74 |
3/3✓ Branch 73 → 74 taken 1362 times.
✓ Branch 74 → 75 taken 1360 times.
✓ Branch 74 → 76 taken 2 times.
|
1362 | if (mailbox.address.contains(QLatin1Char('@'))) |
| 75 |
1/1✓ Branch 75 → 76 taken 1360 times.
|
1360 | result.append(mailbox); |
| 76 |
2/2✓ Branch 79 → 80 taken 1362 times.
✓ Branch 79 → 82 taken 855 times.
|
2217 | }; |
| 77 |
2/2✓ Branch 67 → 3 taken 28423 times.
✓ Branch 67 → 68 taken 2197 times.
|
30620 | for (int i = 0; i < header.size(); ++i) { |
| 78 | 28423 | const QChar c = header.at(i); | |
| 79 |
6/8✓ Branch 7 → 8 taken 5 times.
✓ Branch 7 → 12 taken 28418 times.
✓ Branch 8 → 9 taken 5 times.
✗ Branch 8 → 12 not taken.
✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 12 not taken.
✓ Branch 13 → 14 taken 5 times.
✓ Branch 13 → 18 taken 28418 times.
|
28423 | if (c == QLatin1Char('\\') && quoted && i + 1 < header.size()) { |
| 80 |
1/1✓ Branch 14 → 15 taken 5 times.
|
5 | current += c; |
| 81 |
1/1✓ Branch 16 → 17 taken 5 times.
|
5 | current += header.at(++i); |
| 82 | 25 | continue; | |
| 83 | } | ||
| 84 |
2/2✓ Branch 21 → 22 taken 44 times.
✓ Branch 21 → 23 taken 28374 times.
|
28418 | if (c == QLatin1Char('"')) |
| 85 | 44 | quoted = !quoted; | |
| 86 |
6/6✓ Branch 23 → 24 taken 28139 times.
✓ Branch 23 → 29 taken 235 times.
✓ Branch 27 → 28 taken 306 times.
✓ Branch 27 → 29 taken 27833 times.
✓ Branch 30 → 31 taken 306 times.
✓ Branch 30 → 32 taken 28068 times.
|
28374 | else if (!quoted && c == QLatin1Char('<')) |
| 87 | 306 | ++angle; | |
| 88 |
7/8✓ Branch 32 → 33 taken 27833 times.
✓ Branch 32 → 39 taken 235 times.
✓ Branch 36 → 37 taken 306 times.
✓ Branch 36 → 39 taken 27527 times.
✓ Branch 37 → 38 taken 306 times.
✗ Branch 37 → 39 not taken.
✓ Branch 40 → 41 taken 306 times.
✓ Branch 40 → 42 taken 27762 times.
|
28068 | else if (!quoted && c == QLatin1Char('>') && angle > 0) |
| 89 | 306 | --angle; | |
| 90 |
10/10✓ Branch 42 → 43 taken 28161 times.
✓ Branch 42 → 53 taken 257 times.
✓ Branch 43 → 44 taken 22235 times.
✓ Branch 43 → 53 taken 5926 times.
✓ Branch 47 → 48 taken 22216 times.
✓ Branch 47 → 52 taken 19 times.
✓ Branch 51 → 52 taken 1 time.
✓ Branch 51 → 53 taken 22215 times.
✓ Branch 54 → 55 taken 20 times.
✓ Branch 54 → 62 taken 28398 times.
|
28418 | if (!quoted && angle == 0 && (c == QLatin1Char(',') || c == QLatin1Char(';'))) { |
| 91 |
2/2✓ Branch 58 → 59 taken 1 time.
✓ Branch 58 → 60 taken 19 times.
|
20 | if (c == QLatin1Char(';')) |
| 92 |
1/1✓ Branch 59 → 60 taken 1 time.
|
1 | current += c; |
| 93 |
1/1✓ Branch 60 → 61 taken 20 times.
|
20 | flush(); |
| 94 | 20 | continue; | |
| 95 | } | ||
| 96 |
1/1✓ Branch 62 → 63 taken 28398 times.
|
28398 | current += c; |
| 97 | } | ||
| 98 |
1/1✓ Branch 68 → 69 taken 2197 times.
|
2197 | flush(); |
| 99 | 2197 | return result; | |
| 100 | 2197 | } | |
| 101 | |||
| 102 | } // namespace MailAddressList | ||
| 103 |