mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-17 09:31:59 -05:00
Fix various sample downloader issues especially server redirect handling
Thanks to Mike W9MDB for the concept of forcing to HTTP if OpenSSL is not installed or if the user requires it for other reasons. The sample downloader should now be usable with or without OpenSSL libraries being installed, so long as SourceForge continue to serve identical content from both HTTP and HTTPS schemes on their file servers and mirrors. For users with baulked OpenSSL installations, incorrect or incomplete CA certificate stores, either the improved capability to ignore SSL/TLS errors for the duration of a session at their discretion or, as a last resort a new option to force an HTTP URL scheme is provided. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7379 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
9af1379576
commit
440559f0c3
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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};
|
||||
|
@ -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);
|
||||
|
@ -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 ()
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <QUrl>
|
||||
#include <QFileInfo>
|
||||
#include <QSaveFile>
|
||||
#include <QPointer>
|
||||
|
||||
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<QNetworkReply> reply_;
|
||||
bool is_valid_;
|
||||
unsigned redirect_count_;
|
||||
QSaveFile file_;
|
||||
|
Loading…
Reference in New Issue
Block a user