mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-01-05 20:51:21 -05:00
Add NetworkRequest.
This commit is contained in:
parent
825657b217
commit
9d7d3dd5fd
@ -51,6 +51,7 @@ set(keepassx_SOURCES
|
|||||||
core/Merger.cpp
|
core/Merger.cpp
|
||||||
core/Metadata.cpp
|
core/Metadata.cpp
|
||||||
core/ModifiableObject.cpp
|
core/ModifiableObject.cpp
|
||||||
|
core/NetworkRequest.cpp
|
||||||
core/PasswordGenerator.cpp
|
core/PasswordGenerator.cpp
|
||||||
core/PasswordHealth.cpp
|
core/PasswordHealth.cpp
|
||||||
core/PassphraseGenerator.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