diff --git a/SampleDownloader.cpp b/SampleDownloader.cpp index f096db37b..2ea930c1d 100644 --- a/SampleDownloader.cpp +++ b/SampleDownloader.cpp @@ -30,7 +30,7 @@ public: show (); raise (); activateWindow (); - directory_.refresh (); + directory_.refresh (http_only_check_box_.isChecked ()); } protected: @@ -46,6 +46,7 @@ private: SettingsGroup g (settings_, title); settings_->setValue ("geometry", saveGeometry ()); settings_->setValue ("SamplesURL", url_line_edit_.text ()); + settings_->setValue ("HTTPOnly", http_only_check_box_.isChecked ()); } Q_SLOT void button_clicked (QAbstractButton *); @@ -58,6 +59,7 @@ private: QWidget details_widget_; QFormLayout details_layout_; QLineEdit url_line_edit_; + QCheckBox http_only_check_box_; }; #include "SampleDownloader.moc" @@ -92,6 +94,7 @@ SampleDownloader::impl::impl (QSettings * settings SettingsGroup g {settings_, title}; restoreGeometry (settings_->value ("geometry", saveGeometry ()).toByteArray ()); url_line_edit_.setText (settings_->value ("SamplesURL", PROJECT_SAMPLES_URL).toString ()); + http_only_check_box_.setChecked (settings_->value ("HTTPOnly", false).toBool ()); directory_.url_root (url_line_edit_.text ()); } @@ -107,6 +110,8 @@ SampleDownloader::impl::impl (QSettings * settings details_widget_.hide (); details_layout_.setMargin (0); details_layout_.addRow ("Base URL for samples:", &url_line_edit_); + details_layout_.addRow ("Only use HTTP:", &http_only_check_box_); + http_only_check_box_.setToolTip ("Check this is you get SSL/TLS errors"); details_widget_.setLayout (&details_layout_); main_layout_.addLayout (&left_layout_, 0, 0); @@ -120,13 +125,16 @@ SampleDownloader::impl::impl (QSettings * settings connect (&url_line_edit_, &QLineEdit::editingFinished, [this] () { if (directory_.url_root (url_line_edit_.text ())) { - directory_.refresh (); + directory_.refresh (http_only_check_box_.isChecked ()); } else { MessageBox::warning_message (this, tr ("Input Error"), tr ("Invalid URL format")); } }); + connect (&http_only_check_box_, &QAbstractButton::toggled, [this] (bool checked) { + directory_.refresh (checked); + }); } void SampleDownloader::impl::button_clicked (QAbstractButton * button) @@ -142,7 +150,7 @@ void SampleDownloader::impl::button_clicked (QAbstractButton * button) break; case QDialogButtonBox::ResetRole: - directory_.refresh (); + directory_.refresh (http_only_check_box_.isChecked ()); break; default: diff --git a/SampleDownloader/Directory.cpp b/SampleDownloader/Directory.cpp index c6168e5ce..92c1c5cdf 100644 --- a/SampleDownloader/Directory.cpp +++ b/SampleDownloader/Directory.cpp @@ -37,6 +37,7 @@ Directory::Directory (Configuration const * configuration : QTreeWidget {parent} , configuration_ {configuration} , network_manager_ {network_manager} + , http_only_ {false} , root_dir_ {configuration_->save_directory ()} , contents_ {this , network_manager_ @@ -79,12 +80,12 @@ bool Directory::url_root (QUrl root) { root.setPath (root.path () + '/'); } - if (root.isValid ()) + bool valid = root.isValid (); + if (valid) { url_root_ = root; - refresh (); } - return root.isValid (); + return valid; } void Directory::error (QString const& title, QString const& message) @@ -92,7 +93,7 @@ void Directory::error (QString const& title, QString const& message) MessageBox::warning_message (this, title, message); } -bool Directory::refresh () +bool Directory::refresh (bool http_only) { abort (); clear (); @@ -100,6 +101,7 @@ bool Directory::refresh () root_dir_ = configuration_->save_directory (); QDir contents_dir {root_dir_.absoluteFilePath (samples_dir_name)}; contents_.local_file_path (contents_dir.absoluteFilePath (contents_file_name)); + contents_.http_only (http_only_ = http_only); QUrl url {url_root_.resolved (QDir {root_dir_.relativeFilePath (samples_dir_name)}.filePath (contents_file_name))}; if (url.isValid ()) { @@ -175,7 +177,7 @@ void Directory::parse_entries (QJsonArray const& entries, QDir const& dir, QTree { auto node = new FileNode {parent, network_manager_ , QDir {root_dir_.filePath (dir.path ())}.absoluteFilePath (name) - , url}; + , url, http_only_}; FileNode::sync_blocker b {node}; node->setIcon (0, file_icon_); node->setCheckState (0, node->local () ? Qt::Checked : Qt::Unchecked); @@ -255,28 +257,27 @@ namespace // maximum bytes to expect // int recurse_children (QTreeWidgetItem const * item, int * counted - , qint64 * bytes, qint64 * max) + , qint64 * bytes, qint64 * max) { int items {0}; for (int index {0}; index < item->childCount (); ++index) { - auto const * child = item->child (index); - qDebug () << "Item name:" << child->text (0); - if (child->type () == FileNode::Type) // only count files - { - ++items; - if (auto size = child->data (1, Qt::UserRole).toLongLong ()) - { - *max += size; - ++*counted; - } - *bytes += child->data (1, Qt::DisplayRole).toLongLong (); - } - else - { - // recurse into sub-directory subtrees - items += recurse_children (child, counted, bytes, max); - } + auto const * child = item->child (index); + if (child->type () == FileNode::Type) // only count files + { + ++items; + if (auto size = child->data (1, Qt::UserRole).toLongLong ()) + { + *max += size; + ++*counted; + } + *bytes += child->data (1, Qt::DisplayRole).toLongLong (); + } + else + { + // recurse into sub-directory subtrees + items += recurse_children (child, counted, bytes, max); + } } return items; } diff --git a/SampleDownloader/Directory.hpp b/SampleDownloader/Directory.hpp index 3e933c9f3..1ffae0d8c 100644 --- a/SampleDownloader/Directory.hpp +++ b/SampleDownloader/Directory.hpp @@ -33,7 +33,7 @@ public: QSize sizeHint () const override {return {400, 500};} bool url_root (QUrl); - bool refresh (); + bool refresh (bool http_only); void abort (); void update (QTreeWidgetItem * item); @@ -48,6 +48,7 @@ private: Configuration const * configuration_; QNetworkAccessManager * network_manager_; + bool http_only_; QDir root_dir_; QUrl url_root_; RemoteFile contents_; diff --git a/SampleDownloader/FileNode.cpp b/SampleDownloader/FileNode.cpp index 3bb6caf2a..85234f382 100644 --- a/SampleDownloader/FileNode.cpp +++ b/SampleDownloader/FileNode.cpp @@ -11,9 +11,10 @@ FileNode::FileNode (QTreeWidgetItem * parent , QNetworkAccessManager * network_manager , QString const& local_file_path - , QUrl const& url) + , QUrl const& url + , bool http_only) : QTreeWidgetItem {parent, Type} - , remote_file_ {this, network_manager, local_file_path} + , remote_file_ {this, network_manager, local_file_path, http_only} , block_sync_ {false} { sync_blocker b {this}; diff --git a/SampleDownloader/FileNode.hpp b/SampleDownloader/FileNode.hpp index 6261a1f27..4ba9f9d21 100644 --- a/SampleDownloader/FileNode.hpp +++ b/SampleDownloader/FileNode.hpp @@ -28,7 +28,8 @@ public: explicit FileNode (QTreeWidgetItem * parent , QNetworkAccessManager * network_manager , QString const& local_path - , QUrl const& url); + , QUrl const& url + , bool http_only); bool local () const {return remote_file_.local ();} bool sync (bool local); diff --git a/SampleDownloader/RemoteFile.cpp b/SampleDownloader/RemoteFile.cpp index ddcf6c40f..5aac13b4d 100644 --- a/SampleDownloader/RemoteFile.cpp +++ b/SampleDownloader/RemoteFile.cpp @@ -10,12 +10,12 @@ #include "moc_RemoteFile.cpp" RemoteFile::RemoteFile (ListenerInterface * listener, QNetworkAccessManager * network_manager - , QString const& local_file_path, QObject * parent) + , QString const& local_file_path, bool http_only, QObject * parent) : QObject {parent} , listener_ {listener} , network_manager_ {network_manager} , local_file_ {local_file_path} - , reply_ {nullptr} + , http_only_ {http_only} , is_valid_ {false} , redirect_count_ {0} , file_ {local_file_path} @@ -107,13 +107,17 @@ bool RemoteFile::sync (QUrl const& url, bool local, bool force) return true; } -void RemoteFile::download (QUrl const& url) +void RemoteFile::download (QUrl url) { if (QNetworkAccessManager::Accessible != network_manager_->networkAccessible ()) { // try and recover network access for QNAM network_manager_->setNetworkAccessible (QNetworkAccessManager::Accessible); } + if (url.isValid () && (!QSslSocket::supportsSsl () || http_only_)) + { + url.setScheme ("http"); + } QNetworkRequest request {url}; request.setRawHeader ("User-Agent", "WSJT Sample Downloader"); request.setOriginatingObject (this); @@ -151,9 +155,10 @@ void RemoteFile::abort () void RemoteFile::reply_finished () { - auto saved_reply = reply_; - auto redirect_url = reply_->attribute (QNetworkRequest::RedirectionTargetAttribute).toUrl (); - if (!redirect_url.isEmpty ()) + if (!reply_) return; // we probably deleted it in an + // earlier call + QUrl redirect_url {reply_->attribute (QNetworkRequest::RedirectionTargetAttribute).toUrl ()}; + if (reply_->error () == QNetworkReply::NoError && !redirect_url.isEmpty ()) { if (listener_->redirect_request (redirect_url)) { @@ -210,7 +215,7 @@ void RemoteFile::reply_finished () { // now get the body content is_valid_ = true; - download (reply_->url () .resolved (redirect_url)); + download (reply_->url ().resolved (redirect_url)); } else { @@ -219,9 +224,10 @@ void RemoteFile::reply_finished () } } } - if (reply_->isFinished ()) reply_ = nullptr; - disconnect (saved_reply); - saved_reply->deleteLater (); // finished with QNetworkReply + if (reply_ && reply_->isFinished ()) + { + reply_->deleteLater (); + } } void RemoteFile::store () diff --git a/SampleDownloader/RemoteFile.hpp b/SampleDownloader/RemoteFile.hpp index e1f0dbddd..3e6cb8514 100644 --- a/SampleDownloader/RemoteFile.hpp +++ b/SampleDownloader/RemoteFile.hpp @@ -6,6 +6,7 @@ #include #include #include +#include class QNetworkAccessManager; class QNetworkReply; @@ -38,7 +39,8 @@ public: }; explicit RemoteFile (ListenerInterface * listener, QNetworkAccessManager * network_manager - , QString const& local_file_path, QObject * parent = nullptr); + , QString const& local_file_path, bool http_only = false + , QObject * parent = nullptr); // true if local file exists or will do very soon bool local () const; @@ -55,8 +57,11 @@ public: QString local_file_path () const {return local_file_.absoluteFilePath ();} QUrl url () const {return url_;} + // always use an http scheme for remote URLs + void http_only (bool flag = true) {http_only_ = flag;} + private: - void download (QUrl const& url); + void download (QUrl url); void reply_finished (); Q_SLOT void store (); @@ -68,8 +73,9 @@ private: ListenerInterface * listener_; QNetworkAccessManager * network_manager_; QFileInfo local_file_; + bool http_only_; QUrl url_; - QNetworkReply * reply_; + QPointer reply_; bool is_valid_; unsigned redirect_count_; QSaveFile file_;