diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /utils/rbutilqt/base/httpget.cpp | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'utils/rbutilqt/base/httpget.cpp')
-rw-r--r-- | utils/rbutilqt/base/httpget.cpp | 256 |
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 | |||
27 | QString HttpGet::m_globalUserAgent; //< globally set user agent for requests | ||
28 | QDir HttpGet::m_globalCache; //< global cach path value for new objects | ||
29 | QNetworkProxy HttpGet::m_globalProxy; | ||
30 | |||
31 | HttpGet::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 | */ | ||
50 | void 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 | */ | ||
62 | void 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 | */ | ||
93 | QByteArray HttpGet::readAll() | ||
94 | { | ||
95 | return m_data; | ||
96 | } | ||
97 | |||
98 | |||
99 | /** @brief Set and enable Proxy to use. | ||
100 | * @param proxy Proxy URL. | ||
101 | */ | ||
102 | void 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 | */ | ||
117 | void 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 | */ | ||
132 | void HttpGet::setFile(QFile *file) | ||
133 | { | ||
134 | m_outputFile = file; | ||
135 | } | ||
136 | |||
137 | |||
138 | void HttpGet::abort() | ||
139 | { | ||
140 | if(m_reply) m_reply->abort(); | ||
141 | } | ||
142 | |||
143 | |||
144 | void 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 | |||
192 | void HttpGet::downloadProgress(qint64 received, qint64 total) | ||
193 | { | ||
194 | emit dataReadProgress((int)received, (int)total); | ||
195 | } | ||
196 | |||
197 | |||
198 | void 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 | |||
217 | void 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 | */ | ||
232 | void 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 | */ | ||
243 | QString HttpGet::errorString(void) | ||
244 | { | ||
245 | return m_lastErrorString; | ||
246 | } | ||
247 | |||
248 | |||
249 | /** @brief Return last HTTP response code. | ||
250 | * @return Response code. | ||
251 | */ | ||
252 | int HttpGet::httpResponse(void) | ||
253 | { | ||
254 | return m_lastStatusCode; | ||
255 | } | ||
256 | |||