1 /*
2 SPDX-FileCopyrightText: 2006-2007 Volker Krause <vkrause@kde.org>
3 SPDX-FileCopyrightText: 2007 KovoKs <info@kovoks.nl>
4 SPDX-FileCopyrightText: 2008 Thomas McGuire <thomas.mcguire@gmx.net>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8
9 // Own
10 #include "servertest.h"
11 #include "socket.h"
12
13 #include <mailtransport_defs.h>
14 #include <transportbase.h>
15
16 // Qt
17 #include <QHash>
18 #include <QHostInfo>
19 #include <QProgressBar>
20 #include <QRegularExpression>
21 #include <QSet>
22 #include <QTimer>
23
24 // KDE
25 #include "mailtransport_debug.h"
26
27 using namespace MailTransport;
28
29 namespace MailTransport
30 {
31 class ServerTestPrivate
32 {
33 public:
34 ServerTestPrivate(ServerTest *test);
35
36 ServerTest *const q;
37 QString server;
38 QString fakeHostname;
39 QString testProtocol;
40
41 MailTransport::Socket *normalSocket = nullptr;
42 MailTransport::Socket *secureSocket = nullptr;
43
44 QSet<int> connectionResults;
45 QHash<int, QVector<int>> authenticationResults;
46 QSet<ServerTest::Capability> capabilityResults;
47 QHash<int, uint> customPorts;
48 QTimer *normalSocketTimer = nullptr;
49 QTimer *secureSocketTimer = nullptr;
50 QTimer *progressTimer = nullptr;
51
52 QProgressBar *testProgress = nullptr;
53
54 bool secureSocketFinished = false;
55 bool normalSocketFinished = false;
56 bool tlsFinished = false;
57 bool popSupportsTLS;
58 int normalStage;
59 int secureStage;
60 int encryptionMode;
61
62 bool normalPossible = true;
63 bool securePossible = true;
64
65 void finalResult();
66 void handleSMTPIMAPResponse(int type, const QString &text);
67 void sendInitialCapabilityQuery(MailTransport::Socket *socket);
68 bool handlePopConversation(MailTransport::Socket *socket, int type, int stage, const QString &response, bool *shouldStartTLS);
69 bool handleNntpConversation(MailTransport::Socket *socket, int type, int *stage, const QString &response, bool *shouldStartTLS);
70 QVector<int> parseAuthenticationList(const QStringList &authentications);
71
isGmail(const QString & server) const72 inline bool isGmail(const QString &server) const
73 {
74 return server.endsWith(QLatin1String("gmail.com")) || server.endsWith(QLatin1String("googlemail.com"));
75 }
76
77 // slots
78 void slotNormalPossible();
79 void slotNormalNotPossible();
80 void slotSslPossible();
81 void slotSslNotPossible();
82 void slotTlsDone();
83 void slotReadNormal(const QString &text);
84 void slotReadSecure(const QString &text);
85 void slotUpdateProgress();
86 };
87 }
88
ServerTestPrivate(ServerTest * test)89 ServerTestPrivate::ServerTestPrivate(ServerTest *test)
90 : q(test)
91 {
92 }
93
finalResult()94 void ServerTestPrivate::finalResult()
95 {
96 if (!secureSocketFinished || !normalSocketFinished || !tlsFinished) {
97 return;
98 }
99
100 qCDebug(MAILTRANSPORT_LOG) << "Modes:" << connectionResults;
101 qCDebug(MAILTRANSPORT_LOG) << "Capabilities:" << capabilityResults;
102 qCDebug(MAILTRANSPORT_LOG) << "Normal:" << q->normalProtocols();
103 qCDebug(MAILTRANSPORT_LOG) << "SSL:" << q->secureProtocols();
104 qCDebug(MAILTRANSPORT_LOG) << "TLS:" << q->tlsProtocols();
105
106 if (testProgress) {
107 testProgress->hide();
108 }
109 progressTimer->stop();
110 secureSocketFinished = false;
111 normalSocketFinished = false;
112 tlsFinished = false;
113
114 QVector<int> resultsAsVector;
115 resultsAsVector.reserve(connectionResults.size());
116 for (int res : std::as_const(connectionResults)) {
117 resultsAsVector.append(res);
118 }
119
120 Q_EMIT q->finished(resultsAsVector);
121 }
122
parseAuthenticationList(const QStringList & authentications)123 QVector<int> ServerTestPrivate::parseAuthenticationList(const QStringList &authentications)
124 {
125 QVector<int> result;
126 for (QStringList::ConstIterator it = authentications.begin(); it != authentications.end(); ++it) {
127 QString current = (*it).toUpper();
128 if (current == QLatin1String("LOGIN")) {
129 result << Transport::EnumAuthenticationType::LOGIN;
130 } else if (current == QLatin1String("PLAIN")) {
131 result << Transport::EnumAuthenticationType::PLAIN;
132 } else if (current == QLatin1String("CRAM-MD5")) {
133 result << Transport::EnumAuthenticationType::CRAM_MD5;
134 } else if (current == QLatin1String("DIGEST-MD5")) {
135 result << Transport::EnumAuthenticationType::DIGEST_MD5;
136 } else if (current == QLatin1String("NTLM")) {
137 result << Transport::EnumAuthenticationType::NTLM;
138 } else if (current == QLatin1String("GSSAPI")) {
139 result << Transport::EnumAuthenticationType::GSSAPI;
140 } else if (current == QLatin1String("ANONYMOUS")) {
141 result << Transport::EnumAuthenticationType::ANONYMOUS;
142 } else if (current == QLatin1String("XOAUTH2")) {
143 if (isGmail(server)) {
144 result << Transport::EnumAuthenticationType::XOAUTH2;
145 }
146 }
147 // APOP is handled by handlePopConversation()
148 }
149 qCDebug(MAILTRANSPORT_LOG) << authentications << result;
150
151 // LOGIN doesn't offer anything over PLAIN, requires more server
152 // roundtrips and is not an official SASL mechanism, but a MS-ism,
153 // so only enable it if PLAIN isn't available:
154 if (result.contains(Transport::EnumAuthenticationType::PLAIN)) {
155 result.removeAll(Transport::EnumAuthenticationType::LOGIN);
156 }
157
158 return result;
159 }
160
handleSMTPIMAPResponse(int type,const QString & text)161 void ServerTestPrivate::handleSMTPIMAPResponse(int type, const QString &text)
162 {
163 if (!text.contains(QLatin1String("AUTH"), Qt::CaseInsensitive)) {
164 qCDebug(MAILTRANSPORT_LOG) << "No authentication possible";
165 return;
166 }
167
168 QStringList protocols;
169 if (isGmail(server)) {
170 protocols << QStringLiteral("XOAUTH2");
171 }
172
173 protocols << QStringLiteral("LOGIN") << QStringLiteral("PLAIN") << QStringLiteral("CRAM-MD5") << QStringLiteral("DIGEST-MD5") << QStringLiteral("NTLM")
174 << QStringLiteral("GSSAPI") << QStringLiteral("ANONYMOUS");
175
176 QStringList results;
177 for (int i = 0; i < protocols.count(); ++i) {
178 if (text.contains(protocols.at(i), Qt::CaseInsensitive)) {
179 results.append(protocols.at(i));
180 }
181 }
182
183 authenticationResults[type] = parseAuthenticationList(results);
184
185 // if we couldn't parse any authentication modes, default to clear-text
186 if (authenticationResults[type].isEmpty()) {
187 authenticationResults[type] << Transport::EnumAuthenticationType::CLEAR;
188 }
189
190 qCDebug(MAILTRANSPORT_LOG) << "For type" << type << ", we have:" << authenticationResults[type];
191 }
192
slotNormalPossible()193 void ServerTestPrivate::slotNormalPossible()
194 {
195 normalSocketTimer->stop();
196 connectionResults << Transport::EnumEncryption::None;
197 }
198
sendInitialCapabilityQuery(MailTransport::Socket * socket)199 void ServerTestPrivate::sendInitialCapabilityQuery(MailTransport::Socket *socket)
200 {
201 if (testProtocol == IMAP_PROTOCOL) {
202 socket->write(QStringLiteral("1 CAPABILITY"));
203 } else if (testProtocol == SMTP_PROTOCOL) {
204 // Detect the hostname which we send with the EHLO command.
205 // If there is a fake one set, use that, otherwise use the
206 // local host name (and make sure it contains a domain, so the
207 // server thinks it is valid).
208 QString hostname;
209 if (!fakeHostname.isNull()) {
210 hostname = fakeHostname;
211 } else {
212 hostname = QHostInfo::localHostName();
213 if (hostname.isEmpty()) {
214 hostname = QStringLiteral("localhost.invalid");
215 } else if (!hostname.contains(QChar::fromLatin1('.'))) {
216 hostname += QLatin1String(".localnet");
217 }
218 }
219 qCDebug(MAILTRANSPORT_LOG) << "Hostname for EHLO is" << hostname;
220
221 socket->write(QLatin1String("EHLO ") + hostname);
222 }
223 }
224
slotTlsDone()225 void ServerTestPrivate::slotTlsDone()
226 {
227 // The server will not send a response after starting TLS. Therefore, we have to manually
228 // call slotReadNormal(), because this is not triggered by a data received signal this time.
229 slotReadNormal(QString());
230 }
231
handlePopConversation(MailTransport::Socket * socket,int type,int stage,const QString & response,bool * shouldStartTLS)232 bool ServerTestPrivate::handlePopConversation(MailTransport::Socket *socket, int type, int stage, const QString &response, bool *shouldStartTLS)
233 {
234 Q_ASSERT(shouldStartTLS != nullptr);
235
236 // Initial Greeting
237 if (stage == 0) {
238 // Regexp taken from POP3 ioslave
239 const QString responseWithoutCRLF = response.isEmpty() ? response : response.chopped(2);
240 static const QRegularExpression re(QStringLiteral("<[A-Za-z0-9\\.\\-_]+@[A-Za-z0-9\\.\\-_]+>$"), QRegularExpression::CaseInsensitiveOption);
241 if (responseWithoutCRLF.indexOf(re) != -1) {
242 authenticationResults[type] << Transport::EnumAuthenticationType::APOP;
243 }
244
245 // Each server is supposed to support clear text login
246 authenticationResults[type] << Transport::EnumAuthenticationType::CLEAR;
247
248 // If we are in TLS stage, the server does not send the initial greeting.
249 // Assume that the APOP availability is the same as with an unsecured connection.
250 if (type == Transport::EnumEncryption::TLS
251 && authenticationResults[Transport::EnumEncryption::None].contains(Transport::EnumAuthenticationType::APOP)) {
252 authenticationResults[Transport::EnumEncryption::TLS] << Transport::EnumAuthenticationType::APOP;
253 }
254
255 socket->write(QStringLiteral("CAPA"));
256 return true;
257 }
258 // CAPA result
259 else if (stage == 1) {
260 // Example:
261 // CAPA
262 // +OK
263 // TOP
264 // USER
265 // SASL LOGIN CRAM-MD5
266 // UIDL
267 // RESP-CODES
268 // .
269 if (response.contains(QLatin1String("TOP"))) {
270 capabilityResults += ServerTest::Top;
271 }
272 if (response.contains(QLatin1String("PIPELINING"))) {
273 capabilityResults += ServerTest::Pipelining;
274 }
275 if (response.contains(QLatin1String("UIDL"))) {
276 capabilityResults += ServerTest::UIDL;
277 }
278 if (response.contains(QLatin1String("STLS"))) {
279 connectionResults << Transport::EnumEncryption::TLS;
280 popSupportsTLS = true;
281 }
282 socket->write(QStringLiteral("AUTH"));
283 return true;
284 }
285 // AUTH response
286 else if (stage == 2) {
287 // Example:
288 // C: AUTH
289 // S: +OK List of supported authentication methods follows
290 // S: LOGIN
291 // S: CRAM-MD5
292 // S:.
293 QString formattedReply = response;
294
295 // Get rid of trailing ".CRLF"
296 formattedReply.chop(3);
297
298 // Get rid of the first +OK line
299 formattedReply = formattedReply.right(formattedReply.size() - formattedReply.indexOf(QLatin1Char('\n')) - 1);
300 formattedReply = formattedReply.replace(QLatin1Char(' '), QLatin1Char('-')).replace(QLatin1String("\r\n"), QLatin1String(" "));
301
302 authenticationResults[type] += parseAuthenticationList(formattedReply.split(QLatin1Char(' ')));
303 }
304
305 *shouldStartTLS = popSupportsTLS;
306 return false;
307 }
308
handleNntpConversation(MailTransport::Socket * socket,int type,int * stage,const QString & response,bool * shouldStartTLS)309 bool ServerTestPrivate::handleNntpConversation(MailTransport::Socket *socket, int type, int *stage, const QString &response, bool *shouldStartTLS)
310 {
311 Q_ASSERT(shouldStartTLS != nullptr);
312 Q_ASSERT(stage != nullptr);
313
314 // Initial Greeting
315 if (*stage == 0) {
316 if (response.startsWith(QLatin1String("382 "))) {
317 return true;
318 }
319 if (!response.isEmpty() && !response.startsWith(QLatin1String("200 "))) {
320 return false;
321 }
322
323 socket->write(QStringLiteral("CAPABILITIES"));
324 return true;
325 }
326 // CAPABILITIES result
327 else if (*stage == 1) {
328 // Check whether we got "500 command 'CAPABILITIES' not recognized"
329 if (response.startsWith(QLatin1String("500 "))) {
330 return false;
331 }
332
333 // Example:
334 // 101 Capability list:
335 // VERSION 2
336 // IMPLEMENTATION INN 2.5.4
337 // AUTHINFO USER SASL
338 // HDR
339 // LIST ACTIVE [etc]
340 // OVER
341 // POST
342 // READER
343 // SASL DIGEST-MD5 CRAM-MD5 NTLM PLAIN LOGIN
344 // STARTTLS
345 // .
346 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
347 const QVector<QStringView> lines = QStringView(response).split(QStringLiteral("\r\n"), Qt::SkipEmptyParts);
348 for (const QStringView line : lines) {
349 #else
350 const QVector<QStringRef> lines = response.splitRef(QStringLiteral("\r\n"), Qt::SkipEmptyParts);
351 for (const QStringRef &line : lines) {
352 #endif
353 if (line.compare(QLatin1String("STARTTLS"), Qt::CaseInsensitive) == 0) {
354 *shouldStartTLS = true;
355 } else if (line.startsWith(QLatin1String("AUTHINFO "), Qt::CaseInsensitive)) {
356 const QVector<QStringRef> authinfos = line.split(QLatin1Char(' '), Qt::SkipEmptyParts);
357 const QString s(QStringLiteral("USER"));
358 const QStringRef ref(&s);
359 if (authinfos.contains(ref)) {
360 authenticationResults[type].append(Transport::EnumAuthenticationType::CLEAR); // XXX
361 }
362 } else if (line.startsWith(QLatin1String("SASL "), Qt::CaseInsensitive)) {
363 const QStringList auths = line.mid(5).toString().split(QLatin1Char(' '), Qt::SkipEmptyParts);
364 authenticationResults[type] += parseAuthenticationList(auths);
365 } else if (line == QLatin1Char('.')) {
366 return false;
367 }
368 }
369 // We have not hit the end of the capabilities list yet,
370 // so avoid the stage counter to rise without reason.
371 --(*stage);
372 return true;
373 }
374
375 return false;
376 }
377
378 // slotReadNormal() handles normal (no) encryption and TLS encryption.
379 // At first, the communication is not encrypted, but if the server supports
380 // the STARTTLS/STLS keyword, the same authentication query is done again
381 // with TLS.
382 void ServerTestPrivate::slotReadNormal(const QString &text)
383 {
384 Q_ASSERT(encryptionMode != Transport::EnumEncryption::SSL);
385 static const int tlsHandshakeStage = 42;
386
387 qCDebug(MAILTRANSPORT_LOG) << "Stage" << normalStage + 1 << ", Mode" << encryptionMode;
388
389 // If we are in stage 42, we just do the handshake for TLS encryption and
390 // then reset the stage to -1, so that all authentication modes and
391 // capabilities are queried again for TLS encryption (some servers have
392 // different authentication methods in normal and in TLS mode).
393 if (normalStage == tlsHandshakeStage) {
394 Q_ASSERT(encryptionMode == Transport::EnumEncryption::TLS);
395 normalStage = -1;
396 normalSocket->startTLS();
397 return;
398 }
399
400 bool shouldStartTLS = false;
401 normalStage++;
402
403 // Handle the whole POP and NNTP conversations separately, as
404 // they are very different from IMAP and SMTP
405 if (testProtocol == POP_PROTOCOL) {
406 if (handlePopConversation(normalSocket, encryptionMode, normalStage, text, &shouldStartTLS)) {
407 return;
408 }
409 } else if (testProtocol == NNTP_PROTOCOL) {
410 if (handleNntpConversation(normalSocket, encryptionMode, &normalStage, text, &shouldStartTLS)) {
411 return;
412 }
413 } else {
414 // Handle the SMTP/IMAP conversation here. We just send the EHLO command in
415 // sendInitialCapabilityQuery.
416 if (normalStage == 0) {
417 sendInitialCapabilityQuery(normalSocket);
418 return;
419 }
420
421 if (text.contains(QLatin1String("STARTTLS"), Qt::CaseInsensitive)) {
422 connectionResults << Transport::EnumEncryption::TLS;
423 shouldStartTLS = true;
424 }
425 handleSMTPIMAPResponse(encryptionMode, text);
426 }
427
428 // If we reach here, the normal authentication/capabilities query is completed.
429 // Now do the same for TLS.
430 normalSocketFinished = true;
431
432 // If the server announced that STARTTLS/STLS is available, we'll add TLS to the
433 // connection result, do the command and set the stage to 42 to start the handshake.
434 if (shouldStartTLS && encryptionMode == Transport::EnumEncryption::None) {
435 qCDebug(MAILTRANSPORT_LOG) << "Trying TLS...";
436 connectionResults << Transport::EnumEncryption::TLS;
437 if (testProtocol == POP_PROTOCOL) {
438 normalSocket->write(QStringLiteral("STLS"));
439 } else if (testProtocol == IMAP_PROTOCOL) {
440 normalSocket->write(QStringLiteral("2 STARTTLS"));
441 } else {
442 normalSocket->write(QStringLiteral("STARTTLS"));
443 }
444 encryptionMode = Transport::EnumEncryption::TLS;
445 normalStage = tlsHandshakeStage;
446 return;
447 }
448
449 // If we reach here, either the TLS authentication/capabilities query is finished
450 // or the server does not support the STARTTLS/STLS command.
451 tlsFinished = true;
452 finalResult();
453 }
454
455 void ServerTestPrivate::slotReadSecure(const QString &text)
456 {
457 secureStage++;
458 if (testProtocol == POP_PROTOCOL) {
459 bool dummy;
460 if (handlePopConversation(secureSocket, Transport::EnumEncryption::SSL, secureStage, text, &dummy)) {
461 return;
462 }
463 } else if (testProtocol == NNTP_PROTOCOL) {
464 bool dummy;
465 if (handleNntpConversation(secureSocket, Transport::EnumEncryption::SSL, &secureStage, text, &dummy)) {
466 return;
467 }
468 } else {
469 if (secureStage == 0) {
470 sendInitialCapabilityQuery(secureSocket);
471 return;
472 }
473 handleSMTPIMAPResponse(Transport::EnumEncryption::SSL, text);
474 }
475 secureSocketFinished = true;
476 finalResult();
477 }
478
479 void ServerTestPrivate::slotNormalNotPossible()
480 {
481 if (testProtocol == SMTP_PROTOCOL && normalSocket->port() == SMTP_PORT) {
482 // For SMTP, fallback to port 25
483 normalSocket->setPort(SMTP_OLD_PORT);
484 normalSocket->reconnect();
485 normalSocketTimer->start(10000);
486 return;
487 }
488
489 normalSocketTimer->stop();
490 normalPossible = false;
491 normalSocketFinished = true;
492 tlsFinished = true;
493 finalResult();
494 }
495
496 void ServerTestPrivate::slotSslPossible()
497 {
498 secureSocketTimer->stop();
499 connectionResults << Transport::EnumEncryption::SSL;
500 }
501
502 void ServerTestPrivate::slotSslNotPossible()
503 {
504 secureSocketTimer->stop();
505 securePossible = false;
506 secureSocketFinished = true;
507 finalResult();
508 }
509
510 void ServerTestPrivate::slotUpdateProgress()
511 {
512 if (testProgress) {
513 testProgress->setValue(testProgress->value() + 1);
514 }
515 }
516
517 //---------------------- end private class -----------------------//
518
519 ServerTest::ServerTest(QObject *parent)
520 : QObject(parent)
521 , d(new ServerTestPrivate(this))
522 {
523 d->normalSocketTimer = new QTimer(this);
524 d->normalSocketTimer->setSingleShot(true);
525 connect(d->normalSocketTimer, SIGNAL(timeout()), SLOT(slotNormalNotPossible()));
526
527 d->secureSocketTimer = new QTimer(this);
528 d->secureSocketTimer->setSingleShot(true);
529 connect(d->secureSocketTimer, SIGNAL(timeout()), SLOT(slotSslNotPossible()));
530
531 d->progressTimer = new QTimer(this);
532 connect(d->progressTimer, SIGNAL(timeout()), SLOT(slotUpdateProgress()));
533 }
534
535 ServerTest::~ServerTest() = default;
536
537 void ServerTest::start()
538 {
539 qCDebug(MAILTRANSPORT_LOG) << d.get();
540
541 d->connectionResults.clear();
542 d->authenticationResults.clear();
543 d->capabilityResults.clear();
544 d->popSupportsTLS = false;
545 d->normalStage = -1;
546 d->secureStage = -1;
547 d->encryptionMode = Transport::EnumEncryption::None;
548 d->normalPossible = true;
549 d->securePossible = true;
550
551 if (d->testProgress) {
552 d->testProgress->setMaximum(20);
553 d->testProgress->setValue(0);
554 d->testProgress->setTextVisible(true);
555 d->testProgress->show();
556 d->progressTimer->start(1000);
557 }
558
559 d->normalSocket = new MailTransport::Socket(this);
560 d->secureSocket = new MailTransport::Socket(this);
561 d->normalSocket->setObjectName(QStringLiteral("normal"));
562 d->normalSocket->setServer(d->server);
563 d->normalSocket->setProtocol(d->testProtocol);
564 if (d->testProtocol == IMAP_PROTOCOL) {
565 d->normalSocket->setPort(IMAP_PORT);
566 d->secureSocket->setPort(IMAPS_PORT);
567 } else if (d->testProtocol == SMTP_PROTOCOL) {
568 d->normalSocket->setPort(SMTP_PORT);
569 d->secureSocket->setPort(SMTPS_PORT);
570 } else if (d->testProtocol == POP_PROTOCOL) {
571 d->normalSocket->setPort(POP_PORT);
572 d->secureSocket->setPort(POPS_PORT);
573 } else if (d->testProtocol == NNTP_PROTOCOL) {
574 d->normalSocket->setPort(NNTP_PORT);
575 d->secureSocket->setPort(NNTPS_PORT);
576 }
577
578 if (d->customPorts.contains(Transport::EnumEncryption::None)) {
579 d->normalSocket->setPort(d->customPorts.value(Transport::EnumEncryption::None));
580 }
581 if (d->customPorts.contains(Transport::EnumEncryption::SSL)) {
582 d->secureSocket->setPort(d->customPorts.value(Transport::EnumEncryption::SSL));
583 }
584
585 connect(d->normalSocket, SIGNAL(connected()), SLOT(slotNormalPossible()));
586 connect(d->normalSocket, SIGNAL(failed()), SLOT(slotNormalNotPossible()));
587 connect(d->normalSocket, SIGNAL(data(QString)), SLOT(slotReadNormal(QString)));
588 connect(d->normalSocket, SIGNAL(tlsDone()), SLOT(slotTlsDone()));
589 d->normalSocket->reconnect();
590 d->normalSocketTimer->start(10000);
591
592 if (d->secureSocket->port() > 0) {
593 d->secureSocket->setObjectName(QStringLiteral("secure"));
594 d->secureSocket->setServer(d->server);
595 d->secureSocket->setProtocol(d->testProtocol + QLatin1Char('s'));
596 d->secureSocket->setSecure(true);
597 connect(d->secureSocket, SIGNAL(connected()), SLOT(slotSslPossible()));
598 connect(d->secureSocket, SIGNAL(failed()), SLOT(slotSslNotPossible()));
599 connect(d->secureSocket, SIGNAL(data(QString)), SLOT(slotReadSecure(QString)));
600 d->secureSocket->reconnect();
601 d->secureSocketTimer->start(10000);
602 } else {
603 d->slotSslNotPossible();
604 }
605 }
606
607 void ServerTest::setFakeHostname(const QString &fakeHostname)
608 {
609 d->fakeHostname = fakeHostname;
610 }
611
612 QString ServerTest::fakeHostname() const
613 {
614 return d->fakeHostname;
615 }
616
617 void ServerTest::setServer(const QString &server)
618 {
619 d->server = server;
620 }
621
622 void ServerTest::setPort(Transport::EnumEncryption::type encryptionMode, uint port)
623 {
624 Q_ASSERT(encryptionMode == Transport::EnumEncryption::None || encryptionMode == Transport::EnumEncryption::SSL);
625 d->customPorts.insert(encryptionMode, port);
626 }
627
628 void ServerTest::setProgressBar(QProgressBar *pb)
629 {
630 d->testProgress = pb;
631 }
632
633 void ServerTest::setProtocol(const QString &protocol)
634 {
635 d->testProtocol = protocol;
636 d->customPorts.clear();
637 }
638
639 QString ServerTest::protocol() const
640 {
641 return d->testProtocol;
642 }
643
644 QString ServerTest::server() const
645 {
646 return d->server;
647 }
648
649 int ServerTest::port(TransportBase::EnumEncryption::type encryptionMode) const
650 {
651 Q_ASSERT(encryptionMode == Transport::EnumEncryption::None || encryptionMode == Transport::EnumEncryption::SSL);
652 if (d->customPorts.contains(encryptionMode)) {
653 return d->customPorts.value(static_cast<int>(encryptionMode));
654 } else {
655 return -1;
656 }
657 }
658
659 QProgressBar *ServerTest::progressBar() const
660 {
661 return d->testProgress;
662 }
663
664 QVector<int> ServerTest::normalProtocols() const
665 {
666 return d->authenticationResults[TransportBase::EnumEncryption::None];
667 }
668
669 bool ServerTest::isNormalPossible() const
670 {
671 return d->normalPossible;
672 }
673
674 QVector<int> ServerTest::tlsProtocols() const
675 {
676 return d->authenticationResults[TransportBase::EnumEncryption::TLS];
677 }
678
679 QVector<int> ServerTest::secureProtocols() const
680 {
681 return d->authenticationResults[Transport::EnumEncryption::SSL];
682 }
683
684 bool ServerTest::isSecurePossible() const
685 {
686 return d->securePossible;
687 }
688
689 QList<ServerTest::Capability> ServerTest::capabilities() const
690 {
691 return d->capabilityResults.values();
692 }
693
694 #include "moc_servertest.cpp"
695