GeezerVison is showing raw.githubusercontent.com — raw.githubusercontent.com
#include
#include
#include
#include
#include
#include "RemoteNetwork.h"
#include "Settings.h"
#include "version.h"
RemoteNetwork::RemoteNetwork() :
m_manager(new QNetworkAccessManager)
{
// Load settings and set up some more stuff while doing so
reloadSettings();
// Set up signals
connect(m_manager, &QNetworkAccessManager::sslErrors, this, &RemoteNetwork::gotError);
}
RemoteNetwork::~RemoteNetwork()
{
delete m_manager;
}
void RemoteNetwork::reloadSettings()
{
// Configure proxy to use
{
QString type = Settings::getValue("proxy", "type").toString();
QNetworkProxy proxy;
if(type == "system")
{
// For system settings we have to get the system-wide proxy and use that
// Get list of proxies for accessing sqlitebrowser.org via HTTPS and use the first one
auto list = QNetworkProxyFactory::systemProxyForQuery(QNetworkProxyQuery(QUrl("https://sqlitebrowser.org/")));
proxy = list.front();
} else {
// For any other type we have to set up our own proxy configuration
// Retrieve the required settings
QString host = Settings::getValue("proxy", "host").toString();
unsigned short port = static_cast(Settings::getValue("proxy", "port").toUInt());
bool authentication = Settings::getValue("proxy", "authentication").toBool();
if(type == "http")
proxy.setType(QNetworkProxy::HttpProxy);
else if(type == "socks5")
proxy.setType(QNetworkProxy::Socks5Proxy);
else
proxy.setType(QNetworkProxy::NoProxy);
proxy.setHostName(host);
proxy.setPort(port);
// Only set authentication details when authentication is required
if(authentication)
{
QString user = Settings::getValue("proxy", "user").toString();
QString password = Settings::getValue("proxy", "password").toString();
proxy.setUser(user);
proxy.setPassword(password);
}
}
// Start using the new proxy configuration
QNetworkProxy::setApplicationProxy(proxy);
}
}
void RemoteNetwork::gotReply(QNetworkReply* reply)
{
// What type of data is this?
RequestType type = static_cast(reply->property("type").toInt());
// Handle the reply data
switch(type)
{
case RequestTypeCustom:
break;
}
// Delete reply later, i.e. after returning from this slot function
reply->deleteLater();
}
void RemoteNetwork::fetch(const QUrl& url, RequestType type, std::function when_finished, bool synchronous, bool ignore_errors)
{
// Build network request
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("User-Agent", QString("%1 %2").arg(qApp->organizationName(), APP_VERSION).toUtf8());
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
#elif QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
#endif
// Fetch database and prepare pending reply for future processing
QNetworkReply* reply = m_manager->get(request);
reply->setProperty("type", type);
reply->setProperty("ignore_errors", ignore_errors);
// Hook up custom handler when there is one and global handler otherwise
if(when_finished)
{
connect(reply, &QNetworkReply::finished, reply, [this, when_finished, reply]() {
if(handleReply(reply))
when_finished(reply->readAll());
});
} else {
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
if(handleReply(reply))
gotReply(reply);
});
}
// When the synchrounous flag is set we wait for the request to finish before continuing
if(synchronous)
{
QEventLoop loop;
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
}
}
void RemoteNetwork::gotError(QNetworkReply* reply, const QList& errors)
{
// Are there any errors in here that aren't about self-signed certificates and non-matching hostnames?
bool serious_errors = std::any_of(errors.begin(), errors.end(), [](const QSslError& error) { return error.error() != QSslError::SelfSignedCertificate; });
// Just stop the error checking here and accept the reply if there were no 'serious' errors
if(!serious_errors)
{
reply->ignoreSslErrors(errors);
return;
}
// Build an error message and show it to the user
QString message = tr("Error opening remote file at %1.\n%2").arg(reply->url().toString(), errors.at(0).errorString());
QMessageBox::warning(nullptr, qApp->applicationName(), message);
// Delete reply later, i.e. after returning from this slot function
reply->deleteLater();
}
bool RemoteNetwork::handleReply(QNetworkReply* reply)
{
// Check if request was successful
if(reply->error() != QNetworkReply::NoError)
{
// Do not show error message when operation was cancelled on purpose
if(reply->error() != QNetworkReply::OperationCanceledError && !reply->property("ignore_errors").toBool())
{
QMessageBox::warning(nullptr, qApp->applicationName(),
reply->errorString() + "\n" + reply->readAll());
}
reply->deleteLater();
return false;
}
return true;
}