2012-06-21 09:49:32 -05:00
# include <bzlib.h>
# include <sstream>
2012-06-22 13:04:38 -05:00
# include "dialogues/ConfirmPrompt.h"
2012-06-21 09:49:32 -05:00
# include "interface/Engine.h"
2012-06-20 11:51:51 -05:00
# include "UpdateActivity.h"
# include "tasks/Task.h"
2012-06-21 09:49:32 -05:00
# include "client/HTTP.h"
2012-06-21 19:44:30 -05:00
# include "client/Client.h"
2012-06-21 09:49:32 -05:00
# include "Update.h"
2012-06-22 13:04:38 -05:00
# include "Misc.h"
2012-06-21 09:49:32 -05:00
2012-06-20 11:51:51 -05:00
class UpdateDownloadTask : public Task
{
2012-06-21 09:49:32 -05:00
public :
UpdateDownloadTask ( std : : string updateName , UpdateActivity * a ) : updateName ( updateName ) , a ( a ) { } ;
private :
UpdateActivity * a ;
std : : string updateName ;
2012-06-22 13:04:38 -05:00
virtual void notifyDoneMain ( ) {
2012-06-21 09:49:32 -05:00
a - > NotifyDone ( this ) ;
}
2012-06-22 13:04:38 -05:00
virtual void notifyErrorMain ( )
{
a - > NotifyError ( this ) ;
}
virtual bool doWork ( )
2012-06-20 11:51:51 -05:00
{
2012-06-21 09:49:32 -05:00
std : : stringstream errorStream ;
void * request = http_async_req_start ( NULL , ( char * ) updateName . c_str ( ) , NULL , 0 , 0 ) ;
notifyStatus ( " Downloading update " ) ;
notifyProgress ( - 1 ) ;
while ( ! http_async_req_status ( request ) )
{
int total , done ;
http_async_get_length ( request , & total , & done ) ;
notifyProgress ( ( float ( done ) / float ( total ) ) * 100.0f ) ;
}
char * data ;
int dataLength , status ;
data = http_async_req_stop ( request , & status , & dataLength ) ;
if ( status ! = 200 )
{
if ( data )
free ( data ) ;
errorStream < < " Server responded with Status " < < status ;
notifyError ( " Could not download update " ) ;
2012-06-22 13:04:38 -05:00
return false ;
2012-06-21 09:49:32 -05:00
}
if ( ! data )
{
errorStream < < " Server responded with nothing " ;
notifyError ( " Server did not return any data " ) ;
2012-06-22 13:04:38 -05:00
return false ;
2012-06-21 09:49:32 -05:00
}
notifyStatus ( " Unpacking update " ) ;
notifyProgress ( - 1 ) ;
int uncompressedLength ;
if ( dataLength < 16 )
{
errorStream < < " Unsufficient data, got " < < dataLength < < " bytes " ;
goto corrupt ;
}
if ( data [ 0 ] ! = 0x42 | | data [ 1 ] ! = 0x75 | | data [ 2 ] ! = 0x54 | | data [ 3 ] ! = 0x54 )
{
errorStream < < " Invalid update format " ;
goto corrupt ;
}
uncompressedLength = ( unsigned char ) data [ 4 ] ;
uncompressedLength | = ( ( unsigned char ) data [ 5 ] ) < < 8 ;
uncompressedLength | = ( ( unsigned char ) data [ 6 ] ) < < 16 ;
uncompressedLength | = ( ( unsigned char ) data [ 7 ] ) < < 24 ;
char * res ;
res = ( char * ) malloc ( uncompressedLength ) ;
if ( ! res )
{
errorStream < < " Unable to allocate " < < uncompressedLength < < " bytes of memory for decompression " ;
goto corrupt ;
}
int dstate ;
dstate = BZ2_bzBuffToBuffDecompress ( ( char * ) res , ( unsigned * ) & uncompressedLength , ( char * ) ( data + 8 ) , dataLength - 8 , 0 , 0 ) ;
if ( dstate )
{
errorStream < < " Unable to decompress update: " < < dstate ;
free ( res ) ;
goto corrupt ;
}
free ( data ) ;
notifyStatus ( " Applying update " ) ;
notifyProgress ( - 1 ) ;
2012-08-18 06:44:07 -05:00
Client : : Ref ( ) . SetPref ( " version.update " , true ) ;
Client : : Ref ( ) . WritePrefs ( ) ;
2012-06-21 09:49:32 -05:00
if ( update_start ( res , uncompressedLength ) )
{
2012-08-18 06:44:07 -05:00
Client : : Ref ( ) . SetPref ( " version.update " , false ) ;
2012-06-21 09:49:32 -05:00
update_cleanup ( ) ;
notifyError ( " Update failed - try downloading a new version. " ) ;
2012-08-18 06:44:07 -05:00
return false ;
2012-06-21 09:49:32 -05:00
}
2012-06-22 13:04:38 -05:00
return true ;
2012-06-21 09:49:32 -05:00
corrupt :
notifyError ( " Downloaded update is corrupted \n " + errorStream . str ( ) ) ;
free ( data ) ;
2012-06-22 13:04:38 -05:00
return false ;
2012-06-21 09:49:32 -05:00
}
2012-06-20 11:51:51 -05:00
} ;
UpdateActivity : : UpdateActivity ( ) {
2012-06-22 13:04:38 -05:00
std : : stringstream file ;
file < < " http:// " < < SERVER < < Client : : Ref ( ) . GetUpdateInfo ( ) . File ;
updateDownloadTask = new UpdateDownloadTask ( file . str ( ) , this ) ;
2012-06-21 09:49:32 -05:00
updateWindow = new TaskWindow ( " Downloading update... " , updateDownloadTask , true ) ;
}
2012-06-20 11:51:51 -05:00
2012-06-21 09:49:32 -05:00
void UpdateActivity : : NotifyDone ( Task * sender )
2012-06-22 13:04:38 -05:00
{
if ( sender - > GetSuccess ( ) )
{
Exit ( ) ;
}
}
void UpdateActivity : : Exit ( )
2012-06-21 09:49:32 -05:00
{
updateWindow - > Exit ( ) ;
ui : : Engine : : Ref ( ) . Exit ( ) ;
delete this ;
2012-06-20 11:51:51 -05:00
}
2012-06-22 13:04:38 -05:00
void UpdateActivity : : NotifyError ( Task * sender )
{
class ErrorMessageCallback : public ConfirmDialogueCallback
{
UpdateActivity * a ;
public :
ErrorMessageCallback ( UpdateActivity * a_ ) { a = a_ ; }
virtual void ConfirmCallback ( ConfirmPrompt : : DialogueResult result ) {
if ( result = = ConfirmPrompt : : ResultOkay )
{
OpenURI ( " http://powdertoy.co.uk/Download.html " ) ;
}
a - > Exit ( ) ;
}
virtual ~ ErrorMessageCallback ( ) { }
} ;
new ConfirmPrompt ( " Autoupdate failed " , " Please visit the website to download a newer version. \n Error: " + sender - > GetError ( ) , new ErrorMessageCallback ( this ) ) ;
}
2012-06-20 11:51:51 -05:00
UpdateActivity : : ~ UpdateActivity ( ) {
}