@@ -53,7 +53,6 @@ RemoteNetwork::RemoteNetwork() :
5353 reloadSettings ();
5454
5555 // Set up signals
56- connect (m_manager, &QNetworkAccessManager::finished, this , &RemoteNetwork::gotReply);
5756 connect (m_manager, &QNetworkAccessManager::encrypted, this , &RemoteNetwork::gotEncrypted);
5857 connect (m_manager, &QNetworkAccessManager::sslErrors, this , &RemoteNetwork::gotError);
5958}
@@ -161,35 +160,6 @@ void RemoteNetwork::gotEncrypted(QNetworkReply* reply)
161160
162161void RemoteNetwork::gotReply (QNetworkReply* reply)
163162{
164- // Check if request was successful
165- if (reply->error () != QNetworkReply::NoError)
166- {
167- // Do not show error message when operation was cancelled on purpose
168- if (reply->error () != QNetworkReply::OperationCanceledError)
169- {
170- QMessageBox::warning (nullptr , qApp->applicationName (),
171- reply->errorString () + " \n " + reply->readAll ());
172- }
173-
174- reply->deleteLater ();
175- return ;
176- }
177-
178- // Check for redirect
179- QString redirectUrl = reply->attribute (QNetworkRequest::RedirectionTargetAttribute).toString ();
180- if (!redirectUrl.isEmpty ())
181- {
182- // Avoid redirect loop
183- if (reply->url () == redirectUrl)
184- {
185- reply->deleteLater ();
186- return ;
187- }
188- fetch (redirectUrl, static_cast <RequestType>(reply->property (" type" ).toInt ()), reply->property (" certfile" ).toString (), reply->property (" userdata" ));
189- reply->deleteLater ();
190- return ;
191- }
192-
193163 // What type of data is this?
194164 RequestType type = static_cast <RequestType>(reply->property (" type" ).toInt ());
195165
@@ -222,56 +192,6 @@ void RemoteNetwork::gotReply(QNetworkReply* reply)
222192 reply);
223193 }
224194 break ;
225- case RequestTypeDirectory:
226- emit gotDirList (reply->readAll (), reply->property (" userdata" ));
227- break ;
228- case RequestTypeNewVersionCheck:
229- {
230- QString version = reply->readLine ().trimmed ();
231- QString url = reply->readLine ().trimmed ();
232- emit gotCurrentVersion (version, url);
233- break ;
234- }
235- case RequestTypeLicenceList:
236- {
237- // Read and check results
238- json obj = json::parse (reply->readAll (), nullptr , false );
239- if (obj.is_discarded () || !obj.is_object ())
240- break ;
241-
242- // Parse data and build ordered licence map: order -> (short name, long name)
243- std::map<int , std::pair<std::string, std::string>> licences;
244- for (auto it=obj.cbegin ();it!=obj.cend ();++it)
245- licences.insert ({it.value ()[" order" ], {it.key (), it.value ()[" full_name" ]}});
246-
247- // Convert the map into an ordered vector and send it to anyone who's interested
248- std::vector<std::pair<std::string, std::string>> licence_list;
249- std::transform (licences.begin (), licences.end (), std::back_inserter (licence_list), [](const std::pair<int , std::pair<std::string, std::string>>& it) {
250- return it.second ;
251- });
252- emit gotLicenceList (licence_list);
253- break ;
254- }
255- case RequestTypeBranchList:
256- {
257- // Read and check results
258- json obj = json::parse (reply->readAll (), nullptr , false );
259- if (obj.is_discarded () || !obj.is_object ())
260- break ;
261- json obj_branches = obj[" branches" ];
262-
263- // Parse data and assemble branch list
264- std::vector<std::string> branches;
265- for (auto it=obj_branches.cbegin ();it!=obj_branches.cend ();++it)
266- branches.push_back (it.key ());
267-
268- // Get default branch
269- std::string default_branch = (obj.contains (" default_branch" ) && !obj[" default_branch" ].empty ()) ? obj[" default_branch" ] : " master" ;
270-
271- // Send branch list to anyone who is interested
272- emit gotBranchList (branches, default_branch);
273- break ;
274- }
275195 case RequestTypePush:
276196 {
277197 // Read and check results
@@ -288,41 +208,6 @@ void RemoteNetwork::gotReply(QNetworkReply* reply)
288208 reply->property (" source_file" ).toString ());
289209 break ;
290210 }
291- case RequestTypeMetadata:
292- {
293- // Read and check results
294- json obj = json::parse (reply->readAll (), nullptr , false );
295- if (obj.is_discarded () || !obj.is_object ())
296- break ;
297-
298- // Extract and convert data
299- json obj_branches = obj[" branches" ];
300- json obj_commits = obj[" commits" ];
301- json obj_releases = obj[" releases" ];
302- json obj_tags = obj[" tags" ];
303- std::string default_branch = (obj.contains (" default_branch" ) && !obj[" default_branch" ].empty ()) ? obj[" default_branch" ] : " master" ;
304- std::vector<RemoteMetadataBranchInfo> branches;
305- for (auto it=obj_branches.cbegin ();it!=obj_branches.cend ();++it)
306- branches.emplace_back (it.key (), it.value ()[" commit" ], it.value ()[" description" ], it.value ()[" commit_count" ]);
307- std::vector<RemoteMetadataReleaseInfo> releases;
308- for (auto it=obj_releases.cbegin ();it!=obj_releases.cend ();++it)
309- {
310- releases.emplace_back (it.key (), it.value ()[" commit" ], it.value ()[" date" ],
311- it.value ()[" description" ], it.value ()[" email" ],
312- it.value ()[" name" ], it.value ()[" size" ]);
313- }
314- std::vector<RemoteMetadataReleaseInfo> tags;
315- for (auto it=obj_tags.cbegin ();it!=obj_tags.cend ();++it)
316- {
317- tags.emplace_back (it.key (), it.value ()[" commit" ], it.value ()[" date" ],
318- it.value ()[" description" ], it.value ()[" email" ],
319- it.value ()[" name" ], 0 );
320- }
321-
322- // Send data list to anyone who is interested
323- emit gotMetadata (branches, obj_commits.dump (), releases, tags, default_branch, obj[" web_page" ]);
324- break ;
325- }
326211 case RequestTypeDownload:
327212 {
328213 // It's a download
@@ -496,7 +381,8 @@ void RemoteNetwork::prepareProgressDialog(QNetworkReply* reply, bool upload, con
496381 connect (reply, &QNetworkReply::downloadProgress, this , &RemoteNetwork::updateProgress);
497382}
498383
499- void RemoteNetwork::fetch (const QUrl& url, RequestType type, const QString& clientCert, QVariant userdata)
384+ void RemoteNetwork::fetch (const QUrl& url, RequestType type, const QString& clientCert,
385+ std::function<void (QByteArray)> when_finished)
500386{
501387 // Check if network is accessible. If not, abort right here
502388 if (m_manager->networkAccessible () == QNetworkAccessManager::NotAccessible)
@@ -509,6 +395,9 @@ void RemoteNetwork::fetch(const QUrl& url, RequestType type, const QString& clie
509395 QNetworkRequest request;
510396 request.setUrl (url);
511397 request.setRawHeader (" User-Agent" , QString (" %1 %2" ).arg (qApp->organizationName (), APP_VERSION).toUtf8 ());
398+ #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
399+ request.setAttribute (QNetworkRequest::FollowRedirectsAttribute, true );
400+ #endif
512401
513402 // Set SSL configuration when trying to access a file via the HTTPS protocol.
514403 // Skip this step when no client certificate was specified. In this case the default HTTPS configuration is used.
@@ -527,7 +416,20 @@ void RemoteNetwork::fetch(const QUrl& url, RequestType type, const QString& clie
527416 QNetworkReply* reply = m_manager->get (request);
528417 reply->setProperty (" type" , type);
529418 reply->setProperty (" certfile" , clientCert);
530- reply->setProperty (" userdata" , userdata);
419+
420+ // Hook up custom handler when there is one and global handler otherwise
421+ if (when_finished)
422+ {
423+ connect (reply, &QNetworkReply::finished, reply, [this , when_finished, reply]() {
424+ if (handleReply (reply))
425+ when_finished (reply->readAll ());
426+ });
427+ } else {
428+ connect (reply, &QNetworkReply::finished, this , [this , reply]() {
429+ if (handleReply (reply))
430+ gotReply (reply);
431+ });
432+ }
531433
532434 // Initialise the progress dialog for this request, but only if this is a database file or a download.
533435 // Directory listing and similar are small enough to be loaded without progress dialog.
@@ -633,3 +535,22 @@ void RemoteNetwork::clearAccessCache(const QString& clientCert)
633535 m_manager->clearAccessCache ();
634536 }
635537}
538+
539+ bool RemoteNetwork::handleReply (QNetworkReply* reply)
540+ {
541+ // Check if request was successful
542+ if (reply->error () != QNetworkReply::NoError)
543+ {
544+ // Do not show error message when operation was cancelled on purpose
545+ if (reply->error () != QNetworkReply::OperationCanceledError)
546+ {
547+ QMessageBox::warning (nullptr , qApp->applicationName (),
548+ reply->errorString () + " \n " + reply->readAll ());
549+ }
550+
551+ reply->deleteLater ();
552+ return false ;
553+ }
554+
555+ return true ;
556+ }
0 commit comments