summaryrefslogtreecommitdiff
path: root/utils/rbutilqt/base/httpget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rbutilqt/base/httpget.cpp')
-rw-r--r--utils/rbutilqt/base/httpget.cpp256
1 files changed, 256 insertions, 0 deletions
diff --git a/utils/rbutilqt/base/httpget.cpp b/utils/rbutilqt/base/httpget.cpp
new file mode 100644
index 0000000000..2df9501fd6
--- /dev/null
+++ b/utils/rbutilqt/base/httpget.cpp
@@ -0,0 +1,256 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2013 by Dominik Riebeling
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18
19#include <QtNetwork>
20
21#include <QNetworkAccessManager>
22#include <QNetworkRequest>
23
24#include "httpget.h"
25#include "Logger.h"
26
27QString HttpGet::m_globalUserAgent; //< globally set user agent for requests
28QDir HttpGet::m_globalCache; //< global cach path value for new objects
29QNetworkProxy HttpGet::m_globalProxy;
30
31HttpGet::HttpGet(QObject *parent)
32 : QObject(parent),
33 m_mgr(this),
34 m_reply(nullptr),
35 m_cache(nullptr),
36 m_cachedir(m_globalCache),
37 m_outputFile(nullptr),
38 m_proxy(QNetworkProxy::NoProxy)
39{
40 setCache(true);
41 connect(&m_mgr, &QNetworkAccessManager::finished, this,
42 static_cast<void (HttpGet::*)(QNetworkReply*)>(&HttpGet::requestFinished));
43 m_lastServerTimestamp = QDateTime();
44}
45
46
47/** @brief set cache path
48 * @param d new directory to use as cache path
49 */
50void HttpGet::setCache(const QDir& d)
51{
52 if(m_cache && m_cachedir == d.absolutePath())
53 return;
54 m_cachedir.setPath(d.absolutePath());
55 setCache(true);
56}
57
58
59/** @brief enable / disable cache useage
60 * @param c set cache usage
61 */
62void HttpGet::setCache(bool c)
63{
64 // don't change cache if it's already (un)set.
65 if(c && m_cache) return;
66 if(!c && !m_cache) return;
67 // don't delete the old cache directly, it might still be in use. Just
68 // instruct it to delete itself later.
69 if(m_cache) m_cache->deleteLater();
70 m_cache = nullptr;
71
72 QString path = m_cachedir.absolutePath();
73
74 if(!c || m_cachedir.absolutePath().isEmpty()) {
75 LOG_INFO() << "disabling download cache";
76 }
77 else {
78 // append the cache path to make it unique in case the path points to
79 // the system temporary path. In that case using it directly might
80 // cause problems. Extra path also used in configure dialog.
81 path += "/rbutil-cache";
82 LOG_INFO() << "setting cache folder to" << path;
83 m_cache = new QNetworkDiskCache(this);
84 m_cache->setCacheDirectory(path);
85 }
86 m_mgr.setCache(m_cache);
87}
88
89
90/** @brief read all downloaded data into a buffer
91 * @return data
92 */
93QByteArray HttpGet::readAll()
94{
95 return m_data;
96}
97
98
99/** @brief Set and enable Proxy to use.
100 * @param proxy Proxy URL.
101 */
102void HttpGet::setProxy(const QUrl &proxy)
103{
104 LOG_INFO() << "Proxy set to" << proxy;
105 m_proxy.setType(QNetworkProxy::HttpProxy);
106 m_proxy.setHostName(proxy.host());
107 m_proxy.setPort(proxy.port());
108 m_proxy.setUser(proxy.userName());
109 m_proxy.setPassword(proxy.password());
110 m_mgr.setProxy(m_proxy);
111}
112
113
114/** @brief Enable or disable use of previously set proxy.
115 * @param enable Enable proxy.
116 */
117void HttpGet::setProxy(bool enable)
118{
119 if(enable) m_mgr.setProxy(m_proxy);
120 else m_mgr.setProxy(QNetworkProxy::NoProxy);
121}
122
123
124/** @brief Set output file.
125 *
126 * Set filename for storing the downloaded file to. If no file is set the
127 * downloaded file will not be stored to disk but kept in memory. The result
128 * can then be retrieved using readAll().
129 *
130 * @param file Output file.
131 */
132void HttpGet::setFile(QFile *file)
133{
134 m_outputFile = file;
135}
136
137
138void HttpGet::abort()
139{
140 if(m_reply) m_reply->abort();
141}
142
143
144void HttpGet::requestFinished(QNetworkReply* reply)
145{
146 m_lastStatusCode
147 = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
148 LOG_INFO() << "Request finished, status code:" << m_lastStatusCode;
149 m_lastServerTimestamp
150 = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toLocalTime();
151 LOG_INFO() << "Data from cache:"
152 << reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool();
153 m_lastRequestCached =
154 reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool();
155 if(reply->attribute(QNetworkRequest::RedirectionTargetAttribute).isValid()) {
156 // handle relative URLs using QUrl::resolved()
157 QUrl org = reply->request().url();
158 QUrl url = QUrl(org).resolved(
159 reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl());
160 // reconstruct query
161#if QT_VERSION < 0x050000
162 QList<QPair<QByteArray, QByteArray> > qitms = org.encodedQueryItems();
163 for(int i = 0; i < qitms.size(); ++i)
164 url.addEncodedQueryItem(qitms.at(i).first, qitms.at(i).second);
165#else
166 url.setQuery(org.query());
167#endif
168 LOG_INFO() << "Redirected to" << url;
169 startRequest(url);
170 return;
171 }
172 else if(m_lastStatusCode == 200 ||
173 (reply->url().scheme() == "file" && reply->error() == 0)) {
174 // callers might not be aware if the request is file:// so fake 200.
175 m_lastStatusCode = 200;
176 m_data = reply->readAll();
177 if(m_outputFile && m_outputFile->open(QIODevice::WriteOnly)) {
178 m_outputFile->write(m_data);
179 m_outputFile->close();
180 }
181 emit done(false);
182 }
183 else {
184 m_data.clear();
185 emit done(true);
186 }
187 reply->deleteLater();
188 m_reply = nullptr;
189}
190
191
192void HttpGet::downloadProgress(qint64 received, qint64 total)
193{
194 emit dataReadProgress((int)received, (int)total);
195}
196
197
198void HttpGet::startRequest(QUrl url)
199{
200 LOG_INFO() << "Request started";
201 QNetworkRequest req(url);
202 if(!m_globalUserAgent.isEmpty())
203 req.setRawHeader("User-Agent", m_globalUserAgent.toLatin1());
204
205 m_reply = m_mgr.get(req);
206#if QT_VERSION < 0x050f00
207 connect(m_reply,
208 static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error),
209 this, &HttpGet::networkError);
210#else
211 connect(m_reply, &QNetworkReply::errorOccurred, this, &HttpGet::networkError);
212#endif
213 connect(m_reply, &QNetworkReply::downloadProgress, this, &HttpGet::downloadProgress);
214}
215
216
217void HttpGet::networkError(QNetworkReply::NetworkError error)
218{
219 LOG_ERROR() << "NetworkError occured:" << error << m_reply->errorString();
220 m_lastErrorString = m_reply->errorString();
221}
222
223
224/** @brief Retrieve the file pointed to by url.
225 *
226 * Note: This also handles file:// URLs. Be aware that QUrl requires file://
227 * URLs to be absolute, i.e. file://filename.txt doesn't work. Use
228 * QDir::absoluteFilePath() to convert to an absolute path first.
229 *
230 * @param url URL to download.
231 */
232void HttpGet::getFile(const QUrl &url)
233{
234 LOG_INFO() << "Get URI" << url.toString();
235 m_data.clear();
236 startRequest(url);
237}
238
239
240/** @brief Retrieve string representation for most recent error.
241 * @return Error string.
242 */
243QString HttpGet::errorString(void)
244{
245 return m_lastErrorString;
246}
247
248
249/** @brief Return last HTTP response code.
250 * @return Response code.
251 */
252int HttpGet::httpResponse(void)
253{
254 return m_lastStatusCode;
255}
256