mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-31 18:26:20 -05:00
Add NetworkRequest.
This commit is contained in:
parent
825657b217
commit
9d7d3dd5fd
@ -51,6 +51,7 @@ set(keepassx_SOURCES
|
||||
core/Merger.cpp
|
||||
core/Metadata.cpp
|
||||
core/ModifiableObject.cpp
|
||||
core/NetworkRequest.cpp
|
||||
core/PasswordGenerator.cpp
|
||||
core/PasswordHealth.cpp
|
||||
core/PassphraseGenerator.cpp
|
||||
|
143
src/core/NetworkRequest.cpp
Normal file
143
src/core/NetworkRequest.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
|
||||
#include "NetworkRequest.h"
|
||||
#include "NetworkManager.h"
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
|
||||
namespace
|
||||
{
|
||||
QUrl getRedirectTarget(QNetworkReply* reply)
|
||||
{
|
||||
QVariant var = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
QUrl url;
|
||||
if (var.canConvert<QUrl>()) {
|
||||
url = var.toUrl();
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkRequest::fetch(const QUrl& url)
|
||||
{
|
||||
reset();
|
||||
|
||||
QNetworkRequest request(url);
|
||||
m_reply = m_manager->get(request);
|
||||
|
||||
connect(m_reply, &QNetworkReply::finished, this, &NetworkRequest::fetchFinished);
|
||||
connect(m_reply, &QIODevice::readyRead, this, &NetworkRequest::fetchReadyRead);
|
||||
}
|
||||
|
||||
void NetworkRequest::fetchFinished()
|
||||
{
|
||||
auto error = m_reply->error();
|
||||
QUrl redirectTarget = getRedirectTarget(m_reply);
|
||||
QUrl url = m_reply->url();
|
||||
// Returns an empty string if the header was not set
|
||||
QString contentTypeHeader = m_reply->header(QNetworkRequest::ContentTypeHeader).toString();
|
||||
|
||||
m_reply->deleteLater();
|
||||
m_reply = nullptr;
|
||||
|
||||
if(error != QNetworkReply::NoError) {
|
||||
// Do not emit on abort.
|
||||
if(error != QNetworkReply::OperationCanceledError) {
|
||||
emit failure();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (redirectTarget.isValid()) {
|
||||
// Redirected, we need to follow it, or fall through if we have
|
||||
// done too many redirects already.
|
||||
if (m_redirects < m_maxRedirects) {
|
||||
if (redirectTarget.isRelative()) {
|
||||
redirectTarget = url.resolved(redirectTarget);
|
||||
}
|
||||
// Request the redirect target
|
||||
fetch(redirectTarget);
|
||||
return;
|
||||
} else {
|
||||
emit failure();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse content type
|
||||
auto tokens = contentTypeHeader.split(";", Qt::SkipEmptyParts);
|
||||
m_content_type = tokens[0].trimmed();
|
||||
for(int i = 1; i < tokens.size(); ++i) {
|
||||
auto parameterTokens = tokens[i].split("=");
|
||||
m_content_type_parameters[parameterTokens[0]] = parameterTokens[1];
|
||||
}
|
||||
|
||||
emit success(std::move(m_bytes));
|
||||
}
|
||||
|
||||
void NetworkRequest::fetchReadyRead()
|
||||
{
|
||||
m_bytes += m_reply->readAll();
|
||||
}
|
||||
|
||||
void NetworkRequest::reset()
|
||||
{
|
||||
m_redirects = 0;
|
||||
m_bytes.clear();
|
||||
m_content_type = "";
|
||||
m_content_type_parameters.clear();
|
||||
m_timeout.setInterval(m_timeoutDuration);
|
||||
m_timeout.setSingleShot(true);
|
||||
}
|
||||
|
||||
void NetworkRequest::cancel()
|
||||
{
|
||||
if(m_reply) {
|
||||
m_reply->abort();
|
||||
}
|
||||
}
|
||||
|
||||
NetworkRequest::~NetworkRequest()
|
||||
{
|
||||
cancel();
|
||||
}
|
||||
|
||||
QUrl NetworkRequest::url() const
|
||||
{
|
||||
if(m_reply) {
|
||||
return m_reply->url();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void NetworkRequest::setMaxRedirects(int maxRedirects)
|
||||
{
|
||||
m_maxRedirects = std::max(0, maxRedirects);
|
||||
}
|
||||
|
||||
NetworkRequest::NetworkRequest(int maxRedirects, std::chrono::milliseconds timeoutDuration, QNetworkAccessManager* manager) : m_reply(nullptr), m_maxRedirects(maxRedirects), m_redirects(0), m_timeoutDuration(timeoutDuration)
|
||||
{
|
||||
m_manager = manager ? manager : getNetMgr();
|
||||
connect(&m_timeout, &QTimer::timeout, this, &NetworkRequest::fetchTimeout);
|
||||
}
|
||||
|
||||
const QString& NetworkRequest::ContentType() const
|
||||
{
|
||||
return m_content_type;
|
||||
}
|
||||
|
||||
const QHash<QString, QString>& NetworkRequest::ContentTypeParameters() const
|
||||
{
|
||||
return m_content_type_parameters;
|
||||
}
|
||||
|
||||
void NetworkRequest::setTimeout(std::chrono::milliseconds timeoutDuration)
|
||||
{
|
||||
m_timeoutDuration = timeoutDuration;
|
||||
}
|
||||
|
||||
void NetworkRequest::fetchTimeout()
|
||||
{
|
||||
// Cancel request on timeout
|
||||
cancel();
|
||||
}
|
56
src/core/NetworkRequest.h
Normal file
56
src/core/NetworkRequest.h
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
#ifndef KEEPASSXC_NETWORKREQUEST_H
|
||||
#define KEEPASSXC_NETWORKREQUEST_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QTimer>
|
||||
class QNetworkReply;
|
||||
class QNetworkAccessManager;
|
||||
|
||||
class NetworkRequest : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
QNetworkAccessManager* m_manager;
|
||||
QNetworkReply* m_reply;
|
||||
QByteArray m_bytes;
|
||||
|
||||
QString m_content_type;
|
||||
QHash<QString, QString> m_content_type_parameters;
|
||||
QTimer m_timeout;
|
||||
|
||||
int m_maxRedirects;
|
||||
int m_redirects;
|
||||
std::chrono::milliseconds m_timeoutDuration;
|
||||
public:
|
||||
explicit NetworkRequest(int maxRedirects, std::chrono::milliseconds timeoutDuration, QNetworkAccessManager* manager = nullptr);
|
||||
~NetworkRequest() override;
|
||||
|
||||
void setMaxRedirects(int maxRedirects);
|
||||
void setTimeout(std::chrono::milliseconds timeoutDuration);
|
||||
|
||||
void fetch(const QUrl& url);
|
||||
void cancel();
|
||||
|
||||
QUrl url() const;
|
||||
/***
|
||||
* @return The MIME Type set in the Content-Type header. Empty string if Content-Type was not set.
|
||||
*/
|
||||
const QString& ContentType() const;
|
||||
/***
|
||||
* @return Any parameters set in the Content-Type header.
|
||||
*/
|
||||
const QHash<QString, QString>& ContentTypeParameters() const;
|
||||
private:
|
||||
void reset();
|
||||
private slots:
|
||||
void fetchFinished();
|
||||
void fetchReadyRead();
|
||||
void fetchTimeout();
|
||||
|
||||
signals:
|
||||
void success(QByteArray);
|
||||
void failure();
|
||||
};
|
||||
|
||||
#endif // KEEPASSXC_NETWORKREQUEST_H
|
Loading…
Reference in New Issue
Block a user