diff --git a/NetworkAccessManager.hpp b/NetworkAccessManager.hpp new file mode 100644 index 000000000..2381621de --- /dev/null +++ b/NetworkAccessManager.hpp @@ -0,0 +1,63 @@ +#ifndef NETWORK_ACCESS_MANAGER_HPP__ +#define NETWORK_ACCESS_MANAGER_HPP__ + +#include +#include +#include +#include +#include + +#include "MessageBox.hpp" + +class QNetworkRequest; +class QIODevice; +class QWidget; + +// sub-class QNAM to keep a list of accepted SSL errors and allow +// them in future replies +class NetworkAccessManager + : public QNetworkAccessManager +{ +public: + NetworkAccessManager (QWidget * parent = nullptr) + : QNetworkAccessManager (parent) + { + // handle SSL errors that have not been cached as allowed + // exceptions and offer them to the user to add to the ignored + // exception cache + connect (this, &QNetworkAccessManager::sslErrors, [this, &parent] (QNetworkReply * reply, QList const& errors) { + QString message; + for (auto const& error: errors) + { + message += '\n' + reply->request ().url ().toDisplayString () + ": " + + error.errorString (); + } + QString certs; + for (auto const& cert : reply->sslConfiguration ().peerCertificateChain ()) + { + certs += cert.toText () + '\n'; + } + if (MessageBox::Ignore == MessageBox::query_message (parent, tr ("Network SSL Errors"), message, certs, MessageBox::Abort | MessageBox::Ignore)) + { + // accumulate SSL error exceptions that have been allowed + allowed_ssl_errors_.append (errors); + reply->ignoreSslErrors (errors); + } + }); + } + +protected: + QNetworkReply * createRequest (Operation operation, QNetworkRequest const& request, QIODevice * outgoing_data = nullptr) override + { + auto reply = QNetworkAccessManager::createRequest (operation, request, outgoing_data); + // errors are usually certificate specific so passing all cached + // exceptions here is ok + reply->ignoreSslErrors (allowed_ssl_errors_); + return reply; + } + +private: + QList allowed_ssl_errors_; +}; + +#endif diff --git a/main.cpp b/main.cpp index e1a415695..d5c5ab87b 100644 --- a/main.cpp +++ b/main.cpp @@ -8,8 +8,6 @@ #include #include -#include -#include #include #include #include @@ -316,25 +314,8 @@ int main(int argc, char *argv[]) ).toBool () ? 1u : 4u; } - QNetworkAccessManager network_manager {&a}; - // run the application UI - MainWindow w(temp_dir, multiple, &multi_settings, &mem_jt9, downSampleFactor, &network_manager, &splash); - - // set up handling for any SSL issues - QObject::connect (&network_manager, &QNetworkAccessManager::sslErrors, [&w] (QNetworkReply * reply, QList const& errors) { - QString message; - for (auto const& error: errors) - { - message += '\n' + reply->request ().url ().toDisplayString () + ": " - + error.errorString (); - } - if (QMessageBox::Ignore == QMessageBox::question (&w, "Network SSL Errors", message, QMessageBox::Abort | QMessageBox::Ignore)) - { - reply->ignoreSslErrors (); - } - }); - + MainWindow w(temp_dir, multiple, &multi_settings, &mem_jt9, downSampleFactor, &splash); w.show(); splash.raise (); QObject::connect (&a, SIGNAL (lastWindowClosed()), &a, SLOT (quit())); diff --git a/mainwindow.cpp b/mainwindow.cpp index 03f28947c..56d4413c2 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -26,6 +26,7 @@ #include "revision_utils.hpp" #include "qt_helpers.hpp" +#include "NetworkAccessManager.hpp" #include "soundout.h" #include "soundin.h" #include "Modulator.hpp" @@ -157,9 +158,10 @@ namespace //--------------------------------------------------- MainWindow constructor MainWindow::MainWindow(QDir const& temp_directory, bool multiple, MultiSettings * multi_settings, QSharedMemory *shdmem, - unsigned downSampleFactor, QNetworkAccessManager * network_manager, + unsigned downSampleFactor, QSplashScreen * splash, QWidget *parent) : QMainWindow(parent), + m_network_manager {this}, m_valid {true}, m_splash {splash}, m_dataDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}, @@ -254,7 +256,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_onAirFreq0 {0.0}, m_first_error {true}, tx_status_label {"Receiving"}, - wsprNet {new WSPRNet {network_manager, this}}, + wsprNet {new WSPRNet {&m_network_manager, this}}, m_appDir {QApplication::applicationDirPath ()}, m_palette {"Linrad"}, m_mode {"JT9"}, @@ -336,7 +338,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_config.udp_server_name (), m_config.udp_server_port (), this}}, psk_Reporter {new PSK_Reporter {m_messageClient, this}}, - m_manual {network_manager} + m_manual {&m_network_manager} { ui->setupUi(this); createStatusBar(); @@ -485,10 +487,10 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, ui->actionMediumDecode->setActionGroup(DepthGroup); ui->actionDeepestDecode->setActionGroup(DepthGroup); - connect (ui->download_samples_action, &QAction::triggered, [this, network_manager] () { + connect (ui->download_samples_action, &QAction::triggered, [this] () { if (!m_sampleDownloader) { - m_sampleDownloader.reset (new SampleDownloader {m_settings, &m_config, network_manager, this}); + m_sampleDownloader.reset (new SampleDownloader {m_settings, &m_config, &m_network_manager, this}); } m_sampleDownloader->show (); }); diff --git a/mainwindow.h b/mainwindow.h index c43c740f7..c470e5f58 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -35,6 +35,7 @@ #include "commons.h" #include "astro.h" #include "MessageBox.hpp" +#include "NetworkAccessManager.hpp" #define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync #define NUM_JT65_SYMBOLS 126 //63 data + 63 sync @@ -55,7 +56,6 @@ namespace Ui { } class QSettings; -class QNetworkAccessManager; class QLineEdit; class QFont; class QHostInfo; @@ -88,7 +88,6 @@ public: explicit MainWindow(QDir const& temp_directory, bool multiple, MultiSettings *, QSharedMemory *shdmem, unsigned downSampleFactor, - QNetworkAccessManager * network_manager, QSplashScreen *, QWidget *parent = nullptr); ~MainWindow(); @@ -279,6 +278,7 @@ private: void astroUpdate (); void writeAllTxt(QString message); + NetworkAccessManager m_network_manager; bool m_valid; QSplashScreen * m_splash; QDir m_dataDir;