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 "platformdependent_v3.h"
18#include <attica_debug.h>
19#include <atticautils.h>
20
21using namespace Attica;
22
23class Q_DECL_HIDDEN BaseJob::Private
24{
25public:
26 Metadata m_metadata;
27 PlatformDependent *m_internals;
29 bool aborted{false};
30 bool started = false;
31
32 Private(PlatformDependent *internals)
33 : m_internals(internals)
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();
49 QUrl redirectUrl(m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl());
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(std::make_unique<Private>(internals))
67{
68}
69
70BaseJob::~BaseJob() = default;
71
72void BaseJob::dataFinished()
73{
74 if (!d->m_reply) {
75 return;
76 }
77
78 bool error = d->m_reply->error() != QNetworkReply::NoError && d->m_reply->error() != QNetworkReply::OperationCanceledError;
79
80 // handle redirections automatically
81 QUrl newUrl;
82 if (d->redirection(newUrl)) {
83 // qCDebug(ATTICA) << "BaseJob::dataFinished" << newUrl;
84 QNetworkRequest request = d->m_reply->request();
85 QNetworkAccessManager::Operation operation = d->m_reply->operation();
86 if (newUrl.isValid() && operation == QNetworkAccessManager::GetOperation) {
87 d->m_reply->deleteLater();
88 // reissue same request with different Url
89 request.setUrl(newUrl);
90 d->m_reply = internals()->get(request);
91 connect(d->m_reply, &QNetworkReply::finished, this, &BaseJob::dataFinished);
92 return;
93 }
94 error = true;
95 }
96
97 if (error) {
98 d->m_metadata.setError(Metadata::NetworkError);
99 d->m_metadata.setStatusCode(d->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt());
100 d->m_metadata.setStatusString(d->m_reply->errorString());
101 d->m_metadata.setHeaders(d->m_reply->rawHeaderPairs());
102 } else if (d->m_reply->error() == QNetworkReply::OperationCanceledError) {
103 d->m_metadata.setError(Metadata::NoError);
104 } else {
105 QByteArray data = d->m_reply->readAll();
106 // qCDebug(ATTICA) << "XML Returned:\n" << data;
107 parse(QString::fromUtf8(data.constData()));
108 if (d->m_metadata.statusCode() >= 100 && d->m_metadata.statusCode() < 200) {
109 d->m_metadata.setError(Metadata::NoError);
110 } else {
111 d->m_metadata.setError(Metadata::OcsError);
112 }
113 }
114 Q_EMIT finished(this);
115
116 d->m_reply->deleteLater();
117 deleteLater();
118}
119
120void BaseJob::start()
121{
122 if (!d->started) {
123 d->started = true;
124 QTimer::singleShot(0, this, &BaseJob::doWork);
125 }
126}
127
128void BaseJob::doWork()
129{
130 if (d->aborted) {
131 return;
132 }
133
134 auto platformDependentV3 = dynamic_cast<Attica::PlatformDependentV3 *>(d->m_internals);
135 if (platformDependentV3 && !platformDependentV3->isReady()) {
136 connect(platformDependentV3, &Attica::PlatformDependentV3::readyChanged, this, &BaseJob::doWork);
137 return;
138 }
139
140 d->m_reply = executeRequest();
141 qCDebug(ATTICA) << "executing" << Utils::toString(d->m_reply->operation()) << "request for" << d->m_reply->url();
142 connect(d->m_reply, &QNetworkReply::finished, this, &BaseJob::dataFinished);
143 connect(d->m_reply->manager(), &QNetworkAccessManager::authenticationRequired, this, &BaseJob::authenticationRequired);
145 qCDebug(ATTICA) << "error found" << code;
146 });
147}
148
149void BaseJob::authenticationRequired(QNetworkReply *reply, QAuthenticator *auth)
150{
151 auth->setUser(reply->request().attribute((QNetworkRequest::Attribute)BaseJob::UserAttribute).toString());
152 auth->setPassword(reply->request().attribute((QNetworkRequest::Attribute)BaseJob::PasswordAttribute).toString());
153}
154
155void BaseJob::abort()
156{
157 d->aborted = true;
158 if (d->m_reply) {
159 d->m_reply->abort();
160 d->m_reply->deleteLater();
161 }
162 deleteLater();
163}
164
166{
167 return d->aborted;
168}
169
170PlatformDependent *BaseJob::internals()
171{
172 return d->m_internals;
173}
174
175Metadata BaseJob::metadata() const
176{
177 return d->m_metadata;
178}
179
180void BaseJob::setMetadata(const Attica::Metadata &data) const
181{
182 d->m_metadata = data;
183}
184
185#include "moc_atticabasejob.cpp"
The baseclass for all job classes.
bool isAborted() const
Status messages from the server.
Definition metadata.h:29
Platform integration plugin v3.
void readyChanged()
Emit this when the ready state changes.
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
void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
void errorOccurred(QNetworkReply::NetworkError code)
QNetworkRequest request() 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
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:54:33 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.