"Fossies" - the Fresh Open Source Software Archive 
Member "cb2bib-2.0.1/src/c2b/network.cpp" (12 Feb 2021, 13098 Bytes) of package /linux/privat/cb2bib-2.0.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "network.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.0.0_vs_2.0.1.
1 /***************************************************************************
2 * Copyright (C) 2004-2021 by Pere Constans
3 * constans@molspaces.com
4 * cb2Bib version 2.0.1. Licensed under the GNU GPL version 3.
5 * See the LICENSE file that comes with this distribution.
6 ***************************************************************************/
7 #include "network.h"
8
9 #include "cb2bib_utilities.h"
10 #include "settings.h"
11
12 #include <QNetworkCookie>
13 #include <QNetworkCookieJar>
14 #include <QNetworkProxy>
15 #include <QNetworkReply>
16 #include <QTimer>
17
18
19 network::network(QObject* parento) : QObject(parento), _max_redirections(15)
20 {
21 _is_fetching = false;
22 _fetcher = new QNetworkAccessManager(this);
23 connect(_fetcher, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), this,
24 SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
25 loadSettings();
26 connect(settings::instance(), SIGNAL(newSettings()), this, SLOT(loadSettings()));
27 // Set predefined cookies
28 QNetworkCookieJar* ncj = _fetcher->cookieJar();
29 QNetworkCookie nc("GSP", "ID=d093ce1ea042ad2b:IN=54afcd58e3b38df9:HIN=ff7e3a3ab3fbae0a+7e6cc990821af63:CF=4");
30 ncj->setCookiesFromUrl(QList<QNetworkCookie>() << nc, QUrl("https://scholar.google.com"));
31 }
32
33
34 /****************************************************************************
35
36 PUBLIC PART
37
38 *****************************************************************************/
39
40 void network::getFile(const QString& source, const QString& destination, const Action action, QObject* receiver,
41 const char* callback, const bool overwrite)
42 {
43 if (_is_fetching)
44 {
45 c2bUtils::warn(tr("network::getFile: Requesting network while still fetching previous request. Returned"));
46 return;
47 }
48 setup(source, destination);
49 disconnect(this, SIGNAL(requestFinished(bool)), 0, 0);
50 if (receiver)
51 connect(this, SIGNAL(requestFinished(bool)), receiver, callback);
52 if (overwrite)
53 if (QFileInfo::exists(destination))
54 QFile::remove(destination);
55 getFilePrivate(action);
56 }
57
58 void network::headFile(const QString& source, QObject* receiver, const char* callback)
59 {
60 if (_is_fetching)
61 {
62 c2bUtils::warn(tr("network::headFile: Requesting network while still fetching previous request. Returned"));
63 return;
64 }
65 setup(source);
66 disconnect(this, SIGNAL(requestFinished(bool)), 0, 0);
67 if (receiver)
68 connect(this, SIGNAL(requestFinished(bool)), receiver, callback);
69 headFilePrivate();
70 }
71
72 void network::cancelDownload()
73 {
74 if (_is_fetching)
75 _current_reply->abort();
76 }
77
78
79 /****************************************************************************
80
81 PRIVATE PART
82
83 *****************************************************************************/
84
85 void network::getFilePrivate(const Action action)
86 {
87 if (!checkDestination())
88 {
89 _emit_request_finished(false);
90 return;
91 }
92 if (_source_filename.startsWith("<<post>>")) // cb2Bib keyword to use post http method
93 {
94 _source_filename.remove(QRegExp("^<<post>>"));
95 _fetch_c2b(action, QNetworkAccessManager::PostOperation);
96 return;
97 }
98 if (FmClient)
99 if ((action == Copy && !FmClientCopyBin.isEmpty()) || (action == Move && !FmClientMoveBin.isEmpty()))
100 {
101 _fetch_client(action);
102 return;
103 }
104 _fetch_c2b(action);
105 }
106
107 void network::headFilePrivate()
108 {
109 const QUrl u(_source_filename, QUrl::TolerantMode);
110 if (u.scheme() == "file" || QFileInfo::exists(_source_filename))
111 {
112 // Local File
113 const QString fn(u.scheme() == "file" ? u.toLocalFile() : _source_filename);
114 const bool succeeded(QFileInfo::exists(fn));
115 if (!succeeded)
116 _request_error_string = tr("File does not exist.");
117 _emit_request_finished(succeeded);
118 }
119 else
120 {
121 // Network File
122 _head(u);
123 }
124 }
125
126 void network::_emit_request_finished(bool succeeded)
127 {
128 _request_succeeded = succeeded;
129 // Give some time to cleanup events and to return all network functions
130 // before passing the control to the callback routine
131 QTimer::singleShot(50, this, SLOT(_emit_request_finished()));
132 }
133
134 void network::_emit_request_finished()
135 {
136 _is_fetching = false;
137 // Assumed events are clean, all functions returned, then make the callback
138 emit requestFinished(_request_succeeded);
139 }
140
141 bool network::checkDestination()
142 {
143 // Checks whether or not writing to destination is safe
144 // Returns false if file exists
145 if (QFileInfo::exists(_destination_filename))
146 {
147 _request_error_string = tr("Destination file '%1' already exists.").arg(_destination_filename);
148 return false;
149 }
150 else
151 return true;
152 }
153
154 void network::loadSettings()
155 {
156 settings* s(settings::instance());
157 FmClient = s->value("cb2Bib/FmClient").toBool();
158 FmClientCopyBin = s->fileName("cb2Bib/FmClientCopyBin");
159 FmClientMoveBin = s->fileName("cb2Bib/FmClientMoveBin");
160 FmClientCopyArg = s->value("cb2Bib/FmClientCopyArg").toString();
161 FmClientMoveArg = s->value("cb2Bib/FmClientMoveArg").toString();
162 QNetworkProxy proxy;
163 if (s->value("cb2Bib/UseProxy").toBool())
164 {
165 const QString hn(s->value("cb2Bib/ProxyHostName", QString()).toString());
166 if (!hn.isEmpty())
167 {
168 if (s->value("cb2Bib/ProxyType").toInt() == 0)
169 proxy = QNetworkProxy::HttpProxy;
170 else
171 proxy = QNetworkProxy::Socks5Proxy;
172 proxy.setHostName(hn);
173 proxy.setPort(quint16(s->value("cb2Bib/ProxyPort").toInt()));
174 }
175 }
176 _fetcher->setProxy(proxy);
177 }
178
179
180 /****************************************************************************
181
182 PRIVATE PART: FILEMANAGER CLIENT
183
184 *****************************************************************************/
185
186 void network::_fetch_client(const Action action)
187 {
188 // Getting NetworkFile through kfmclient
189 Action act(action);
190 // Only move local files
191 QUrl u(_source_filename);
192 if (!(u.scheme() == "file" || QFileInfo::exists(_source_filename)))
193 if (action == Move)
194 act = Copy; // Copy network files
195
196 QStringList arglist;
197 QString fmclient_bin;
198 if (act == Copy)
199 {
200 fmclient_bin = FmClientCopyBin;
201 arglist = FmClientCopyArg.split(' ', QString::SkipEmptyParts);
202 }
203 else if (act == Move)
204 {
205 fmclient_bin = FmClientMoveBin;
206 arglist = FmClientMoveArg.split(' ', QString::SkipEmptyParts);
207 }
208 arglist.append(_source_filename);
209 arglist.append(_destination_filename);
210 _fetcher_client = new QProcess(this);
211 connect(_fetcher_client, SIGNAL(finished(int,QProcess::ExitStatus)), this,
212 SLOT(_client_finished(int,QProcess::ExitStatus)));
213 _fetcher_client->start(fmclient_bin, arglist);
214 if (!_fetcher_client->waitForStarted())
215 {
216 delete _fetcher_client;
217 _request_error_string = tr("FM Client '%1' could not be launched.").arg(fmclient_bin);
218 _emit_request_finished(false);
219 }
220 }
221
222 void network::_client_finished(int exitCode, QProcess::ExitStatus exitStatus)
223 {
224 bool succeeded(false);
225 if (exitStatus == QProcess::CrashExit)
226 _request_error_string = tr("FM Client crashed.");
227 else
228 {
229 if (QFileInfo::exists(_destination_filename))
230 succeeded = true;
231 else
232 _request_error_string =
233 tr("File '%1' has not been written. Exit code '%2'.").arg(_source_filename).arg(exitCode);
234 }
235 delete _fetcher_client;
236 _emit_request_finished(succeeded);
237 }
238
239
240 /****************************************************************************
241
242 PRIVATE PART: C2B FETCHER
243
244 *****************************************************************************/
245
246 void network::_head(const QUrl& url)
247 {
248 QNetworkRequest request;
249 request.setUrl(url);
250 request.setRawHeader(
251 "User-Agent",
252 QString("cb2Bib/" + C2B_VERSION +
253 " (https://www.molspaces.com/cb2bib/; mailto:cb2bib@molspaces.com; Bibliographic Browser Tool)")
254 .toLatin1());
255 _current_reply = _fetcher->head(request);
256 connect(_current_reply, SIGNAL(finished()), SLOT(_head_finished()));
257 }
258
259 void network::_head_finished()
260 {
261 if (_redirection_count++ < _max_redirections)
262 {
263 const QUrl redirection(_current_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl());
264 if (redirection.isValid())
265 {
266 const QUrl ru(_current_reply->url().resolved(redirection));
267 _source_filename = ru.toString();
268 _current_reply->deleteLater();
269 _head(ru);
270 return;
271 }
272 }
273 const bool succeeded(_current_reply->error() == QNetworkReply::NoError);
274 if (succeeded)
275 _file_mimetype_string = _current_reply->header(QNetworkRequest::ContentTypeHeader).toString();
276 else
277 _request_error_string = _current_reply->errorString() + '.';
278 _current_reply->deleteLater();
279 _emit_request_finished(succeeded);
280 }
281
282 void network::_fetch_c2b(const Action action, const QNetworkAccessManager::Operation operation)
283 {
284 _fetch_operation = operation;
285 _fetch_url_query.clear();
286 QString url_str;
287 if (_fetch_operation == QNetworkAccessManager::PostOperation)
288 {
289 const int qmark(_source_filename.indexOf('?'));
290 url_str = _source_filename.mid(0, qmark);
291 if (qmark > -1)
292 {
293 url_str += '/';
294 _fetch_url_query = _source_filename.mid(qmark + 1).toUtf8();
295 }
296 }
297 else
298 url_str = _source_filename;
299
300 QUrl u(url_str, QUrl::TolerantMode);
301 if (u.scheme() == "file" || QFileInfo::exists(_source_filename))
302 {
303 // Local File
304 QFile source(u.scheme() == "file" ? u.toLocalFile() : _source_filename);
305 bool succeeded(false);
306 if (action == Copy)
307 succeeded = source.copy(_destination_filename);
308 else if (action == Move)
309 succeeded = source.rename(_destination_filename);
310 if (!succeeded)
311 _request_error_string = source.errorString();
312 _emit_request_finished(succeeded);
313 }
314 else
315 {
316 // Network File
317 _fetch(u);
318 }
319 }
320
321 void network::_fetch(const QUrl& url)
322 {
323 _destination_file.setFileName(_destination_filename);
324 if (!_destination_file.open(QIODevice::WriteOnly))
325 {
326 _request_error_string =
327 tr("File '%1' cannot be written. %2").arg(_destination_filename, _destination_file.errorString());
328 _emit_request_finished(false);
329 return;
330 }
331 QNetworkRequest request;
332 request.setUrl(url);
333 request.setRawHeader(
334 "User-Agent",
335 QString("cb2Bib/" + C2B_VERSION +
336 " (https://www.molspaces.com/cb2bib/; mailto:cb2bib@molspaces.com; Bibliographic Browser Tool)")
337 .toLatin1());
338 if (_fetch_operation == QNetworkAccessManager::PostOperation)
339 {
340 request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
341 _current_reply = _fetcher->post(request, _fetch_url_query);
342 }
343 else
344 _current_reply = _fetcher->get(request);
345 connect(_current_reply, SIGNAL(readyRead()), this, SLOT(_fetch_ready_read()));
346 connect(_current_reply, SIGNAL(finished()), SLOT(_fetch_finished()));
347 connect(_current_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(logError()));
348 connect(_current_reply, SIGNAL(downloadProgress(qint64,qint64)), this, SIGNAL(downloadProgress(qint64,qint64)));
349 }
350
351 void network::_fetch_finished()
352 {
353 _destination_file.close();
354 if (_current_reply->error() == QNetworkReply::OperationCanceledError)
355 _destination_file.remove(); // Delete file
356 else if (_redirection_count++ < _max_redirections)
357 {
358 const QUrl redirection(_current_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl());
359 if (redirection.isValid())
360 {
361 const QUrl ru(_current_reply->url().resolved(redirection));
362 _source_filename = ru.toString();
363 const int status(_current_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt());
364 if ((status >= 301 && status <= 303) || status == 307)
365 _fetch_operation = QNetworkAccessManager::GetOperation;
366 _current_reply->deleteLater();
367 _fetch(ru);
368 return;
369 }
370 }
371 const bool succeeded(_current_reply->error() == QNetworkReply::NoError);
372 if (succeeded)
373 _file_mimetype_string = _current_reply->header(QNetworkRequest::ContentTypeHeader).toString();
374 else
375 _request_error_string = _current_reply->errorString() + '.';
376 _current_reply->deleteLater();
377 _emit_request_finished(succeeded);
378 }
379
380 void network::_fetch_ready_read()
381 {
382 _destination_file.write(_current_reply->readAll());
383 }
384
385 void network::logError()
386 {
387 c2bUtils::warn(tr("network::QNetworkReply log: %1").arg(_current_reply->errorString()));
388 }