Attica

atticabasejob.cpp
1/*
2 This file is part of KDE.
3
4 SPDX-FileCopyrightText: 2008 Cornelius Schumacher <schumacher@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7*/
8
9#include "atticabasejob.h"
10
11#include <QAuthenticator>
12#include <QDebug>
13#include <QNetworkReply>
14#include <QTimer>
15
16#include "platformdependent.h"
17#include <attica_debug.h>
18#include <atticautils.h>
19
20using namespace Attica;
21
22class Q_DECL_HIDDEN BaseJob::Private
23{
24public:
25 Metadata m_metadata;
26 PlatformDependent *m_internals;
27 QNetworkReply *m_reply;
28 bool aborted{false};
29 bool started = false;
30
31 Private(PlatformDependent *internals)
32 : m_internals(internals)
33 , m_reply(nullptr)
34 {
35 }
36
37 bool redirection(QUrl &newUrl) const
38 {
39 if (m_reply == nullptr || m_reply->error() != QNetworkReply::NoError) {
40 return false;
41 }
42
43 const int httpStatusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
44 if (httpStatusCode == 301 // Moved Permanently
45 || httpStatusCode == 302 // Found
46 || httpStatusCode == 303 // See Other
47 || httpStatusCode == 307) { // Temporary Redirect
48 QNetworkRequest request = m_reply->request();
50 if (redirectUrl.isRelative()) {
51 QUrl baseUrl(request.url());
52 newUrl = baseUrl.resolved(redirectUrl);
53 qCDebug(ATTICA) << "resolving relative URL redirection to" << newUrl.toString();
54 } else {
55 newUrl = redirectUrl;
56 qCDebug(ATTICA) << "resolving absolute URL redirection to" << newUrl.toString();
57 }
58 return true;
59 }
60
61 return false;
62 }
63};
64
65BaseJob::BaseJob(PlatformDependent *internals)
66 : d(new Private(internals))
67{
68}
69
70BaseJob::~BaseJob()
71{
72 delete d;
73}
74
75void BaseJob::dataFinished()
76{
77 if (!d->m_reply) {
78 return;
79 }
80
81 bool error = d->m_reply->error() != QNetworkReply::NoError && d->m_reply->error() != QNetworkReply::OperationCanceledError;
82
83 // handle redirections automatically
84 QUrl newUrl;
85 if (d->redirection(newUrl)) {
86 // qCDebug(ATTICA) << "BaseJob::dataFinished" << newUrl;
87 QNetworkRequest request = d->m_reply->request();
88 QNetworkAccessManager::Operation operation = d->m_reply->operation();
89 if (newUrl.isValid() && operation == QNetworkAccessManager::GetOperation) {
90 d->m_reply->deleteLater();
91 // reissue same request with different Url
92 request.setUrl(newUrl);
93 d->m_reply = internals()->get(request);
94 connect(d->m_reply, &QNetworkReply::finished, this, &BaseJob::dataFinished);
95 return;
96 } else {
97 error = true;
98 }
99 }
100
101 if (error) {
102 d->m_metadata.setError(Metadata::NetworkError);
103 d->m_metadata.setStatusCode(d->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt());
104 d->m_metadata.setStatusString(d->m_reply->errorString());
105 d->m_metadata.setHeaders(d->m_reply->rawHeaderPairs());
106 } else if (d->m_reply->error() == QNetworkReply::OperationCanceledError) {
107 d->m_metadata.setError(Metadata::NoError);
108 } else {
109 QByteArray data = d->m_reply->readAll();
110 // qCDebug(ATTICA) << "XML Returned:\n" << data;
111 parse(QString::fromUtf8(data.constData()));
112 if (d->m_metadata.statusCode() >= 100 && d->m_metadata.statusCode() < 200) {
113 d->m_metadata.setError(Metadata::NoError);
114 } else {
115 d->m_metadata.setError(Metadata::OcsError);
116 }
117 }
118 Q_EMIT finished(this);
119
120 d->m_reply->deleteLater();
121 deleteLater();
122}
123
124void BaseJob::start()
125{
126 if (!d->started) {
127 d->started = true;
128 QTimer::singleShot(0, this, &BaseJob::doWork);
129 }
130}
131
132void BaseJob::doWork()
133{
134 if (d->aborted) {
135 return;
136 }
137 d->m_reply = executeRequest();
138 qCDebug(ATTICA) << "executing" << Utils::toString(d->m_reply->operation()) << "request for" << d->m_reply->url();
139 connect(d->m_reply, &QNetworkReply::finished, this, &BaseJob::dataFinished);
140 connect(d->m_reply->manager(), &QNetworkAccessManager::authenticationRequired, this, &BaseJob::authenticationRequired);
142 qCDebug(ATTICA) << "error found" << code;
143 });
144}
145
146void BaseJob::authenticationRequired(QNetworkReply *reply, QAuthenticator *auth)
147{
148 auth->setUser(reply->request().attribute((QNetworkRequest::Attribute)BaseJob::UserAttribute).toString());
149 auth->setPassword(reply->request().attribute((QNetworkRequest::Attribute)BaseJob::PasswordAttribute).toString());
150}
151
152void BaseJob::abort()
153{
154 d->aborted = true;
155 if (d->m_reply) {
156 d->m_reply->abort();
157 d->m_reply->deleteLater();
158 }
159 deleteLater();
160}
161
163{
164 return d->aborted;
165}
166
167PlatformDependent *BaseJob::internals()
168{
169 return d->m_internals;
170}
171
172Metadata BaseJob::metadata() const
173{
174 return d->m_metadata;
175}
176
177void BaseJob::setMetadata(const Attica::Metadata &data) const
178{
179 d->m_metadata = data;
180}
181
182#include "moc_atticabasejob.cpp"
The baseclass for all job classes.
bool isAborted() const
Status messages from the server.
Definition metadata.h:29
void setHeaders(const QList< QNetworkReply::RawHeaderPair > &headers)
Sets the http headers read by headers()
Definition metadata.cpp:144
int statusCode() const
The status as integer.
Definition metadata.cpp:99
The Attica namespace,.
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
void setPassword(const QString &password)
void setUser(const QString &user)
const char * constData() const const
QString errorString() const const
QByteArray readAll()
void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
virtual void abort()=0
QVariant attribute(QNetworkRequest::Attribute code) const const
NetworkError error() const const
void errorOccurred(QNetworkReply::NetworkError code)
QNetworkAccessManager * manager() const const
QNetworkAccessManager::Operation operation() const const
const QList< RawHeaderPair > & rawHeaderPairs() const const
QNetworkRequest request() const const
QUrl url() const const
QVariant attribute(Attribute code, const QVariant &defaultValue) const const
void setUrl(const QUrl &url)
QUrl url() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
QString fromUtf8(QByteArrayView str)
bool isValid() const const
QUrl resolved(const QUrl &relative) const const
QString toString(FormattingOptions options) const const
int toInt(bool *ok) const const
QString toString() const const
QUrl toUrl() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:48 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.