2018-08-10 05:51:27 +00:00
# include "autoupdatechecker.h"
# include <QNetworkReply>
# include <QJsonDocument>
# include <QJsonArray>
# include <QJsonObject>
AutoUpdateChecker : : AutoUpdateChecker ( QObject * parent ) :
QObject ( parent ) ,
m_Nam ( this )
{
// Never communicate over HTTP
m_Nam . setStrictTransportSecurityEnabled ( true ) ;
2018-12-04 07:29:49 +00:00
// Allow HTTP redirects
m_Nam . setRedirectPolicy ( QNetworkRequest : : NoLessSafeRedirectPolicy ) ;
2018-08-10 05:51:27 +00:00
connect ( & m_Nam , SIGNAL ( finished ( QNetworkReply * ) ) ,
this , SLOT ( handleUpdateCheckRequestFinished ( QNetworkReply * ) ) ) ;
QString currentVersion ( VERSION_STR ) ;
qDebug ( ) < < " Current Moonlight version: " < < currentVersion ;
parseStringToVersionQuad ( currentVersion , m_CurrentVersionQuad ) ;
// Should at least have a 1.0-style version number
Q_ASSERT ( m_CurrentVersionQuad . count ( ) > 1 ) ;
}
void AutoUpdateChecker : : start ( )
{
2020-04-04 00:03:12 +00:00
# if defined(Q_OS_WIN32) || defined(Q_OS_DARWIN) || defined(STEAM_LINK) || defined(APP_IMAGE) // Only run update checker on platforms without auto-update
2020-05-02 17:14:54 +00:00
# if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) && !defined(QT_NO_BEARERMANAGEMENT)
// HACK: Set network accessibility to work around QTBUG-80947.
// Even though it was fixed in 5.14.2, it still breaks for users attempting to
// directly connect their computers without a router using APIPA and in some cases
// using OpenVPN with IPv6 enabled. https://github.com/moonlight-stream/moonlight-qt/issues/375
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
2019-12-21 20:58:45 +00:00
m_Nam . setNetworkAccessible ( QNetworkAccessManager : : Accessible ) ;
2020-05-02 17:14:54 +00:00
QT_WARNING_POP
2019-12-21 21:54:09 +00:00
# endif
2019-12-21 20:58:45 +00:00
2018-08-10 05:51:27 +00:00
// We'll get a callback when this is finished
2018-12-04 05:48:49 +00:00
QUrl url ( " https://moonlight-stream.org/updates/qt.json " ) ;
2018-08-10 05:51:27 +00:00
m_Nam . get ( QNetworkRequest ( url ) ) ;
# endif
}
void AutoUpdateChecker : : parseStringToVersionQuad ( QString & string , QVector < int > & version )
{
QStringList list = string . split ( ' . ' ) ;
for ( const QString & component : list ) {
version . append ( component . toInt ( ) ) ;
}
}
2019-12-14 04:15:52 +00:00
QString AutoUpdateChecker : : getPlatform ( )
{
2020-04-04 00:03:12 +00:00
# if defined(STEAM_LINK)
2019-12-14 04:15:52 +00:00
return QStringLiteral ( " steamlink " ) ;
2020-04-04 00:03:12 +00:00
# elif defined(APP_IMAGE)
return QStringLiteral ( " appimage " ) ;
2019-12-14 04:15:52 +00:00
# else
return QSysInfo : : productType ( ) ;
# endif
}
2018-08-10 05:51:27 +00:00
void AutoUpdateChecker : : handleUpdateCheckRequestFinished ( QNetworkReply * reply )
{
Q_ASSERT ( reply - > isFinished ( ) ) ;
2020-03-24 01:30:56 +00:00
if ( reply - > error ( ) = = QNetworkReply : : NoError ) {
2018-08-10 05:51:27 +00:00
QTextStream stream ( reply ) ;
stream . setCodec ( " UTF-8 " ) ;
// Read all data and queue the reply for deletion
QString jsonString = stream . readAll ( ) ;
reply - > deleteLater ( ) ;
QJsonParseError error ;
QJsonDocument jsonDoc = QJsonDocument : : fromJson ( jsonString . toUtf8 ( ) , & error ) ;
if ( jsonDoc . isNull ( ) ) {
qWarning ( ) < < " Update manifest malformed: " < < error . errorString ( ) ;
return ;
}
QJsonArray array = jsonDoc . array ( ) ;
if ( array . isEmpty ( ) ) {
qWarning ( ) < < " Update manifest doesn't contain an array " ;
return ;
}
for ( QJsonValueRef updateEntry : array ) {
if ( updateEntry . isObject ( ) ) {
QJsonObject updateObj = updateEntry . toObject ( ) ;
if ( ! updateObj . contains ( " platform " ) | |
! updateObj . contains ( " arch " ) | |
! updateObj . contains ( " version " ) | |
! updateObj . contains ( " browser_url " ) ) {
qWarning ( ) < < " Update manifest entry missing vital field " ;
continue ;
}
if ( ! updateObj [ " platform " ] . isString ( ) | |
! updateObj [ " arch " ] . isString ( ) | |
! updateObj [ " version " ] . isString ( ) | |
! updateObj [ " browser_url " ] . isString ( ) ) {
qWarning ( ) < < " Update manifest entry has unexpected vital field type " ;
continue ;
}
if ( updateObj [ " arch " ] = = QSysInfo : : buildCpuArchitecture ( ) & &
2019-12-14 04:15:52 +00:00
updateObj [ " platform " ] = = getPlatform ( ) ) {
2018-08-10 05:51:27 +00:00
qDebug ( ) < < " Found update manifest match for current platform " ;
QString latestVersion = updateObj [ " version " ] . toString ( ) ;
qDebug ( ) < < " Latest version of Moonlight for this platform is: " < < latestVersion ;
QVector < int > latestVersionQuad ;
parseStringToVersionQuad ( latestVersion , latestVersionQuad ) ;
for ( int i = 0 ; ; i + + ) {
int latestVer = 0 ;
int currentVer = 0 ;
// Treat missing decimal places as 0
if ( i < latestVersionQuad . count ( ) ) {
latestVer = latestVersionQuad [ i ] ;
}
if ( i < m_CurrentVersionQuad . count ( ) ) {
currentVer = m_CurrentVersionQuad [ i ] ;
}
if ( i > = latestVersionQuad . count ( ) & & i > = m_CurrentVersionQuad . count ( ) ) {
break ;
}
if ( currentVer < latestVer ) {
qDebug ( ) < < " Update available " ;
2019-01-04 02:00:54 +00:00
emit onUpdateAvailable ( updateObj [ " version " ] . toString ( ) ,
updateObj [ " browser_url " ] . toString ( ) ) ;
2018-08-10 05:51:27 +00:00
return ;
}
else if ( currentVer > latestVer ) {
qDebug ( ) < < " Update manifest version lower than current version " ;
return ;
}
}
qDebug ( ) < < " Update manifest version equal to current version " ;
return ;
}
}
else {
qWarning ( ) < < " Update manifest contained unrecognized entry: " < < updateEntry . toString ( ) ;
}
}
qWarning ( ) < < " No entry in update manifest found for current platform: "
2019-12-14 04:15:52 +00:00
< < QSysInfo : : buildCpuArchitecture ( ) < < getPlatform ( ) ;
2018-08-10 05:51:27 +00:00
}
else {
2020-03-24 01:30:56 +00:00
qWarning ( ) < < " Update checking failed with error: " < < reply - > error ( ) ;
2018-08-10 05:51:27 +00:00
reply - > deleteLater ( ) ;
}
}