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 <QDebug>
12 #include <QTimer>
13 #include <QNetworkReply>
14 #include <QAuthenticator>
15 
16 #include <attica_debug.h>
17 #include <atticautils.h>
18 #include "platformdependent.h"
19 
20 using namespace Attica;
21 
22 class BaseJob::Private
23 {
24 public:
25  Metadata m_metadata;
26  PlatformDependent *m_internals;
27  QNetworkReply *m_reply;
28  bool aborted{false};
29 
30  Private(PlatformDependent *internals)
31  : m_internals(internals), m_reply(nullptr)
32  {
33  }
34 
35  bool redirection(QUrl &newUrl) const
36  {
37  if (m_reply == nullptr ||
38  m_reply->error()
40  return false;
41  }
42 
43  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 = (
82  d->m_reply->error()
84 
85  // handle redirections automatically
86  QUrl newUrl;
87  if (d->redirection(newUrl)) {
88  //qCDebug(ATTICA) << "BaseJob::dataFinished" << newUrl;
89  QNetworkRequest request = d->m_reply->request();
90  QNetworkAccessManager::Operation operation = d->m_reply->operation();
91  if (newUrl.isValid() && operation == QNetworkAccessManager::GetOperation) {
92  d->m_reply->deleteLater();
93  // reissue same request with different Url
94  request.setUrl(newUrl);
95  d->m_reply = internals()->get(request);
96  connect(d->m_reply, &QNetworkReply::finished, this, &BaseJob::dataFinished);
97  return;
98  } else {
99  error = true;
100  }
101  }
102 
103  if (!error) {
104  QByteArray data = d->m_reply->readAll();
105  //qCDebug(ATTICA) << "XML Returned:\n" << data;
107  if (d->m_metadata.statusCode() >= 100 && d->m_metadata.statusCode() < 200) {
108  d->m_metadata.setError(Metadata::NoError);
109  } else {
110  d->m_metadata.setError(Metadata::OcsError);
111  }
112  } else {
113  d->m_metadata.setError(Metadata::NetworkError);
114  d->m_metadata.setStatusCode(d->m_reply->error());
115  d->m_metadata.setStatusString(d->m_reply->errorString());
116  }
117  Q_EMIT finished(this);
118 
119  d->m_reply->deleteLater();
120  deleteLater();
121 }
122 
123 void BaseJob::start()
124 {
125  QTimer::singleShot(0, this, &BaseJob::doWork);
126 }
127 
128 void BaseJob::doWork()
129 {
130  if (d->aborted) {
131  return;
132  }
133  d->m_reply = executeRequest();
134  qCDebug(ATTICA) << "executing" << Utils::toString(d->m_reply->operation()) << "request for" << d->m_reply->url();
135  connect(d->m_reply, &QNetworkReply::finished, this, &BaseJob::dataFinished);
136  connect(d->m_reply->manager(), &QNetworkAccessManager::authenticationRequired,
137  this, &BaseJob::authenticationRequired);
138 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
139  connect(d->m_reply, static_cast<void(QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error),
140 #else
141  connect(d->m_reply, &QNetworkReply::errorOccurred,
142 #endif
144  qCDebug(ATTICA) << "error found" << code;
145  });
146 }
147 
148 void BaseJob::authenticationRequired(QNetworkReply *reply, QAuthenticator *auth)
149 {
150  auth->setUser(reply->request().attribute((QNetworkRequest::Attribute) BaseJob::UserAttribute).toString());
151  auth->setPassword(reply->request().attribute((QNetworkRequest::Attribute) BaseJob::PasswordAttribute).toString());
152 }
153 
154 void BaseJob::abort()
155 {
156  d->aborted = true;
157  if (d->m_reply) {
158  d->m_reply->abort();
159  d->m_reply->deleteLater();
160  }
161  deleteLater();
162 }
163 
164 PlatformDependent *BaseJob::internals()
165 {
166  return d->m_internals;
167 }
168 
169 Metadata BaseJob::metadata() const
170 {
171  return d->m_metadata;
172 }
173 
174 void BaseJob::setMetadata(const Attica::Metadata &data) const
175 {
176  d->m_metadata = data;
177 }
178 
QUrl toUrl() const const
void setPassword(const QString &password)
void setUrl(const QUrl &url)
QNetworkRequest request() const const
void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
QString toString(QUrl::FormattingOptions options) const const
QString fromUtf8(const char *str, int size)
int toInt(bool *ok) const const
QVector< QVariant > parse(const QString &message, const QDate &externalIssueDate=QDate())
Status messages from the server.
Definition: metadata.h:25
const char * constData() const const
void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
QVariant attribute(QNetworkRequest::Attribute code, const QVariant &defaultValue) const const
void errorOccurred(QNetworkReply::NetworkError code)
QUrl url() const const
bool isValid() const const
QUrl resolved(const QUrl &relative) const const
QVariant attribute(QNetworkRequest::Attribute code) const const
QNetworkReply::NetworkError error() const const
void setUser(const QString &user)
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Jan 23 2021 03:59:44 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.