| 
									
										
										
										
											2017-04-27 20:24:53 +02:00
										 |  |  | // SPDX-License-Identifier: GPL-2.0
 | 
					
						
							| 
									
										
										
										
											2015-06-16 06:08:31 -07:00
										 |  |  | #include <QObject>
 | 
					
						
							|  |  |  | #include <QTimer>
 | 
					
						
							|  |  |  | #include <QNetworkAccessManager>
 | 
					
						
							|  |  |  | #include <QNetworkReply>
 | 
					
						
							|  |  |  | #include <QEventLoop>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "pref.h"
 | 
					
						
							|  |  |  | #include "helpers.h"
 | 
					
						
							| 
									
										
										
										
											2016-04-03 19:26:05 -05:00
										 |  |  | #include "git-access.h"
 | 
					
						
							| 
									
										
										
										
											2015-06-16 06:08:31 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "checkcloudconnection.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 15:25:03 -04:00
										 |  |  | CheckCloudConnection::CheckCloudConnection(QObject *parent) : | 
					
						
							|  |  |  | 	QObject(parent), | 
					
						
							|  |  |  | 	reply(0) | 
					
						
							| 
									
										
										
										
											2015-06-16 06:08:31 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define TEAPOT "/make-latte?number-of-shots=3"
 | 
					
						
							|  |  |  | #define HTTP_I_AM_A_TEAPOT 418
 | 
					
						
							|  |  |  | #define MILK "Linus does not like non-fat milk"
 | 
					
						
							|  |  |  | bool CheckCloudConnection::checkServer() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-03 19:26:05 -05:00
										 |  |  | 	if (verbose) | 
					
						
							|  |  |  | 		fprintf(stderr, "Checking cloud connection...\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 06:08:31 -07:00
										 |  |  | 	QTimer timer; | 
					
						
							|  |  |  | 	timer.setSingleShot(true); | 
					
						
							|  |  |  | 	QEventLoop loop; | 
					
						
							|  |  |  | 	QNetworkRequest request; | 
					
						
							|  |  |  | 	request.setRawHeader("Accept", "text/plain"); | 
					
						
							|  |  |  | 	request.setRawHeader("User-Agent", getUserAgent().toUtf8()); | 
					
						
							| 
									
										
										
										
											2015-11-18 17:57:13 -08:00
										 |  |  | 	request.setRawHeader("Client-Id", getUUID().toUtf8()); | 
					
						
							| 
									
										
										
										
											2015-06-16 06:08:31 -07:00
										 |  |  | 	request.setUrl(QString(prefs.cloud_base_url) + TEAPOT); | 
					
						
							|  |  |  | 	QNetworkAccessManager *mgr = new QNetworkAccessManager(); | 
					
						
							| 
									
										
										
										
											2015-09-23 09:55:11 -07:00
										 |  |  | 	reply = mgr->get(request); | 
					
						
							| 
									
										
										
										
											2015-12-01 15:34:00 -08:00
										 |  |  | 	connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit); | 
					
						
							|  |  |  | 	connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); | 
					
						
							|  |  |  | 	connect(reply, &QNetworkReply::sslErrors, this, &CheckCloudConnection::sslErrors); | 
					
						
							| 
									
										
										
										
											2016-07-23 12:54:30 +09:00
										 |  |  | 	for (int seconds = 1; seconds <= prefs.cloud_timeout; seconds++) { | 
					
						
							|  |  |  | 		timer.start(1000); // wait the given number of seconds (default 5)
 | 
					
						
							| 
									
										
										
										
											2016-04-03 19:26:05 -05:00
										 |  |  | 		loop.exec(); | 
					
						
							|  |  |  | 		if (timer.isActive()) { | 
					
						
							|  |  |  | 			// didn't time out, did we get the right response?
 | 
					
						
							|  |  |  | 			timer.stop(); | 
					
						
							|  |  |  | 			if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == HTTP_I_AM_A_TEAPOT && | 
					
						
							|  |  |  | 			    reply->readAll() == QByteArray(MILK)) { | 
					
						
							|  |  |  | 				reply->deleteLater(); | 
					
						
							|  |  |  | 				mgr->deleteLater(); | 
					
						
							|  |  |  | 				if (verbose > 1) | 
					
						
							|  |  |  | 					qWarning() << "Cloud storage: successfully checked connection to cloud server"; | 
					
						
							|  |  |  | 				return true; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-07-23 12:54:30 +09:00
										 |  |  | 		} else if (seconds < prefs.cloud_timeout) { | 
					
						
							| 
									
										
										
										
											2017-06-22 14:27:52 +02:00
										 |  |  | 			QString text = tr("Waiting for cloud connection (%n second(s) passed)", "", seconds); | 
					
						
							| 
									
										
										
										
											2017-06-17 23:22:37 -07:00
										 |  |  | 			git_storage_update_progress(qPrintable(text)); | 
					
						
							| 
									
										
										
										
											2016-04-03 19:26:05 -05:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			disconnect(reply, SIGNAL(finished()), &loop, SLOT(quit())); | 
					
						
							|  |  |  | 			reply->abort(); | 
					
						
							| 
									
										
										
										
											2015-06-16 06:08:31 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-17 23:50:22 -07:00
										 |  |  | 	git_storage_update_progress(qPrintable(tr("Cloud connection failed"))); | 
					
						
							| 
									
										
										
										
											2016-07-17 09:15:10 +09:00
										 |  |  | 	prefs.git_local_only = true; | 
					
						
							| 
									
										
										
										
											2015-09-23 09:55:11 -07:00
										 |  |  | 	if (verbose) | 
					
						
							|  |  |  | 		qDebug() << "connection test to cloud server failed" << | 
					
						
							|  |  |  | 			    reply->error() << reply->errorString() << | 
					
						
							|  |  |  | 			    reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() << | 
					
						
							|  |  |  | 			    reply->readAll(); | 
					
						
							| 
									
										
										
										
											2015-06-16 06:08:31 -07:00
										 |  |  | 	reply->deleteLater(); | 
					
						
							|  |  |  | 	mgr->deleteLater(); | 
					
						
							| 
									
										
										
										
											2015-09-20 10:11:09 -07:00
										 |  |  | 	if (verbose) | 
					
						
							|  |  |  | 		qWarning() << "Cloud storage: unable to connect to cloud server"; | 
					
						
							| 
									
										
										
										
											2015-06-16 06:08:31 -07:00
										 |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-23 09:55:11 -07:00
										 |  |  | void CheckCloudConnection::sslErrors(QList<QSslError> errorList) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (verbose) { | 
					
						
							|  |  |  | 		qDebug() << "Received error response trying to set up https connection with cloud storage backend:"; | 
					
						
							|  |  |  | 		Q_FOREACH (QSslError err, errorList) { | 
					
						
							|  |  |  | 			qDebug() << err.errorString(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	QSslConfiguration conf = reply->sslConfiguration(); | 
					
						
							|  |  |  | 	QSslCertificate cert = conf.peerCertificate(); | 
					
						
							|  |  |  | 	QByteArray hexDigest = cert.digest().toHex(); | 
					
						
							|  |  |  | 	if (reply->url().toString().contains(prefs.cloud_base_url) && | 
					
						
							|  |  |  | 	    hexDigest == "13ff44c62996cfa5cd69d6810675490e") { | 
					
						
							|  |  |  | 		if (verbose) | 
					
						
							|  |  |  | 			qDebug() << "Overriding SSL check as I recognize the certificate digest" << hexDigest; | 
					
						
							|  |  |  | 		reply->ignoreSslErrors(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if (verbose) | 
					
						
							|  |  |  | 			qDebug() << "got invalid SSL certificate with hex digest" << hexDigest; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 06:08:31 -07:00
										 |  |  | // helper to be used from C code
 | 
					
						
							|  |  |  | extern "C" bool canReachCloudServer() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-20 10:11:09 -07:00
										 |  |  | 	if (verbose) | 
					
						
							|  |  |  | 		qWarning() << "Cloud storage: checking connection to cloud server"; | 
					
						
							| 
									
										
										
										
											2017-12-05 23:22:47 +01:00
										 |  |  | 	return CheckCloudConnection().checkServer(); | 
					
						
							| 
									
										
										
										
											2015-06-16 06:08:31 -07:00
										 |  |  | } |