service/ImapAppendStream.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "ImapAppendStream.h" | ||
| 2 | |||
| 3 | #include "ImapCommandTable.h" | ||
| 4 | #include "ImapMutationCommands.h" | ||
| 5 | #include "ImapPushSession.h" | ||
| 6 | |||
| 7 | #include <QLoggingCategory> | ||
| 8 | #include <QRegularExpression> | ||
| 9 | #include <QSslSocket> | ||
| 10 | #include <QTimer> | ||
| 11 | |||
| 12 | #include <algorithm> | ||
| 13 | #include <utility> | ||
| 14 | |||
| 15 | Q_DECLARE_LOGGING_CATEGORY(lcImap) | ||
| 16 | |||
| 17 | 1401 | ImapAppendStream::ImapAppendStream(QObject *owner, QSslSocket *socket, | |
| 18 | ImapCommandTable &commands, ImapPushSession &push, | ||
| 19 | ImapMutationCommands &mutations, const State &state, | ||
| 20 | 1401 | Deps deps) | |
| 21 | 1401 | : m_owner(owner), m_socket(socket), m_commands(commands), m_push(push), | |
| 22 | 1401 | m_mutations(mutations), m_state(state), m_deps(std::move(deps)) {} | |
| 23 | |||
| 24 | // T-176: IMAP APPEND – upload a message to a folder | ||
| 25 | 35 | quint64 ImapAppendStream::appendMessage(const QString &folder, | |
| 26 | const QByteArray &rfcMessage, | ||
| 27 | const QString &flags, | ||
| 28 | qint64 mutationToken) { | ||
| 29 | 35 | const quint64 requestId = reserveAppendRequestId(); | |
| 30 | 35 | appendMessageWithId(requestId, folder, rfcMessage, flags, mutationToken); | |
| 31 | 35 | return requestId; | |
| 32 | } | ||
| 33 | |||
| 34 | 40 | quint64 ImapAppendStream::reserveAppendRequestId() { | |
| 35 | 40 | quint64 requestId = m_nextAppendRequestId++; | |
| 36 |
2/2✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 39 times.
|
40 | if (requestId == 0) |
| 37 | 1 | requestId = m_nextAppendRequestId++; | |
| 38 | 40 | return requestId; | |
| 39 | } | ||
| 40 | |||
| 41 | 10 | void ImapAppendStream::appendMessage(quint64 requestId, const QString &folder, | |
| 42 | const QByteArray &rfcMessage, | ||
| 43 | const QString &flags, | ||
| 44 | qint64 mutationToken) { | ||
| 45 |
2/2✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 9 times.
|
10 | if (requestId == 0) |
| 46 | 1 | requestId = reserveAppendRequestId(); | |
| 47 | 10 | appendMessageWithId(requestId, folder, rfcMessage, flags, mutationToken); | |
| 48 | 10 | } | |
| 49 | |||
| 50 | 48 | void ImapAppendStream::appendMessageWithId(quint64 requestId, const QString &folder, | |
| 51 | const QByteArray &rfcMessage, | ||
| 52 | const QString &flags, | ||
| 53 | qint64 mutationToken) { | ||
| 54 |
1/1✓ Branch 2 → 3 taken 48 times.
|
48 | m_mutations.trackMutation(mutationToken); |
| 55 |
4/4✓ Branch 3 → 4 taken 29 times.
✓ Branch 3 → 36 taken 19 times.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 36 taken 28 times.
|
48 | if (m_state != State::Authenticated && m_state != State::Selected) { |
| 56 |
5/5✓ Branch 5 → 6 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 14 → 7 taken 1 time.
✓ Branch 14 → 15 taken 1 time.
|
2 | qCWarning(lcImap) << "Cannot APPEND: not authenticated"; |
| 57 |
1/1✓ Branch 18 → 19 taken 1 time.
|
2 | m_deps.appendFailed(requestId, QStringLiteral("Not authenticated")); |
| 58 |
1/1✓ Branch 24 → 25 taken 1 time.
|
2 | m_deps.appendError(QStringLiteral("Not authenticated")); |
| 59 |
1/1✓ Branch 31 → 32 taken 1 time.
|
2 | m_mutations.completeMutation(mutationToken, MutationOutcome::Rejected, |
| 60 | 2 | QStringLiteral("Not authenticated")); | |
| 61 | 13 | return; | |
| 62 | } | ||
| 63 |
2/3✓ Branch 36 → 37 taken 47 times.
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 51 taken 47 times.
|
47 | if (!m_push.probeBeforeUse("APPEND")) { |
| 64 | // failConnection() cancelled the journal token before dispatch. | ||
| 65 | ✗ | m_deps.appendFailed(requestId, QStringLiteral("Connection lost")); | |
| 66 | ✗ | m_deps.appendError(QStringLiteral("Connection lost")); | |
| 67 | ✗ | return; | |
| 68 | } | ||
| 69 |
3/3✓ Branch 51 → 52 taken 47 times.
✓ Branch 52 → 53 taken 5 times.
✓ Branch 52 → 61 taken 42 times.
|
47 | if (m_commands.hasStatefulCommandInFlight()) { |
| 70 |
2/8✓ Branch 56 → 57 taken 5 times.
✓ Branch 57 → 58 taken 5 times.
✗ Branch 245 → 246 not taken.
✗ Branch 245 → 247 not taken.
✗ Branch 248 → 249 not taken.
✗ Branch 248 → 250 not taken.
✗ Branch 251 → 252 not taken.
✗ Branch 251 → 253 not taken.
|
5 | m_commands.enqueueSerializedCommand([this, requestId, folder, rfcMessage, flags, |
| 71 | mutationToken]() { | ||
| 72 | 3 | appendMessageWithId(requestId, folder, rfcMessage, flags, | |
| 73 | mutationToken); | ||
| 74 | 3 | }); | |
| 75 | 5 | return; | |
| 76 | } | ||
| 77 | |||
| 78 | // Build: APPEND "folder" (\Flags) {size} | ||
| 79 |
2/2✓ Branch 65 → 66 taken 42 times.
✓ Branch 66 → 67 taken 42 times.
|
84 | QString cmd = QStringLiteral("APPEND %1").arg(ImapService::quoteMailboxName(folder)); |
| 80 |
2/2✓ Branch 71 → 72 taken 38 times.
✓ Branch 71 → 175 taken 4 times.
|
42 | if (!flags.isEmpty()) { |
| 81 | 38 | const QStringList flagTokens = flags.split(QLatin1Char(' '), | |
| 82 |
1/1✓ Branch 75 → 76 taken 38 times.
|
38 | Qt::SkipEmptyParts); |
| 83 |
2/2✓ Branch 114 → 78 taken 40 times.
✓ Branch 114 → 115 taken 32 times.
|
72 | for (const QString &flag : flagTokens) { |
| 84 |
3/3✓ Branch 79 → 80 taken 40 times.
✓ Branch 80 → 81 taken 6 times.
✓ Branch 80 → 112 taken 34 times.
|
40 | if (!ImapService::isValidImapFlag(flag)) { |
| 85 |
5/5✓ Branch 81 → 82 taken 6 times.
✓ Branch 85 → 86 taken 6 times.
✓ Branch 86 → 87 taken 6 times.
✓ Branch 90 → 83 taken 6 times.
✓ Branch 90 → 91 taken 6 times.
|
12 | qCWarning(lcImap) << "Refusing malformed APPEND flag token"; |
| 86 |
1/1✓ Branch 94 → 95 taken 6 times.
|
12 | m_deps.appendFailed(requestId, |
| 87 | 12 | QStringLiteral("Invalid IMAP flag token")); | |
| 88 |
1/1✓ Branch 100 → 101 taken 6 times.
|
12 | m_deps.appendError(QStringLiteral("Invalid IMAP flag token")); |
| 89 |
1/1✓ Branch 107 → 108 taken 6 times.
|
12 | m_mutations.completeMutation(mutationToken, MutationOutcome::Rejected, |
| 90 | 12 | QStringLiteral("Invalid IMAP flag token")); | |
| 91 | 6 | return; | |
| 92 | } | ||
| 93 | } | ||
| 94 |
2/3✓ Branch 119 → 120 taken 31 times.
✓ Branch 120 → 121 taken 31 times.
✗ Branch 120 → 132 not taken.
|
63 | if (flagTokens.isEmpty() || flags.contains(QLatin1Char('\t')) || |
| 95 |
6/8✓ Branch 116 → 117 taken 31 times.
✓ Branch 116 → 132 taken 1 time.
✓ Branch 123 → 124 taken 31 times.
✓ Branch 124 → 125 taken 31 times.
✗ Branch 124 → 132 not taken.
✓ Branch 127 → 128 taken 31 times.
✓ Branch 128 → 129 taken 31 times.
✗ Branch 128 → 132 not taken.
|
94 | flags.contains(QLatin1Char('\r')) || flags.contains(QLatin1Char('\n')) || |
| 96 |
4/5✓ Branch 130 → 131 taken 31 times.
✗ Branch 131 → 132 not taken.
✓ Branch 131 → 133 taken 31 times.
✓ Branch 134 → 135 taken 1 time.
✓ Branch 134 → 156 taken 31 times.
|
63 | flags.contains(QChar(0))) { |
| 97 |
1/1✓ Branch 138 → 139 taken 1 time.
|
2 | m_deps.appendFailed(requestId, QStringLiteral("Invalid IMAP flag token")); |
| 98 |
1/1✓ Branch 144 → 145 taken 1 time.
|
2 | m_deps.appendError(QStringLiteral("Invalid IMAP flag token")); |
| 99 |
1/1✓ Branch 151 → 152 taken 1 time.
|
2 | m_mutations.completeMutation(mutationToken, MutationOutcome::Rejected, |
| 100 | 2 | QStringLiteral("Invalid IMAP flag token")); | |
| 101 | 1 | return; | |
| 102 | } | ||
| 103 |
3/3✓ Branch 162 → 163 taken 31 times.
✓ Branch 163 → 164 taken 31 times.
✓ Branch 164 → 165 taken 31 times.
|
62 | cmd += QStringLiteral(" (%1)").arg(flagTokens.join(QLatin1Char(' '))); |
| 104 | 38 | } | |
| 105 |
2/2✓ Branch 180 → 181 taken 35 times.
✓ Branch 181 → 182 taken 35 times.
|
70 | cmd += QStringLiteral(" {%1}").arg(rfcMessage.size()); |
| 106 | |||
| 107 |
1/1✓ Branch 185 → 186 taken 35 times.
|
35 | resetAppendLiteral(); |
| 108 | 35 | ImapPendingCommand append; | |
| 109 | 35 | append.appendData = rfcMessage; | |
| 110 | 35 | append.appendFolder = folder; | |
| 111 | 35 | append.appendRequestId = requestId; | |
| 112 | 35 | append.appendToken = mutationToken; | |
| 113 |
2/2✓ Branch 190 → 191 taken 35 times.
✓ Branch 191 → 192 taken 35 times.
|
35 | m_commands.sendCommand("APPEND", cmd, std::move(append)); |
| 114 |
1/1✓ Branch 194 → 195 taken 35 times.
|
35 | m_mutations.markMutationDispatched(mutationToken); |
| 115 | 42 | } | |
| 116 | |||
| 117 | 2576 | void ImapAppendStream::resetAppendLiteral() { | |
| 118 | 2576 | ++m_appendLiteralGeneration; | |
| 119 | 2576 | m_appendLiteralStreaming = false; | |
| 120 | 2576 | m_appendPumpScheduled = false; | |
| 121 | 2576 | m_appendLiteralOffset = 0; | |
| 122 |
3/3✓ Branch 5 → 6 taken 2576 times.
✓ Branch 8 → 9 taken 28 times.
✓ Branch 8 → 10 taken 2548 times.
|
5152 | if (ImapPendingCommand *append = m_commands.recordOfType(QStringLiteral("APPEND"))) |
| 123 | 28 | append->appendData.clear(); | |
| 124 | 2576 | } | |
| 125 | |||
| 126 | 370 | void ImapAppendStream::scheduleAppendLiteralPump() { | |
| 127 |
3/4✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 4 taken 368 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
|
370 | if (!m_appendLiteralStreaming || m_appendPumpScheduled) return; |
| 128 | 2 | m_appendPumpScheduled = true; | |
| 129 | 2 | const quint64 generation = m_appendLiteralGeneration; | |
| 130 |
1/1✓ Branch 5 → 6 taken 2 times.
|
2 | QTimer::singleShot(0, m_owner, [this, generation] { |
| 131 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
|
2 | if (generation != m_appendLiteralGeneration) return; |
| 132 | 2 | m_appendPumpScheduled = false; | |
| 133 | 2 | pumpAppendLiteral(); | |
| 134 | }); | ||
| 135 | } | ||
| 136 | |||
| 137 | 3 | void ImapAppendStream::pumpAppendLiteral() { | |
| 138 |
1/1✓ Branch 5 → 6 taken 3 times.
|
6 | ImapPendingCommand *append = m_commands.recordOfType(QStringLiteral("APPEND")); |
| 139 |
4/8✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 12 not taken.
✓ Branch 9 → 10 taken 3 times.
✗ Branch 9 → 12 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 3 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 3 times.
|
3 | if (!m_appendLiteralStreaming || !append || append->appendData.isEmpty()) return; |
| 140 | 3 | const QByteArray &literal = append->appendData; | |
| 141 |
1/2✗ Branch 17 → 18 not taken.
✓ Branch 17 → 25 taken 3 times.
|
3 | if (m_socket->state() != QAbstractSocket::ConnectedState) { |
| 142 | ✗ | failConnection(QStringLiteral("APPEND literal socket closed")); | |
| 143 | ✗ | return; | |
| 144 | } | ||
| 145 | 3 | constexpr qint64 chunkBytes = 64 * 1024; | |
| 146 | 3 | constexpr qint64 windowBytes = 256 * 1024; | |
| 147 | 3 | qint64 turnBudget = windowBytes; | |
| 148 |
6/6✓ Branch 46 → 47 taken 12 times.
✓ Branch 46 → 49 taken 1 time.
✓ Branch 47 → 48 taken 10 times.
✓ Branch 47 → 49 taken 2 times.
✓ Branch 50 → 26 taken 10 times.
✓ Branch 50 → 51 taken 3 times.
|
13 | while (m_appendLiteralOffset < literal.size() && |
| 149 | turnBudget > 0) { | ||
| 150 | 10 | const qint64 available = windowBytes - m_socket->bytesToWrite(); | |
| 151 |
1/2✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 10 times.
|
10 | if (available <= 0) break; |
| 152 | ✗ | const qint64 count = std::min({chunkBytes, turnBudget, available, | |
| 153 | 10 | qint64(literal.size()) - | |
| 154 |
1/1✓ Branch 30 → 31 taken 10 times.
|
10 | m_appendLiteralOffset}); |
| 155 | 30 | const qint64 written = m_socket->write( | |
| 156 | 10 | literal.constData() + m_appendLiteralOffset, count); | |
| 157 |
1/2✗ Branch 33 → 34 not taken.
✓ Branch 33 → 41 taken 10 times.
|
10 | if (written < 0) { |
| 158 | ✗ | failConnection(QStringLiteral("APPEND literal write failed")); | |
| 159 | ✗ | return; | |
| 160 | } | ||
| 161 |
1/2✗ Branch 41 → 42 not taken.
✓ Branch 41 → 44 taken 10 times.
|
10 | if (written == 0) { |
| 162 | ✗ | const quint64 generation = m_appendLiteralGeneration; | |
| 163 | ✗ | QTimer::singleShot(10, m_owner, [this, generation] { | |
| 164 | ✗ | if (generation == m_appendLiteralGeneration) | |
| 165 | ✗ | scheduleAppendLiteralPump(); | |
| 166 | ✗ | }); | |
| 167 | ✗ | return; | |
| 168 | } | ||
| 169 | 10 | m_appendLiteralOffset += written; | |
| 170 | 10 | turnBudget -= written; | |
| 171 | 10 | m_commands.refreshCommandTimeout(); | |
| 172 | } | ||
| 173 |
2/2✓ Branch 52 → 53 taken 1 time.
✓ Branch 52 → 64 taken 2 times.
|
3 | if (m_appendLiteralOffset == literal.size()) { |
| 174 |
1/2✗ Branch 54 → 55 not taken.
✓ Branch 54 → 62 taken 1 time.
|
1 | if (m_socket->write("\r\n", 2) != 2) { |
| 175 | ✗ | failConnection(QStringLiteral("APPEND literal terminator write failed")); | |
| 176 | ✗ | return; | |
| 177 | } | ||
| 178 | 1 | resetAppendLiteral(); | |
| 179 | 1 | m_commands.refreshCommandTimeout(); | |
| 180 |
1/2✗ Branch 65 → 66 not taken.
✓ Branch 65 → 67 taken 2 times.
|
2 | } else if (m_socket->bytesToWrite() < windowBytes) { |
| 181 | // Even a socket that accepts writes immediately gets one bounded chunk | ||
| 182 | // per event turn, so TLS work cannot consume one large GUI frame. | ||
| 183 | ✗ | scheduleAppendLiteralPump(); | |
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | // T-176: APPEND literal continuation (cut out of the former processLine, | ||
| 188 | // S92.1.1; the line reader dispatches every "+" response here). | ||
| 189 | 31 | void ImapAppendStream::handleContinuation(const QString &line) { | |
| 190 | // T-176: APPEND literal continuation – server sent "+" | ||
| 191 | // T-79.A1/H1: only serve the payload while an APPEND is actually in | ||
| 192 | // flight; a "+" from any other command (e.g. "+ idling") must never | ||
| 193 | // flush a (stale) message into the command stream. | ||
| 194 | // FUNC-08: the payload lives in the APPEND tag's record, so a payload | ||
| 195 | // without an APPEND in flight (the former stale-payload case) cannot exist. | ||
| 196 |
1/1✓ Branch 5 → 6 taken 31 times.
|
62 | ImapPendingCommand *append = m_commands.recordOfType(QStringLiteral("APPEND")); |
| 197 |
6/7✓ Branch 8 → 9 taken 25 times.
✓ Branch 8 → 12 taken 6 times.
✓ Branch 10 → 11 taken 25 times.
✗ Branch 10 → 12 not taken.
✓ Branch 13 → 14 taken 25 times.
✓ Branch 13 → 35 taken 3 times.
✓ Branch 13 → 41 taken 3 times.
|
31 | if (append && !append->appendData.isEmpty()) { |
| 198 |
5/5✓ Branch 14 → 15 taken 25 times.
✓ Branch 18 → 19 taken 25 times.
✓ Branch 19 → 20 taken 25 times.
✓ Branch 26 → 16 taken 25 times.
✓ Branch 26 → 27 taken 25 times.
|
50 | qCInfo(lcImap) << "APPEND continuation: sending" |
| 199 |
2/2✓ Branch 21 → 22 taken 25 times.
✓ Branch 22 → 23 taken 25 times.
|
25 | << append->appendData.size() << "bytes"; |
| 200 | #ifdef MAILJD_E2E_TESTING | ||
| 201 |
1/1✓ Branch 30 → 31 taken 17 times.
|
34 | reportE2eTransportPhase(QStringLiteral("append-literal-write"), |
| 202 | append->appendRequestId); | ||
| 203 | #endif | ||
| 204 |
3/4✓ Branch 28 → 29 taken 8 times.
✗ Branch 28 → 33 not taken.
✓ Branch 34 → 35 taken 16 times.
✓ Branch 34 → 39 taken 1 time.
|
25 | if (append->appendData.size() <= 256 * 1024) { |
| 205 | 24 | m_socket->write(append->appendData); | |
| 206 | 24 | m_socket->write("\r\n"); | |
| 207 | 24 | resetAppendLiteral(); | |
| 208 | 24 | m_commands.refreshCommandTimeout(); | |
| 209 |
1/4✗ Branch 33 → 34 not taken.
✗ Branch 33 → 47 not taken.
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 62 not taken.
|
1 | } else if (!m_appendLiteralStreaming) { |
| 210 | 1 | m_appendLiteralStreaming = true; | |
| 211 | 1 | m_appendLiteralOffset = 0; | |
| 212 | 1 | pumpAppendLiteral(); | |
| 213 | } | ||
| 214 | } else { | ||
| 215 | #ifdef MAILJD_E2E_TESTING | ||
| 216 |
1/2✓ Branch 42 → 43 taken 3 times.
✗ Branch 42 → 50 not taken.
|
3 | if (m_push.isIdling()) |
| 217 |
1/1✓ Branch 46 → 47 taken 3 times.
|
3 | reportE2eTransportPhase( |
| 218 | 6 | QStringLiteral("idle-continuation-received")); | |
| 219 | #endif | ||
| 220 |
12/12✓ Branch 35 → 36 taken 3 times.
✓ Branch 39 → 40 taken 3 times.
✓ Branch 40 → 41 taken 3 times.
✓ Branch 41 → 42 taken 3 times.
✓ Branch 45 → 37 taken 3 times.
✓ Branch 45 → 46 taken 3 times.
✓ Branch 50 → 51 taken 3 times.
✓ Branch 54 → 55 taken 3 times.
✓ Branch 55 → 56 taken 3 times.
✓ Branch 56 → 57 taken 3 times.
✓ Branch 60 → 52 taken 3 times.
✓ Branch 60 → 61 taken 3 times.
|
12 | qCDebug(lcImap) << "Continuation response (ignored):" << line; |
| 221 | } | ||
| 222 | 31 | } | |
| 223 | 34 | void ImapAppendStream::handleTaggedAppend(const TaggedResponse &response, | |
| 224 | ImapPendingCommand &command) { | ||
| 225 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 10 taken 34 times.
|
34 | if (m_appendLiteralStreaming) { |
| 226 | // A tagged result before the literal terminator is queued leaves old | ||
| 227 | // bytes in the TLS buffer. Abort instead of letting a later command | ||
| 228 | // follow those bytes into an ambiguous protocol stream. | ||
| 229 | ✗ | failConnection(QStringLiteral("APPEND completed before literal upload")); | |
| 230 | ✗ | return; | |
| 231 | } | ||
| 232 |
2/2✓ Branch 11 → 12 taken 30 times.
✓ Branch 11 → 70 taken 4 times.
|
34 | if (response.status == "OK") { |
| 233 | // Parse APPENDUID if present: [APPENDUID <uidvalidity> <uid>] | ||
| 234 | 30 | qint64 appendedUid = 0; | |
| 235 | 30 | quint32 appendedUidValidity = 0; // Sprint 102: the mailbox identity of the UID | |
| 236 | static QRegularExpression appendUidRx( | ||
| 237 |
5/8✓ Branch 12 → 13 taken 7 times.
✓ Branch 12 → 22 taken 23 times.
✓ Branch 14 → 15 taken 7 times.
✗ Branch 14 → 22 not taken.
✓ Branch 16 → 17 taken 7 times.
✓ Branch 17 → 18 taken 7 times.
✗ Branch 104 → 105 not taken.
✗ Branch 104 → 106 not taken.
|
30 | R"(\[APPENDUID\s+(\d+)\s+(\d+)\])", QRegularExpression::CaseInsensitiveOption); |
| 238 |
1/1✓ Branch 23 → 24 taken 30 times.
|
30 | auto uidMatch = appendUidRx.match(response.message); |
| 239 |
3/3✓ Branch 24 → 25 taken 30 times.
✓ Branch 25 → 26 taken 12 times.
✓ Branch 25 → 46 taken 18 times.
|
30 | if (uidMatch.hasMatch()) { |
| 240 |
2/2✓ Branch 26 → 27 taken 12 times.
✓ Branch 27 → 28 taken 12 times.
|
12 | appendedUid = uidMatch.captured(2).toLongLong(); |
| 241 |
2/2✓ Branch 29 → 30 taken 12 times.
✓ Branch 30 → 31 taken 12 times.
|
12 | appendedUidValidity = uidMatch.captured(1).toUInt(); |
| 242 |
6/6✓ Branch 32 → 33 taken 12 times.
✓ Branch 36 → 37 taken 12 times.
✓ Branch 37 → 38 taken 12 times.
✓ Branch 38 → 39 taken 12 times.
✓ Branch 44 → 34 taken 12 times.
✓ Branch 44 → 45 taken 12 times.
|
24 | qCInfo(lcImap) << "APPEND complete, APPENDUID:" << appendedUid |
| 243 |
2/2✓ Branch 39 → 40 taken 12 times.
✓ Branch 40 → 41 taken 12 times.
|
12 | << "to" << command.appendFolder; |
| 244 | } else { | ||
| 245 |
5/5✓ Branch 46 → 47 taken 18 times.
✓ Branch 50 → 51 taken 18 times.
✓ Branch 51 → 52 taken 18 times.
✓ Branch 56 → 48 taken 18 times.
✓ Branch 56 → 57 taken 18 times.
|
36 | qCInfo(lcImap) << "APPEND complete (no UIDPLUS) to" |
| 246 |
1/1✓ Branch 52 → 53 taken 18 times.
|
18 | << command.appendFolder; |
| 247 | } | ||
| 248 |
3/3✓ Branch 58 → 59 taken 12 times.
✓ Branch 58 → 60 taken 18 times.
✓ Branch 61 → 62 taken 30 times.
|
30 | m_deps.appendCompleted(command.appendRequestId, command.appendFolder, |
| 249 | appendedUid, appendedUid > 0 ? appendedUidValidity : 0); | ||
| 250 |
1/1✓ Branch 62 → 63 taken 30 times.
|
30 | m_deps.messageAppended(command.appendFolder, appendedUid); |
| 251 |
1/1✓ Branch 65 → 66 taken 30 times.
|
30 | m_mutations.completeMutation(command.appendToken, |
| 252 | MutationOutcome::Confirmed, {}, | ||
| 253 |
1/1✓ Branch 63 → 64 taken 30 times.
|
60 | QString::number(appendedUid)); |
| 254 | 30 | } else { | |
| 255 |
6/6✓ Branch 70 → 71 taken 4 times.
✓ Branch 74 → 75 taken 4 times.
✓ Branch 75 → 76 taken 4 times.
✓ Branch 76 → 77 taken 4 times.
✓ Branch 80 → 72 taken 4 times.
✓ Branch 80 → 81 taken 4 times.
|
8 | qCWarning(lcImap) << "APPEND failed:" << response.message; |
| 256 | 4 | m_deps.appendFailed(command.appendRequestId, response.message); | |
| 257 | 4 | m_deps.appendError(response.message); | |
| 258 | 8 | m_mutations.completeMutation(command.appendToken, | |
| 259 |
1/1✓ Branch 84 → 85 taken 4 times.
|
4 | MutationOutcome::Rejected, response.message); |
| 260 | } | ||
| 261 | 34 | resetAppendLiteral(); | |
| 262 |
2/2✓ Branch 90 → 91 taken 2 times.
✓ Branch 90 → 92 taken 32 times.
|
34 | if (!m_commands.deferredCommands().isEmpty()) { |
| 263 | 2 | m_commands.runNextDeferredCommand(); | |
| 264 | } else { | ||
| 265 | 32 | m_push.restartPush(); | |
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | 2482 | void ImapAppendStream::resetForSession() { | |
| 270 | 2482 | resetAppendLiteral(); | |
| 271 | 2482 | } | |
| 272 | |||
| 273 | 2342 | bool ImapAppendStream::literalPending() { | |
| 274 |
1/1✓ Branch 5 → 6 taken 2342 times.
|
4684 | const ImapPendingCommand *append = m_commands.recordOfType(QStringLiteral("APPEND")); |
| 275 |
4/4✓ Branch 8 → 9 taken 3 times.
✓ Branch 8 → 12 taken 2339 times.
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 12 taken 1 time.
|
2342 | return append && !append->appendData.isEmpty(); |
| 276 | } | ||
| 277 |