352 lines
11 KiB
PHP
352 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* @brief upgrade
|
|
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
|
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
|
* @license http://www.invisionpower.com/legal/standards/
|
|
* @package IPS Social Suite
|
|
* @since 28 Jul 2015
|
|
* @version SVN_VERSION_NUMBER
|
|
*/
|
|
|
|
namespace IPS\core\modules\admin\system;
|
|
|
|
/* To prevent PHP errors (extending class does not exist) revealing path */
|
|
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
|
{
|
|
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* upgrade
|
|
*/
|
|
class _upgrade extends \IPS\Dispatcher\Controller
|
|
{
|
|
/**
|
|
* Manage
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function manage()
|
|
{
|
|
\IPS\Dispatcher::i()->checkAcpPermission( 'upgrade_manage' );
|
|
|
|
if ( \IPS\NO_WRITES )
|
|
{
|
|
\IPS\Output::i()->error( 'no_writes', '1C287/1', 403, '' );
|
|
}
|
|
|
|
$wizard = new \IPS\Helpers\Wizard( array(
|
|
'upgrade_confirm_update' => array( $this, '_selectVersion' ),
|
|
'upgrade_login' => array( $this, '_login' ),
|
|
'upgrade_extract_update' => array( $this, '_extractUpdate' ),
|
|
'upgrade_upgrade' => array( $this, '_upgrade' ),
|
|
), \IPS\Http\Url::internal( 'app=core&module=system&controller=upgrade' ) );
|
|
|
|
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('ips_suite_upgrade');
|
|
\IPS\Output::i()->output = $wizard;
|
|
}
|
|
|
|
/**
|
|
* Select Version
|
|
*
|
|
* @param array $data Wizard data
|
|
* @return string|array
|
|
*/
|
|
public function _selectVersion( $data )
|
|
{
|
|
/* Check latest version */
|
|
$versions = array();
|
|
foreach ( \IPS\Db::i()->select( '*', 'core_applications', \IPS\Db::i()->in( 'app_directory', \IPS\Application::$ipsApps ) ) as $app )
|
|
{
|
|
if ( $app['app_enabled'] )
|
|
{
|
|
$versions[] = $app['app_long_version'];
|
|
}
|
|
}
|
|
$version = min( $versions );
|
|
$url = \IPS\Http\Url::ips('updateCheck');
|
|
if ( \IPS\USE_DEVELOPMENT_BUILDS )
|
|
{
|
|
$url = $url->setQueryString( 'development', 1 );
|
|
}
|
|
try
|
|
{
|
|
$response = $url->setQueryString( 'version', $version )->request()->get()->decodeJson();
|
|
$coreApp = \IPS\Application::load('core');
|
|
$coreApp->update_version = json_encode( $response );
|
|
$coreApp->update_last_check = time();
|
|
$coreApp->save();
|
|
}
|
|
catch ( \Exception $e ) { }
|
|
|
|
/* Build form */
|
|
$form = new \IPS\Helpers\Form( 'select_version' );
|
|
$options = array();
|
|
$descriptions = array();
|
|
$latestVersion = 0;
|
|
foreach( \IPS\Application::load( 'core' )->availableUpgrade() as $possibleVersion )
|
|
{
|
|
$options[ $possibleVersion['longversion'] ] = $possibleVersion['version'];
|
|
$descriptions[ $possibleVersion['longversion'] ] = $possibleVersion;
|
|
if ( $latestVersion < $possibleVersion['longversion'] )
|
|
{
|
|
$latestVersion = $possibleVersion['longversion'];
|
|
}
|
|
}
|
|
$form->add( new \IPS\Helpers\Form\Radio( 'version', $latestVersion, TRUE, array( 'options' => $options, '_details' => $descriptions ) ) );
|
|
|
|
/* Handle submissions */
|
|
if ( $values = $form->values() )
|
|
{
|
|
return array( 'version' => $values['version'] );
|
|
}
|
|
|
|
/* Display */
|
|
return $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'system' ) ), 'upgradeSelectVersion' ) );
|
|
}
|
|
|
|
/**
|
|
* Login
|
|
*
|
|
* @param array $data Wizard data
|
|
* @return string|array
|
|
*/
|
|
public function _login( $data )
|
|
{
|
|
/* Build form */
|
|
$form = new \IPS\Helpers\Form( 'login', 'continue' );
|
|
$form->hiddenValues['version'] = $data['version'];
|
|
$form->add( new \IPS\Helpers\Form\Email( 'ips_email_address', NULL ) );
|
|
$form->add( new \IPS\Helpers\Form\Password( 'ips_password', NULL ) );
|
|
|
|
/* Handle submissions */
|
|
if ( $values = $form->values() )
|
|
{
|
|
$key = \IPS\IPS::licenseKey();
|
|
|
|
$url = \IPS\Http\Url::ips( 'build/' . $key['key'] )->setQueryString( 'ip', \IPS\Request::i()->ipAddress() );
|
|
if ( \IPS\USE_DEVELOPMENT_BUILDS )
|
|
{
|
|
$url = $url->setQueryString( 'development', 1 );
|
|
}
|
|
elseif ( isset( $values['version'] ) )
|
|
{
|
|
$url = $url->setQueryString( 'versionToDownload', $values['version'] );
|
|
}
|
|
if ( \IPS\CP_DIRECTORY !== 'admin' )
|
|
{
|
|
$url = $url->setQueryString( 'cp_directory', \IPS\CP_DIRECTORY );
|
|
}
|
|
|
|
try
|
|
{
|
|
$response = $url->request( 30 )->login( $values['ips_email_address'], $values['ips_password'] )->get();
|
|
switch ( $response->httpResponseCode )
|
|
{
|
|
case 200:
|
|
if ( !preg_match( '/^ips_[a-z0-9]{5}$/', (string) $response ) )
|
|
{
|
|
\IPS\Log::i( LOG_ERR )->write( (string) $response );
|
|
$form->error = \IPS\Member::loggedIn()->language()->addToStack('download_upgrade_error');
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
$data['key'] = (string) $response;
|
|
return $data;
|
|
}
|
|
|
|
case 304:
|
|
if ( \IPS\Db::i()->select( 'MIN(app_long_version)', 'core_applications', \IPS\Db::i()->in( 'app_directory', \IPS\Application::$ipsApps ) )->first() < \IPS\Application::getAvailableVersion('core') )
|
|
{
|
|
$data['key'] = NULL;
|
|
return $data;
|
|
}
|
|
$form->error = \IPS\Member::loggedIn()->language()->addToStack('download_upgrade_nothing');
|
|
break;
|
|
|
|
default:
|
|
$form->error = (string) $response;
|
|
}
|
|
|
|
}
|
|
catch ( \Exception $exception )
|
|
{
|
|
\IPS\Log::i( LOG_ERR )->write( get_class( $exception ) . "\n" . $exception->getCode() . ": " . $exception->getMessage() . "\n" . $exception->getTraceAsString() );
|
|
$form->error = \IPS\Member::loggedIn()->language()->addToStack('download_upgrade_error');
|
|
}
|
|
}
|
|
|
|
return (string) $form;
|
|
}
|
|
|
|
/**
|
|
* Extract Update
|
|
*
|
|
* @param array $data Wizard data
|
|
* @return string|array
|
|
*/
|
|
public function _extractUpdate( $data )
|
|
{
|
|
/* Download & Extract */
|
|
if ( $data['key'] and !isset( \IPS\Request::i()->check ) )
|
|
{
|
|
/* Muliple Redirector */
|
|
return (string) new \IPS\Helpers\MultipleRedirect( \IPS\Http\Url::internal('app=core&module=system&controller=upgrade'), function( $mrData ) use ( $data )
|
|
{
|
|
/* Init */
|
|
if ( !is_array( $mrData ) )
|
|
{
|
|
return array( array( 'status' => 'download' ), \IPS\Member::loggedIn()->language()->addToStack('delta_upgrade_downloading'), 0 );
|
|
}
|
|
/* Download */
|
|
elseif ( $mrData['status'] == 'download' )
|
|
{
|
|
if ( !isset( $mrData['tmpFileName'] ) )
|
|
{
|
|
$mrData['tmpFileName'] = tempnam( \IPS\TEMP_DIRECTORY, 'IPS' ) . '.zip';
|
|
|
|
return array( $mrData, \IPS\Member::loggedIn()->language()->addToStack('delta_upgrade_downloading'), 0 );
|
|
}
|
|
else
|
|
{
|
|
if ( !isset( $mrData['range'] ) )
|
|
{
|
|
$mrData['range'] = 0;
|
|
}
|
|
$startRange = $mrData['range'];
|
|
$endRange = $startRange + 1000000 - 1;
|
|
|
|
$response = \IPS\Http\Url::ips("download/{$data['key']}")->request( 30 )->setHeaders( array( 'Range' => "bytes={$startRange}-{$endRange}" ) )->get();
|
|
|
|
try
|
|
{
|
|
\IPS\Log::i( LOG_ERR )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Fetching download [range={$startRange}-{$endRange}] with a response code: " . $response->httpResponseCode, 'auto_upgrade' );
|
|
}
|
|
catch( \Exception $ex ) { }
|
|
|
|
if ( $response->httpResponseCode == 404 )
|
|
{
|
|
if ( isset( $mrData['tmpFileName'] ) )
|
|
{
|
|
@unlink( $mrData['tmpFileName'] );
|
|
}
|
|
|
|
return array( \IPS\Theme::i()->getTemplate('system')->upgradeDeltaFailed( TRUE, isset( $data['key'] ) ? \IPS\Http\Url::ips("download/{$data['key']}") : NULL ) );
|
|
}
|
|
elseif ( $response->httpResponseCode == 206 )
|
|
{
|
|
$totalFileSize = intval( mb_substr( $response->httpHeaders['Content-Range'], mb_strpos( $response->httpHeaders['Content-Range'], '/' ) + 1 ) );
|
|
$fh = \fopen( $mrData['tmpFileName'], 'a' );
|
|
\fwrite( $fh, (string) $response );
|
|
\fclose( $fh );
|
|
|
|
$mrData['range'] = $endRange + 1;
|
|
return array( $mrData, \IPS\Member::loggedIn()->language()->addToStack('delta_upgrade_downloading'), 100 / $totalFileSize * $mrData['range'] );
|
|
}
|
|
else
|
|
{
|
|
$mrData['status'] = 'extract';
|
|
return array( $mrData, \IPS\Member::loggedIn()->language()->addToStack('delta_upgrade_extracting'), 0 );
|
|
}
|
|
}
|
|
}
|
|
/* Extract */
|
|
elseif ( $mrData['status'] == 'extract' )
|
|
{
|
|
try
|
|
{
|
|
try
|
|
{
|
|
\IPS\Log::i( LOG_ERR )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Attempting to extract", 'auto_upgrade' );
|
|
}
|
|
catch( \Exception $ex ) { }
|
|
|
|
/* Open the zip */
|
|
$zip = \IPS\Archive\Zip::fromLocalFile( $mrData['tmpFileName'], $data['key'] . '/' );
|
|
|
|
/* Extract some files */
|
|
$numberToDo = 20;
|
|
if ( !isset( $mrData['extractNumber'] ) )
|
|
{
|
|
$mrData['extractNumber'] = 0;
|
|
}
|
|
$offset = $mrData['extractNumber'];
|
|
|
|
if ( $zip->extract( \IPS\ROOT_PATH, $numberToDo, $offset ) === TRUE )
|
|
{
|
|
if ( isset( $mrData['tmpFileName'] ) )
|
|
{
|
|
@unlink( $mrData['tmpFileName'] );
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
$mrData['extractNumber'] += $numberToDo;
|
|
$numberOfFiles = $zip->numberOfFiles();
|
|
|
|
try
|
|
{
|
|
\IPS\Log::i( LOG_ERR )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Extracting files {$mrData['extractNumber']} / {$numberOfFiles}", 'auto_upgrade' );
|
|
}
|
|
catch( \Exception $ex ) { }
|
|
|
|
return array( $mrData, \IPS\Member::loggedIn()->language()->addToStack('delta_upgrade_extracting'), 100 / $numberOfFiles * $mrData['extractNumber'] );
|
|
}
|
|
}
|
|
catch ( \RuntimeException $e )
|
|
{
|
|
try
|
|
{
|
|
\IPS\Log::i( LOG_ERR )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Extract Failed", 'auto_upgrade' );
|
|
\IPS\Log::i( LOG_ERR )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( $e, 'auto_upgrade' );
|
|
}
|
|
catch( \Exception $ex ) { }
|
|
|
|
\IPS\Session\Admin::i()->log( ( $e->getCode() === \IPS\Archive\Exception::COULD_NOT_OPEN ) ? 'delta_upgrade_zip_fail' : ( $e->getCode() === \IPS\Archive\Exception::COULD_NOT_WRITE ? 'delta_upgrade_write_fail' : '' ) );
|
|
|
|
if ( isset( $mrData['tmpFileName'] ) )
|
|
{
|
|
@unlink( $mrData['tmpFileName'] );
|
|
}
|
|
|
|
return array( \IPS\Theme::i()->getTemplate('system')->upgradeDeltaFailed( $e->getCode(), isset( $data['key'] ) ? \IPS\Http\Url::ips("download/{$data['key']}") : NULL ) );
|
|
}
|
|
}
|
|
},
|
|
function()
|
|
{
|
|
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=system&controller=upgrade&check=1') );
|
|
} );
|
|
}
|
|
|
|
/* Run md5 check */
|
|
try
|
|
{
|
|
$files = \IPS\Application::md5Check();
|
|
if ( count( $files ) )
|
|
{
|
|
return \IPS\Theme::i()->getTemplate('system')->upgradeDeltaFailed( $files, isset( $data['key'] ) ? \IPS\Http\Url::ips("download/{$data['key']}") : NULL );
|
|
}
|
|
}
|
|
catch ( \Exception $e ) {}
|
|
|
|
/* Nope, we're good! */
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Upgrade
|
|
*
|
|
* @param array $data Wizard data
|
|
* @return string|array
|
|
*/
|
|
public function _upgrade( $data )
|
|
{
|
|
\IPS\Output::i()->redirect( 'upgrade/?adsess=' . \IPS\Request::i()->adsess );
|
|
}
|
|
} |