2013-11-22 17:01:13 +01:00
///////////////////////////////////////////////////////////////////////////////
// Simple x264 Launcher
2016-01-01 23:59:55 +01:00
// Copyright (C) 2004-2016 LoRd_MuldeR <MuldeR2@GMX.de>
2013-11-22 17:01:13 +01:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// http://www.gnu.org/licenses/gpl-2.0.txt
///////////////////////////////////////////////////////////////////////////////
# include "win_updater.h"
2015-02-01 16:33:31 +01:00
# include "UIC_win_updater.h"
2013-11-22 17:01:13 +01:00
2015-02-01 21:05:17 +01:00
//Internal
2013-11-22 17:01:13 +01:00
# include "global.h"
2014-02-12 19:34:14 +01:00
# include "model_sysinfo.h"
2015-02-01 21:05:17 +01:00
//MUtils
# include <MUtils/UpdateChecker.h>
# include <MUtils/Hash_Blake2.h>
2015-02-02 22:11:06 +01:00
# include <MUtils/GUI.h>
# include <MUtils/OSSupport.h>
# include <MUtils/Exception.h>
2013-11-23 15:20:07 +01:00
2015-02-02 22:11:06 +01:00
//Qt
2013-11-23 15:20:07 +01:00
# include <QMovie>
# include <QCloseEvent>
# include <QTimer>
2013-11-29 18:10:11 +01:00
# include <QMessageBox>
2013-12-11 15:50:26 +01:00
# include <QDesktopServices>
# include <QUrl>
# include <QProcess>
# include <QFileInfo>
# include <QDir>
# include <QMap>
2013-11-23 15:20:07 +01:00
///////////////////////////////////////////////////////////////////////////////
2014-04-21 16:39:54 +02:00
const UpdaterDialog : : binary_t UpdaterDialog : : BINARIES [ ] =
{
{ " wget.exe " , " 7b522345239bcb95b5b0f7f50a883ba5957894a1feb769763e38ed789a8a0f63fead0155f54b9ffd0f1cdc5dfd855d207a6e7a8e4fd192589a8838ce646c504e " , 1 } ,
2016-04-23 15:09:13 +02:00
{ " netc.exe " , " c199ea12d761fa3191006da250f8f600ad426265fdf4a43e551cdf04a451a105692efd3ef82ac621c0799394aa21ac65bfbb4bab90c3fbb1f557e93f490fcb75 " , 1 } ,
2015-05-14 11:38:42 +02:00
{ " gpgv.exe " , " 18c5456cbb9ebf5cb9012a939b199d9eaa71c92a39f574f1e032babad0bbd9e72a064af96ca9d3d01f2892b064ec239fd61f27bac2eb9a64f7b2ece7beea3158 " , 1 } ,
2015-10-12 20:31:24 +02:00
{ " gpgv.gpg " , " 745c7a9c040196d9d322b1580e0046ff26ec13238cfd04325ceb3d4c8948294c593c027f895dc8ec427295175003e75d34f083019b706b0f4f06f81cce8df47d " , 0 } ,
{ " wupd.exe " , " 7eb8338efe0ddf973ee9fda5e5bfa4728876f2fcff2b3add30cb8c439d3d59a5de1a0636176c34be0b0da1a764363d0cfec014679749dc504999aa184f35dfd5 " , 1 } ,
2014-04-21 16:39:54 +02:00
{ NULL , NULL , 0 }
} ;
2013-11-23 15:20:07 +01:00
# define UPDATE_TEXT(N, TEXT) ui->label_phase##N->setText((TEXT))
# define UPDATE_ICON(N, ICON) ui->icon_phase##N->setPixmap(QIcon(": / buttons / " ICON ".png").pixmap(16, 16))
# define SHOW_ANIMATION(FLAG) do \
{ \
2013-12-16 22:58:21 +01:00
ui - > frameAnimation - > setVisible ( ( FLAG ) ) ; \
2013-11-23 15:20:07 +01:00
ui - > labelInfo - > setVisible ( ! ( FLAG ) ) ; \
ui - > labelUrl - > setVisible ( ! ( FLAG ) ) ; \
2013-12-16 22:58:21 +01:00
ui - > labelBuildNo - > setVisible ( ! ( FLAG ) ) ; \
2013-12-13 15:25:36 +01:00
if ( ( FLAG ) ) m_animator - > start ( ) ; else m_animator - > stop ( ) ; \
2013-11-23 15:20:07 +01:00
} \
while ( 0 )
2013-11-22 17:01:13 +01:00
///////////////////////////////////////////////////////////////////////////////
// Constructor & Destructor
///////////////////////////////////////////////////////////////////////////////
2014-04-20 19:40:59 +02:00
UpdaterDialog : : UpdaterDialog ( QWidget * parent , const SysinfoModel * sysinfo , const char * const updateUrl )
2013-11-22 17:01:13 +01:00
:
QDialog ( parent ) ,
2013-11-23 15:20:07 +01:00
ui ( new Ui : : UpdaterDialog ( ) ) ,
2014-02-12 19:34:14 +01:00
m_sysinfo ( sysinfo ) ,
2014-04-20 19:40:59 +02:00
m_updateUrl ( updateUrl ) ,
2015-02-01 21:05:17 +01:00
m_status ( MUtils : : UpdateChecker : : UpdateStatus_NotStartedYet ) ,
2013-12-09 22:19:32 +01:00
m_thread ( NULL ) ,
2013-12-13 15:25:36 +01:00
m_updaterProcess ( NULL ) ,
2013-12-14 22:30:19 +01:00
m_success ( false ) ,
2013-11-23 15:20:07 +01:00
m_firstShow ( true )
2013-11-22 17:01:13 +01:00
{
//Init the dialog, from the .ui file
ui - > setupUi ( this ) ;
setWindowFlags ( windowFlags ( ) & ( ~ Qt : : WindowContextHelpButtonHint ) ) ;
//Fix size
2013-11-23 15:20:07 +01:00
setFixedSize ( size ( ) ) ;
2013-12-11 15:50:26 +01:00
//Enable buttons
connect ( ui - > buttonCancel , SIGNAL ( clicked ( ) ) , this , SLOT ( close ( ) ) ) ;
connect ( ui - > buttonDownload , SIGNAL ( clicked ( ) ) , this , SLOT ( installUpdate ( ) ) ) ;
connect ( ui - > buttonRetry , SIGNAL ( clicked ( ) ) , this , SLOT ( checkForUpdates ( ) ) ) ;
//Enable info label
connect ( ui - > labelUrl , SIGNAL ( linkActivated ( QString ) ) , this , SLOT ( openUrl ( QString ) ) ) ;
2013-11-23 15:20:07 +01:00
//Init animation
2015-02-01 21:05:17 +01:00
m_animator . reset ( new QMovie ( " :/images/loading.gif " ) ) ;
ui - > labelLoadingCenter - > setMovie ( m_animator . data ( ) ) ;
2013-11-23 15:20:07 +01:00
//Init buttons
ui - > buttonCancel - > setEnabled ( false ) ;
ui - > buttonRetry - > hide ( ) ;
ui - > buttonDownload - > hide ( ) ;
2013-12-16 22:58:21 +01:00
//Start animation
SHOW_ANIMATION ( true ) ;
2013-11-22 17:01:13 +01:00
}
UpdaterDialog : : ~ UpdaterDialog ( void )
{
2015-02-01 21:05:17 +01:00
if ( ! m_thread . isNull ( ) )
2013-12-09 22:19:32 +01:00
{
2015-02-01 21:05:17 +01:00
if ( ! m_thread - > wait ( 5000 ) )
2013-12-09 22:19:32 +01:00
{
m_thread - > terminate ( ) ;
m_thread - > wait ( ) ;
}
}
2015-02-01 21:05:17 +01:00
cleanFiles ( ) ;
2013-11-22 17:01:13 +01:00
delete ui ;
}
///////////////////////////////////////////////////////////////////////////////
// Public Functions
///////////////////////////////////////////////////////////////////////////////
2013-11-29 18:10:11 +01:00
/*None yet*/
2013-11-22 17:01:13 +01:00
///////////////////////////////////////////////////////////////////////////////
// Events
///////////////////////////////////////////////////////////////////////////////
2013-12-13 15:25:36 +01:00
bool UpdaterDialog : : event ( QEvent * e )
{
if ( ( e - > type ( ) = = QEvent : : ActivationChange ) & & ( m_updaterProcess ! = NULL ) )
{
2015-02-02 22:11:06 +01:00
MUtils : : GUI : : bring_to_front ( m_updaterProcess ) ;
2013-12-13 15:25:36 +01:00
}
return QDialog : : event ( e ) ;
}
2013-11-23 15:20:07 +01:00
void UpdaterDialog : : showEvent ( QShowEvent * event )
{
if ( m_firstShow )
{
m_firstShow = false ;
2013-12-14 22:30:19 +01:00
QTimer : : singleShot ( 16 , this , SLOT ( initUpdate ( ) ) ) ;
2013-11-23 15:20:07 +01:00
}
}
void UpdaterDialog : : closeEvent ( QCloseEvent * e )
{
if ( ! ui - > buttonCancel - > isEnabled ( ) )
{
e - > ignore ( ) ;
}
}
2013-11-22 17:01:13 +01:00
2013-12-11 15:50:26 +01:00
void UpdaterDialog : : keyPressEvent ( QKeyEvent * event )
{
if ( event - > key ( ) = = Qt : : Key_F11 )
{
2015-02-02 22:11:06 +01:00
QFile logFile ( QString ( " %1/%2.log " ) . arg ( MUtils : : temp_folder ( ) , MUtils : : rand_str ( ) ) ) ;
2013-12-11 15:50:26 +01:00
if ( logFile . open ( QIODevice : : WriteOnly | QIODevice : : Truncate ) )
{
logFile . write ( " \xEF \xBB \xBF " ) ;
for ( QStringList : : ConstIterator iter = m_logFile . constBegin ( ) ; iter ! = m_logFile . constEnd ( ) ; iter + + )
{
logFile . write ( iter - > toUtf8 ( ) ) ;
logFile . write ( " \r \n " ) ;
}
logFile . close ( ) ;
QDesktopServices : : openUrl ( QUrl : : fromLocalFile ( logFile . fileName ( ) ) ) ;
}
}
}
2013-11-22 17:01:13 +01:00
///////////////////////////////////////////////////////////////////////////////
// Slots
///////////////////////////////////////////////////////////////////////////////
2013-11-23 15:20:07 +01:00
void UpdaterDialog : : initUpdate ( void )
{
2015-02-01 21:05:17 +01:00
//Clean up files from previous attempt
if ( ! m_binaries . isEmpty ( ) )
{
cleanFiles ( ) ;
}
2013-12-09 20:42:02 +01:00
//Check binary files
2016-04-23 15:09:13 +02:00
if ( ! checkBinaries ( ) )
2013-12-09 20:42:02 +01:00
{
ui - > buttonCancel - > setEnabled ( true ) ;
2014-04-20 19:40:59 +02:00
const QString message = QString ( " %1<br><br><nobr><a href= \" %2 \" >%3</a></nobr><br> " ) . arg ( tr ( " At least one file required by the web-update tool is missing or corrupted.<br>Please re-install this application and then try again! " ) , QString : : fromLatin1 ( m_updateUrl ) , QString : : fromLatin1 ( m_updateUrl ) . replace ( " - " , " − " ) ) ;
if ( QMessageBox : : critical ( this , tr ( " File Error " ) , message , tr ( " Download Latest Version " ) , tr ( " Discard " ) ) = = 0 )
{
QDesktopServices : : openUrl ( QUrl ( QString : : fromLatin1 ( m_updateUrl ) ) ) ;
}
2013-12-16 22:58:21 +01:00
close ( ) ; return ;
}
//Make sure user does have admin access
2015-02-02 22:11:06 +01:00
if ( ! MUtils : : OS : : user_is_admin ( ) )
2013-12-16 22:58:21 +01:00
{
qWarning ( " User is not in the \" admin \" group, cannot update! " ) ;
QString message ;
message + = QString ( " <nobr>%1</nobr><br> " ) . arg ( tr ( " Sorry, but only users in the \" Administrators \" group can install updates. " ) ) ;
message + = QString ( " <nobr>%1</nobr> " ) . arg ( tr ( " Please start application from an administrator account and try again! " ) ) ;
if ( QMessageBox : : critical ( this , this - > windowTitle ( ) , message , tr ( " Discard " ) , tr ( " Ignore " ) ) ! = 1 )
{
ui - > buttonCancel - > setEnabled ( true ) ;
close ( ) ; return ;
}
2013-12-09 20:42:02 +01:00
}
2013-12-09 22:19:32 +01:00
//Create and setup thread
if ( ! m_thread )
{
2016-04-23 15:09:13 +02:00
m_thread . reset ( new MUtils : : UpdateChecker ( m_binaries . value ( " wget.exe " ) , m_binaries . value ( " netc.exe " ) , m_binaries . value ( " gpgv.exe " ) , m_binaries . value ( " gpgv.gpg " ) , " Simple x264 Launcher " , x264_version_build ( ) , false ) ) ;
2015-02-01 21:05:17 +01:00
connect ( m_thread . data ( ) , SIGNAL ( statusChanged ( int ) ) , this , SLOT ( threadStatusChanged ( int ) ) ) ;
connect ( m_thread . data ( ) , SIGNAL ( finished ( ) ) , this , SLOT ( threadFinished ( ) ) ) ;
connect ( m_thread . data ( ) , SIGNAL ( terminated ( ) ) , this , SLOT ( threadFinished ( ) ) ) ;
connect ( m_thread . data ( ) , SIGNAL ( messageLogged ( QString ) ) , this , SLOT ( threadMessageLogged ( QString ) ) ) ;
2013-12-09 22:19:32 +01:00
}
2013-12-09 20:42:02 +01:00
2013-12-11 15:50:26 +01:00
//Begin updater run
2013-12-14 22:30:19 +01:00
QTimer : : singleShot ( 16 , this , SLOT ( checkForUpdates ( ) ) ) ;
2013-12-09 22:19:32 +01:00
}
void UpdaterDialog : : checkForUpdates ( void )
{
if ( ( ! m_thread ) | | m_thread - > isRunning ( ) )
{
qWarning ( " Update in progress, cannot check for updates now! " ) ;
}
2013-12-11 15:50:26 +01:00
//Clear texts
ui - > retranslateUi ( this ) ;
2013-12-14 22:30:19 +01:00
ui - > labelBuildNo - > setText ( tr ( " Installed build is #%1 | Latest build is #%2 " ) . arg ( QString : : number ( x264_version_build ( ) ) , tr ( " N/A " ) ) ) ;
2013-12-11 15:50:26 +01:00
2013-12-09 22:19:32 +01:00
//Init buttons
ui - > buttonCancel - > setEnabled ( false ) ;
ui - > buttonRetry - > hide ( ) ;
ui - > buttonDownload - > hide ( ) ;
//Hide labels
ui - > labelInfo - > hide ( ) ;
ui - > labelUrl - > hide ( ) ;
2013-12-11 15:50:26 +01:00
2013-12-09 22:19:32 +01:00
//Update status
2015-02-01 21:05:17 +01:00
threadStatusChanged ( MUtils : : UpdateChecker : : UpdateStatus_NotStartedYet ) ;
2013-12-09 22:19:32 +01:00
2013-12-11 15:50:26 +01:00
//Start animation
SHOW_ANIMATION ( true ) ;
2013-12-09 22:19:32 +01:00
//Update cursor
QApplication : : processEvents ( QEventLoop : : ExcludeUserInputEvents ) ;
QApplication : : setOverrideCursor ( Qt : : WaitCursor ) ;
2013-12-11 15:50:26 +01:00
//Clear log
m_logFile . clear ( ) ;
2013-12-09 22:19:32 +01:00
//Start the updater thread
2015-02-01 21:05:17 +01:00
QTimer : : singleShot ( 250 , m_thread . data ( ) , SLOT ( start ( ) ) ) ;
2013-11-23 15:20:07 +01:00
}
2013-12-09 22:19:32 +01:00
void UpdaterDialog : : threadStatusChanged ( int status )
2013-11-23 15:20:07 +01:00
{
2013-12-11 15:50:26 +01:00
switch ( m_status = status )
2013-11-23 15:20:07 +01:00
{
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_NotStartedYet :
2013-12-09 22:19:32 +01:00
UPDATE_ICON ( 1 , " clock " ) ;
UPDATE_ICON ( 2 , " clock " ) ;
UPDATE_ICON ( 3 , " clock " ) ;
break ;
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_CheckingConnection :
2013-11-23 15:20:07 +01:00
UPDATE_ICON ( 1 , " play " ) ;
break ;
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_FetchingUpdates :
2013-11-23 15:20:07 +01:00
UPDATE_ICON ( 1 , " shield_green " ) ;
UPDATE_TEXT ( 1 , tr ( " Internet connection is working. " ) ) ;
UPDATE_ICON ( 2 , " play " ) ;
break ;
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_ErrorNoConnection :
2013-12-11 15:50:26 +01:00
UPDATE_ICON ( 1 , " shield_error " ) ;
UPDATE_TEXT ( 1 , tr ( " Computer is currently offline! " ) ) ;
UPDATE_ICON ( 2 , " shield_grey " ) ;
UPDATE_ICON ( 3 , " shield_grey " ) ;
break ;
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_ErrorConnectionTestFailed :
2013-12-11 15:50:26 +01:00
UPDATE_ICON ( 1 , " shield_error " ) ;
UPDATE_TEXT ( 1 , tr ( " Internet connectivity test failed! " ) ) ;
UPDATE_ICON ( 2 , " shield_grey " ) ;
UPDATE_ICON ( 3 , " shield_grey " ) ;
break ;
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_ErrorFetchUpdateInfo :
2013-12-11 15:50:26 +01:00
UPDATE_ICON ( 2 , " shield_error " ) ;
UPDATE_TEXT ( 2 , tr ( " Failed to download the update information! " ) ) ;
UPDATE_ICON ( 3 , " shield_grey " ) ;
break ;
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_CompletedUpdateAvailable :
case MUtils : : UpdateChecker : : UpdateStatus_CompletedNoUpdates :
case MUtils : : UpdateChecker : : UpdateStatus_CompletedNewVersionOlder :
2013-12-11 15:50:26 +01:00
UPDATE_ICON ( 2 , " shield_green " ) ;
UPDATE_TEXT ( 2 , tr ( " Update information received successfully. " ) ) ;
UPDATE_ICON ( 3 , " play " ) ;
2013-12-09 22:19:32 +01:00
break ;
default :
2015-02-02 22:11:06 +01:00
MUTILS_THROW ( " Unknown status code! " ) ;
2013-12-09 22:19:32 +01:00
}
2013-12-11 15:50:26 +01:00
}
void UpdaterDialog : : threadFinished ( void )
2013-12-14 22:30:19 +01:00
{
m_success = m_thread - > getSuccess ( ) ;
QTimer : : singleShot ( ( m_success ? 1000 : 0 ) , this , SLOT ( updateFinished ( ) ) ) ;
}
void UpdaterDialog : : updateFinished ( void )
2013-12-11 15:50:26 +01:00
{
//Restore cursor
QApplication : : restoreOverrideCursor ( ) ;
2013-12-13 15:25:36 +01:00
//If update was successfull, process final updater state
if ( m_thread - > getSuccess ( ) )
2013-12-09 22:19:32 +01:00
{
2013-12-13 15:25:36 +01:00
switch ( m_status )
{
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_CompletedUpdateAvailable :
2013-12-13 15:25:36 +01:00
UPDATE_ICON ( 3 , " shield_exclamation " ) ;
UPDATE_TEXT ( 3 , tr ( " A newer version is available! " ) ) ;
ui - > buttonDownload - > show ( ) ;
break ;
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_CompletedNoUpdates :
2013-12-13 15:25:36 +01:00
UPDATE_ICON ( 3 , " shield_green " ) ;
UPDATE_TEXT ( 3 , tr ( " Your version is up-to-date. " ) ) ;
break ;
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_CompletedNewVersionOlder :
2013-12-14 22:30:19 +01:00
UPDATE_ICON ( 3 , " shield_blue " ) ;
2013-12-14 14:20:43 +01:00
UPDATE_TEXT ( 3 , tr ( " You are using a pre-release version! " ) ) ;
2013-12-13 15:25:36 +01:00
break ;
default :
qWarning ( " Update thread succeeded with unexpected status code: %d " , m_status ) ;
}
2013-12-11 15:50:26 +01:00
}
//Show update info or retry button
switch ( m_status )
{
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_CompletedUpdateAvailable :
case MUtils : : UpdateChecker : : UpdateStatus_CompletedNoUpdates :
case MUtils : : UpdateChecker : : UpdateStatus_CompletedNewVersionOlder :
2013-12-11 15:50:26 +01:00
SHOW_ANIMATION ( false ) ;
2015-02-01 21:05:17 +01:00
ui - > labelBuildNo - > setText ( tr ( " Installed build is #%1 | Latest build is #%2 " ) . arg ( QString : : number ( x264_version_build ( ) ) , QString : : number ( m_thread - > getUpdateInfo ( ) - > getBuildNo ( ) ) ) ) ;
ui - > labelUrl - > setText ( QString ( " <a href= \" %1 \" >%1</a> " ) . arg ( m_thread - > getUpdateInfo ( ) - > getDownloadSite ( ) ) ) ;
2013-12-11 15:50:26 +01:00
break ;
2015-02-01 21:05:17 +01:00
case MUtils : : UpdateChecker : : UpdateStatus_ErrorNoConnection :
case MUtils : : UpdateChecker : : UpdateStatus_ErrorConnectionTestFailed :
case MUtils : : UpdateChecker : : UpdateStatus_ErrorFetchUpdateInfo :
2013-12-13 15:25:36 +01:00
m_animator - > stop ( ) ;
2013-12-11 15:50:26 +01:00
ui - > buttonRetry - > show ( ) ;
2013-11-23 15:20:07 +01:00
break ;
2013-12-13 15:25:36 +01:00
default :
qWarning ( " Update thread finished with unexpected status code: %d " , m_status ) ;
2013-11-23 15:20:07 +01:00
}
2013-12-11 15:50:26 +01:00
//Re-enbale cancel button
ui - > buttonCancel - > setEnabled ( true ) ;
}
void UpdaterDialog : : threadMessageLogged ( const QString & message )
{
m_logFile < < message ;
}
void UpdaterDialog : : openUrl ( const QString & url )
{
qDebug ( " Open URL: %s " , url . toLatin1 ( ) . constData ( ) ) ;
QDesktopServices : : openUrl ( QUrl ( url ) ) ;
}
void UpdaterDialog : : installUpdate ( void )
{
if ( ! ( ( m_thread ) & & m_thread - > getSuccess ( ) ) )
{
qWarning ( " Cannot download/install update at this point! " ) ;
return ;
}
2013-12-13 15:25:36 +01:00
QApplication : : setOverrideCursor ( Qt : : WaitCursor ) ;
ui - > buttonDownload - > hide ( ) ;
ui - > buttonCancel - > setEnabled ( false ) ;
SHOW_ANIMATION ( true ) ;
2015-02-01 21:05:17 +01:00
const MUtils : : UpdateCheckerInfo * updateInfo = m_thread - > getUpdateInfo ( ) ;
2013-12-11 15:50:26 +01:00
QProcess process ;
QStringList args ;
QEventLoop loop ;
2015-02-02 22:11:06 +01:00
MUtils : : init_process ( process , MUtils : : temp_folder ( ) , false ) ;
2013-12-11 15:50:26 +01:00
connect ( & process , SIGNAL ( error ( QProcess : : ProcessError ) ) , & loop , SLOT ( quit ( ) ) ) ;
connect ( & process , SIGNAL ( finished ( int , QProcess : : ExitStatus ) ) , & loop , SLOT ( quit ( ) ) ) ;
2015-02-01 21:05:17 +01:00
args < < QString ( " /Location=%1 " ) . arg ( updateInfo - > getDownloadAddress ( ) ) ;
args < < QString ( " /Filename=%1 " ) . arg ( updateInfo - > getDownloadFilename ( ) ) ;
args < < QString ( " /TicketID=%1 " ) . arg ( updateInfo - > getDownloadFilecode ( ) ) ;
2015-10-12 20:31:24 +02:00
args < < QString ( " /CheckSum=%1 " ) . arg ( updateInfo - > getDownloadChecksum ( ) ) ;
args < < QString ( " /ToFolder=%1 " ) . arg ( QDir : : toNativeSeparators ( QDir ( QApplication : : applicationDirPath ( ) ) . canonicalPath ( ) ) ) ;
2013-12-11 15:50:26 +01:00
args < < QString ( " /ToExFile=%1.exe " ) . arg ( QFileInfo ( QFileInfo ( QApplication : : applicationFilePath ( ) ) . canonicalFilePath ( ) ) . completeBaseName ( ) ) ;
2015-02-01 21:05:17 +01:00
args < < QString ( " /AppTitle=Simple x264 Launcher (Build #%1) " ) . arg ( QString : : number ( updateInfo - > getBuildNo ( ) ) ) ;
2013-12-11 15:50:26 +01:00
2015-02-01 21:05:17 +01:00
process . start ( m_binaries . value ( " wupd.exe " ) , args ) ;
2013-12-11 15:50:26 +01:00
if ( ! process . waitForStarted ( ) )
{
2013-12-13 15:25:36 +01:00
QApplication : : restoreOverrideCursor ( ) ;
SHOW_ANIMATION ( false ) ;
2013-12-11 15:50:26 +01:00
QMessageBox : : critical ( this , tr ( " Update Failed " ) , tr ( " Sorry, failed to launch web-update program! " ) ) ;
2013-12-13 15:25:36 +01:00
ui - > buttonDownload - > show ( ) ;
ui - > buttonCancel - > setEnabled ( true ) ;
2013-12-11 15:50:26 +01:00
return ;
}
2015-02-02 22:11:06 +01:00
m_updaterProcess = MUtils : : OS : : process_id ( & process ) ;
2013-12-11 15:50:26 +01:00
loop . exec ( QEventLoop : : ExcludeUserInputEvents ) ;
if ( ! process . waitForFinished ( ) )
{
process . kill ( ) ;
process . waitForFinished ( ) ;
}
2013-12-13 15:25:36 +01:00
m_updaterProcess = NULL ;
2013-12-11 15:50:26 +01:00
QApplication : : restoreOverrideCursor ( ) ;
ui - > buttonDownload - > show ( ) ;
ui - > buttonCancel - > setEnabled ( true ) ;
2013-12-13 15:25:36 +01:00
SHOW_ANIMATION ( false ) ;
2013-12-11 15:50:26 +01:00
if ( process . exitCode ( ) = = 0 )
{
2013-12-14 22:30:19 +01:00
done ( READY_TO_INSTALL_UPDATE ) ;
2013-12-11 15:50:26 +01:00
}
2013-11-23 15:20:07 +01:00
}
2013-12-09 20:42:02 +01:00
///////////////////////////////////////////////////////////////////////////////
// Private Functions
///////////////////////////////////////////////////////////////////////////////
2016-04-23 15:09:13 +02:00
bool UpdaterDialog : : checkBinaries ( void )
2013-12-09 20:42:02 +01:00
{
qDebug ( " [File Verification] " ) ;
2015-02-01 21:05:17 +01:00
m_binaries . clear ( ) ;
2013-12-09 22:19:32 +01:00
2015-02-01 21:05:17 +01:00
//Validate hashes first
const QString tempPath = MUtils : : temp_folder ( ) ;
2014-04-21 16:39:54 +02:00
for ( size_t i = 0 ; BINARIES [ i ] . name ; i + + )
2013-12-09 20:42:02 +01:00
{
2015-02-01 21:05:17 +01:00
const QString orgName = QString : : fromLatin1 ( BINARIES [ i ] . name ) ;
const QString binPath = QString ( " %1/toolset/common/%2 " ) . arg ( m_sysinfo - > getAppPath ( ) , orgName ) ;
const QString outPath = QString ( " %1/%2_%3.%4 " ) . arg ( tempPath , QFileInfo ( orgName ) . baseName ( ) , MUtils : : rand_str ( ) , QFileInfo ( orgName ) . suffix ( ) ) ;
if ( ! checkFileHash ( binPath , BINARIES [ i ] . hash ) )
2013-12-09 22:19:32 +01:00
{
2015-02-01 21:05:17 +01:00
qWarning ( " Verification of '%s' has failed! " , MUTILS_UTF8 ( orgName ) ) ;
return false ;
2013-12-09 22:19:32 +01:00
}
2015-02-01 21:05:17 +01:00
if ( ! QFile : : copy ( binPath , outPath ) )
2013-12-11 15:50:26 +01:00
{
2015-02-01 21:05:17 +01:00
qWarning ( " Copying of '%s' has failed! " , MUTILS_UTF8 ( orgName ) ) ;
return false ;
2013-12-11 15:50:26 +01:00
}
2015-02-01 21:05:17 +01:00
QFile : : setPermissions ( outPath , QFile : : ReadOwner ) ;
m_binaries . insert ( BINARIES [ i ] . name , outPath ) ;
QApplication : : processEvents ( QEventLoop : : ExcludeUserInputEvents ) ;
2013-12-09 20:42:02 +01:00
}
2015-02-01 21:05:17 +01:00
return true ;
2013-12-09 20:42:02 +01:00
}
bool UpdaterDialog : : checkFileHash ( const QString & filePath , const char * expectedHash )
{
qDebug ( " Checking file: %s " , filePath . toUtf8 ( ) . constData ( ) ) ;
2015-02-01 21:05:17 +01:00
MUtils : : Hash : : Blake2 checksum2 ;
2013-12-09 20:42:02 +01:00
QFile file ( filePath ) ;
if ( file . open ( QIODevice : : ReadOnly ) )
{
checksum2 . update ( file ) ;
const QByteArray fileHash = checksum2 . finalize ( ) ;
if ( ( strlen ( expectedHash ) ! = fileHash . size ( ) ) | | ( memcmp ( fileHash . constData ( ) , expectedHash , fileHash . size ( ) ) ! = 0 ) )
{
qWarning ( " \n File appears to be corrupted: \n %s \n " , filePath . toUtf8 ( ) . constData ( ) ) ;
qWarning ( " Expected Hash: %s \n Detected Hash: %s \n " , expectedHash , fileHash . constData ( ) ) ;
return false ;
}
return true ;
}
else
{
qWarning ( " Failed to open file: \n %s \n " , filePath . toUtf8 ( ) . constData ( ) ) ;
return false ;
}
}
2015-02-01 21:05:17 +01:00
void UpdaterDialog : : cleanFiles ( void )
{
const QStringList keys = m_binaries . keys ( ) ;
foreach ( const QString & key , keys )
{
const QString fileName = m_binaries . value ( key ) ;
QFile : : setPermissions ( fileName , QFile : : ReadOwner | QFile : : WriteOwner ) ;
if ( ! QFile : : remove ( fileName ) )
{
qWarning ( " Failed to remove file: %s " , MUTILS_UTF8 ( fileName ) ) ;
}
m_binaries . remove ( key ) ;
}
}