2013-11-22 17:01:13 +01:00
///////////////////////////////////////////////////////////////////////////////
// Simple x264 Launcher
// Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
//
// 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"
# include "uic_win_updater.h"
# include "global.h"
2013-12-09 22:19:32 +01:00
# include "thread_updater.h"
2013-11-23 15:20:07 +01:00
# include "checksum.h"
# include <QMovie>
# include <QCloseEvent>
# include <QTimer>
2013-11-29 18:10:11 +01:00
# include <QMessageBox>
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 \
{ \
ui - > labelLoadingLeft - > setVisible ( ( FLAG ) ) ; \
ui - > labelLoadingCenter - > setVisible ( ( FLAG ) ) ; \
ui - > labelLoadingRight - > setVisible ( ( FLAG ) ) ; \
ui - > labelInfo - > setVisible ( ! ( FLAG ) ) ; \
ui - > labelUrl - > setVisible ( ! ( FLAG ) ) ; \
} \
while ( 0 )
2013-11-22 17:01:13 +01:00
///////////////////////////////////////////////////////////////////////////////
// Constructor & Destructor
///////////////////////////////////////////////////////////////////////////////
2013-12-09 20:42:02 +01:00
UpdaterDialog : : UpdaterDialog ( QWidget * parent , const QString & binDir )
2013-11-22 17:01:13 +01:00
:
QDialog ( parent ) ,
2013-11-23 15:20:07 +01:00
ui ( new Ui : : UpdaterDialog ( ) ) ,
2013-12-09 20:42:02 +01:00
m_binDir ( binDir ) ,
2013-12-09 22:19:32 +01:00
m_thread ( NULL ) ,
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 ( ) ) ;
//Init animation
m_animator = new QMovie ( " :/images/loading.gif " ) ;
ui - > labelLoadingCenter - > setMovie ( m_animator ) ;
m_animator - > start ( ) ;
//Init buttons
ui - > buttonCancel - > setEnabled ( false ) ;
ui - > buttonRetry - > hide ( ) ;
ui - > buttonDownload - > hide ( ) ;
//Hide labels
ui - > labelInfo - > hide ( ) ;
ui - > labelUrl - > hide ( ) ;
2013-11-22 17:01:13 +01:00
}
UpdaterDialog : : ~ UpdaterDialog ( void )
{
2013-12-09 22:19:32 +01:00
if ( m_thread )
{
if ( ! m_thread - > wait ( 1000 ) )
{
m_thread - > terminate ( ) ;
m_thread - > wait ( ) ;
}
}
X264_DELETE ( m_thread ) ;
2013-11-23 15:20:07 +01:00
X264_DELETE ( m_animator ) ;
2013-12-09 22:19:32 +01:00
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-11-23 15:20:07 +01:00
void UpdaterDialog : : showEvent ( QShowEvent * event )
{
if ( m_firstShow )
{
m_firstShow = false ;
QTimer : : singleShot ( 0 , this , SLOT ( initUpdate ( ) ) ) ;
}
}
void UpdaterDialog : : closeEvent ( QCloseEvent * e )
{
if ( ! ui - > buttonCancel - > isEnabled ( ) )
{
e - > ignore ( ) ;
}
}
2013-11-22 17:01:13 +01:00
///////////////////////////////////////////////////////////////////////////////
// Slots
///////////////////////////////////////////////////////////////////////////////
2013-11-23 15:20:07 +01:00
void UpdaterDialog : : initUpdate ( void )
{
2013-11-22 17:01:13 +01:00
2013-11-23 15:20:07 +01:00
//Reset icons
2013-12-09 22:19:32 +01:00
2013-11-23 15:20:07 +01:00
//Show animation
2013-12-09 20:42:02 +01:00
//Check binary files
2013-12-09 22:19:32 +01:00
QStringList binaries ;
if ( ! checkBinaries ( binaries ) )
2013-12-09 20:42:02 +01:00
{
ui - > buttonCancel - > setEnabled ( true ) ;
QMessageBox : : critical ( this , tr ( " File Error " ) , tr ( " At least one file required by web-update is missing or corrupted.<br>Please re-install this application and then try again! " ) ) ;
close ( ) ;
return ;
}
2013-12-09 22:19:32 +01:00
//Create and setup thread
if ( ! m_thread )
{
m_thread = new UpdateCheckThread ( binaries [ 0 ] , binaries [ 1 ] , binaries [ 2 ] , false ) ;
connect ( m_thread , SIGNAL ( statusChanged ( int ) ) , this , SLOT ( threadStatusChanged ( int ) ) ) ;
connect ( m_thread , SIGNAL ( progressChanged ( int ) ) , this , SLOT ( threadProgressChanged ( int ) ) ) ;
connect ( m_thread , SIGNAL ( messageLogged ( QString ) ) , this , SLOT ( threadMessageLogged ( QString ) ) ) ;
connect ( m_thread , SIGNAL ( finished ( ) ) , this , SLOT ( threadFinished ( ) ) ) ;
connect ( m_thread , SIGNAL ( terminated ( ) ) , this , SLOT ( threadFinished ( ) ) ) ;
}
2013-12-09 20:42:02 +01:00
2013-11-23 15:20:07 +01:00
//Begin updater test run
2013-12-09 22:19:32 +01:00
QTimer : : singleShot ( 0 , this , SLOT ( checkForUpdates ( ) ) ) ;
}
void UpdaterDialog : : checkForUpdates ( void )
{
if ( ( ! m_thread ) | | m_thread - > isRunning ( ) )
{
qWarning ( " Update in progress, cannot check for updates now! " ) ;
}
//Init buttons
ui - > buttonCancel - > setEnabled ( false ) ;
ui - > buttonRetry - > hide ( ) ;
ui - > buttonDownload - > hide ( ) ;
//Hide labels
ui - > labelInfo - > hide ( ) ;
ui - > labelUrl - > hide ( ) ;
//Update status
threadStatusChanged ( UpdateCheckThread : : UpdateStatus_NotStartedYet ) ;
//Update cursor
QApplication : : processEvents ( QEventLoop : : ExcludeUserInputEvents ) ;
QApplication : : setOverrideCursor ( Qt : : WaitCursor ) ;
//Start the updater thread
m_thread - > 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-09 22:19:32 +01:00
switch ( status )
2013-11-23 15:20:07 +01:00
{
2013-12-09 22:19:32 +01:00
case UpdateCheckThread : : UpdateStatus_NotStartedYet :
UPDATE_ICON ( 1 , " clock " ) ;
UPDATE_ICON ( 2 , " clock " ) ;
UPDATE_ICON ( 3 , " clock " ) ;
ui - > retranslateUi ( this ) ;
break ;
case UpdateCheckThread : : UpdateStatus_CheckingConnection :
2013-11-23 15:20:07 +01:00
UPDATE_ICON ( 1 , " play " ) ;
break ;
2013-12-09 22:19:32 +01:00
case UpdateCheckThread : : 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 ;
2013-12-09 22:19:32 +01:00
case UpdateCheckThread : : UpdateStatus_CompletedUpdateAvailable :
2013-11-23 15:20:07 +01:00
UPDATE_ICON ( 3 , " shield_exclamation " ) ;
UPDATE_TEXT ( 3 , tr ( " A newer version is available! " ) ) ;
2013-12-09 22:19:32 +01:00
break ;
case UpdateCheckThread : : UpdateStatus_ErrorNoConnection :
case UpdateCheckThread : : UpdateStatus_ErrorConnectionTestFailed :
case UpdateCheckThread : : UpdateStatus_ErrorFetchUpdateInfo :
break ;
default :
throw " Unknown status code! " ;
}
switch ( status )
{
case UpdateCheckThread : : UpdateStatus_CompletedUpdateAvailable :
case UpdateCheckThread : : UpdateStatus_CompletedNoUpdates :
case UpdateCheckThread : : UpdateStatus_CompletedNewVersionOlder :
UPDATE_ICON ( 2 , " shield_green " ) ;
UPDATE_TEXT ( 2 , tr ( " Update-information was received successfully. " ) ) ;
ui - > buttonDownload - > show ( ) ;
case UpdateCheckThread : : UpdateStatus_ErrorNoConnection :
case UpdateCheckThread : : UpdateStatus_ErrorConnectionTestFailed :
case UpdateCheckThread : : UpdateStatus_ErrorFetchUpdateInfo :
2013-11-23 15:20:07 +01:00
SHOW_ANIMATION ( false ) ;
ui - > buttonCancel - > setEnabled ( true ) ;
break ;
}
}
2013-12-09 20:42:02 +01:00
///////////////////////////////////////////////////////////////////////////////
// Private Functions
///////////////////////////////////////////////////////////////////////////////
2013-12-09 22:19:32 +01:00
bool UpdaterDialog : : checkBinaries ( QStringList & binaries )
2013-12-09 20:42:02 +01:00
{
qDebug ( " [File Verification] " ) ;
static struct
{
const char * name ;
const char * hash ;
}
FILE_INFO [ ] =
{
{ " wget.exe " , " 7b522345239bcb95b5b0f7f50a883ba5957894a1feb769763e38ed789a8a0f63fead0155f54b9ffd0f1cdc5dfd855d207a6e7a8e4fd192589a8838ce646c504e " } ,
{ " gpgv.exe " , " e61d28e4c47b2422ceec7b8fc08f9c70f10a3056e3779a974026eb24fe09551eedc2e7f34fbe5ef8e844fab0dbe68b85c4ca69d63bf85d445f7cae152c17f589 " } ,
{ " gpgv.gpg " , " 58e0f0e462bbd0b5aa4f638801c1097da7da4b3eb38c8c88ad1db23705c0f11e174b083fa55fe76bd3ba196341c967833a6f3427d6f63ad8565900745535d8fa " } ,
{ NULL , NULL }
} ;
bool okay = true ;
2013-12-09 22:19:32 +01:00
binaries . clear ( ) ;
2013-12-09 20:42:02 +01:00
for ( size_t i = 0 ; FILE_INFO [ i ] . name ; i + + )
{
2013-12-09 22:19:32 +01:00
const QString binPath = QString ( " %1/common/%2 " ) . arg ( m_binDir , QString : : fromLatin1 ( FILE_INFO [ i ] . name ) ) ;
if ( okay = okay & & checkFileHash ( binPath , FILE_INFO [ i ] . hash ) )
{
binaries < < binPath ;
}
2013-12-09 20:42:02 +01:00
}
if ( okay )
{
qDebug ( " Completed. \n " ) ;
}
return okay ;
}
bool UpdaterDialog : : checkFileHash ( const QString & filePath , const char * expectedHash )
{
qDebug ( " Checking file: %s " , filePath . toUtf8 ( ) . constData ( ) ) ;
QBlake2Checksum checksum2 ;
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 ;
}
}