Attica

atticabasejob.cpp
1 /*
2  This file is part of KDE.
3 
4  SPDX-FileCopyrightText: 2008 Cornelius Schumacher <[email protected]>
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 
20 using namespace Attica;
21 
22 class Q_DECL_HIDDEN BaseJob::Private
23 {
24 public:
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 
65 BaseJob::BaseJob(PlatformDependent *internals)
66  : d(new Private(internals))
67 {
68 }
69 
70 BaseJob::~BaseJob()
71 {
72  delete d;
73 }
74 
75 void 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 {
107  QByteArray data = d->m_reply->readAll();
108  // qCDebug(ATTICA) << "XML Returned:\n" << data;
109  parse(QString::fromUtf8(data.constData()));
110  if (d->m_metadata.statusCode() >= 100 && d->m_metadata.statusCode() < 200) {
111  d->m_metadata.setError(Metadata::NoError);
112  } else {
113  d->m_metadata.setError(Metadata::OcsError);
114  }
115  }
116  Q_EMIT finished(this);
117 
118  d->m_reply->deleteLater();
119  deleteLater();
120 }
121 
122 void BaseJob::start()
123 {
124  if (!d->started) {
125  d->started = true;
126  QTimer::singleShot(0, this, &BaseJob::doWork);
127  }
128 }
129 
130 void BaseJob::doWork()
131 {
132  if (d->aborted) {
133  return;
134  }
135  d->m_reply = executeRequest();
136  qCDebug(ATTICA) << "executing" << Utils::toString(d->m_reply->operation()) << "request for" << d->m_reply->url();
137  connect(d->m_reply, &QNetworkReply::finished, this, &BaseJob::dataFinished);
138  connect(d->m_reply->manager(), &QNetworkAccessManager::authenticationRequired, this, &BaseJob::authenticationRequired);
140  qCDebug(ATTICA) << "error found" << code;
141  });
142 }
143 
144 void BaseJob::authenticationRequired(QNetworkReply *reply, QAuthenticator *auth)
145 {
146  auth->setUser(reply->request().attribute((QNetworkRequest::Attribute)BaseJob::UserAttribute).toString());
147  auth->setPassword(reply->request().attribute((QNetworkRequest::Attribute)BaseJob::PasswordAttribute).toString());
148 }
149 
150 void BaseJob::abort()
151 {
152  d->aborted = true;
153  if (d->m_reply) {
154  d->m_reply->abort();
155  d->m_reply->deleteLater();
156  }
157  deleteLater();
158 }
159 
160 bool BaseJob::isAborted() const
161 {
162  return d->aborted;
163 }
164 
165 PlatformDependent *BaseJob::internals()
166 {
167  return d->m_internals;
168 }
169 
170 Metadata BaseJob::metadata() const
171 {
172  return d->m_metadata;
173 }
174 
175 void BaseJob::setMetadata(const Attica::Metadata &data) const
176 {
177  d->m_metadata = data;
178 }
179 
180 #include "moc_atticabasejob.cpp"
void errorOccurred(QNetworkReply::NetworkError code)
QVariant attribute(QNetworkRequest::Attribute code, const QVariant &defaultValue) const const
QUrl url() const const
QUrl toUrl() const const
void setPassword(const QString &password)
QString fromUtf8(const char *str, int size)
Q_EMITQ_EMIT
void setUser(const QString &user)
bool isAborted() const
QNetworkReply::NetworkError error() const const
void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool isValid() const const
void deleteLater()
QString toString(QUrl::FormattingOptions options) const const
int toInt(bool *ok) const const
QNetworkRequest request() const const
QUrl resolved(const QUrl &relative) const const
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
QVariant attribute(QNetworkRequest::Attribute code) const const
const char * constData() const const
void setUrl(const QUrl &url)
The Attica namespace,.
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Dec 3 2023 04:08:16 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.