Version 4.7.0
This commit is contained in:
1 parent
517a5e1f70
commit
8ba7d43898
1933 files changed
+65613
-11332
No files matched your search
+208
-5
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Invision Community Update Extractor</title>
|
||||
<style type='text/css'>body{font-family:BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.ipsProgressBar{width:50%;margin:auto;height:26px;overflow:hidden;background:rgb(237, 242, 247);background-image:linear-gradient(to bottom,rgba(23, 126, 201,0.1),rgba(23, 126, 201,0.1));border-radius:4px;}.ipsProgressBar_animated .ipsProgressBar_progress{background-color:rgb(23, 126, 201);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-size:40px 40px;animation:progress-bar-stripes 2s linear infinite}.ipsProgressBar_progress{display:flex;align-items:center;width:0;height:100%;font-size:12px;color:#ffffff;text-align:right;background:rgb(23, 126, 201);position:relative;white-space:nowrap;line-height:26px;text-indent:6px;padding-right:2px;}.ipsProgressBar>span:first-child{padding-left:7px;}.ipsProgressBar_progress[data-progress]:after{top:0;color:#fff;content:attr(data-progress);display:block;right:5px;}</style>
|
||||
<style type='text/css'>body{font-family:BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.ipsProgressBar{width:50%;margin:auto;height:26px;overflow:hidden;background:rgb(237, 242, 247);background-image:linear-gradient(to bottom,rgba(23, 126, 201,0.1),rgba(23, 126, 201,0.1));border-radius:4px;}.ipsProgressBar_animated .ipsProgressBar_progress{background-color:rgb(23, 126, 201);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-size:40px 40px;animation:progress-bar-stripes 2s linear infinite}.ipsProgressBar_progress{display:flex;align-items:center;width:0;height:100%;font-size:12px;color:#ffffff;text-align:right;background:rgb(23, 126, 201);position:relative;white-space:nowrap;line-height:26px;text-indent:6px;padding-right:2px;}.ipsProgressBar>span:first-child{padding-left:7px;}.ipsProgressBar_progress[data-progress]:after{top:0;color:#fff;content:attr(data-progress);display:block;right:5px;}@media (prefers-color-scheme: dark) { body{ background-color: rgb(45, 49, 57); } }</style>
|
||||
</head>
|
||||
<body style="margin:0">
|
||||
<?php
|
||||
@@ -26,7 +26,7 @@ if ( file_exists( "../../constants.php" ) )
|
||||
{
|
||||
require "../../constants.php";
|
||||
}
|
||||
foreach ( array( 'FOLDER_PERMISSION_NO_WRITE' => 0755, 'FILE_PERMISSION_NO_WRITE' => 0644, 'IPS_FILE_PERMISSION' => 0666, 'TEMP_DIRECTORY' => sys_get_temp_dir() ) as $k => $v )
|
||||
foreach ( [ 'FOLDER_PERMISSION_NO_WRITE' => 0755, 'FILE_PERMISSION_NO_WRITE' => 0644, 'IPS_FILE_PERMISSION' => 0666, 'TEMP_DIRECTORY' => sys_get_temp_dir(), 'TEXT_ENCRYPTION_KEY' => NULL ] as $k => $v )
|
||||
{
|
||||
if ( !\defined( $k ) )
|
||||
{
|
||||
@@ -80,6 +80,16 @@ class Extractor
|
||||
* @brief SFTP Directory
|
||||
*/
|
||||
private $sftpDir;
|
||||
|
||||
/**
|
||||
* @brief Database connection
|
||||
*/
|
||||
public $db;
|
||||
|
||||
/**
|
||||
* @brief Database prefix
|
||||
*/
|
||||
public $dbPrefix;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -109,7 +119,8 @@ class Extractor
|
||||
{
|
||||
require "../../conf_global.php";
|
||||
|
||||
$db = new mysqli( $INFO['sql_host'], $INFO['sql_user'], $INFO['sql_pass'], $INFO['sql_database'], !empty( $INFO['sql_port'] ) ? $INFO['sql_port'] : null, !empty( $INFO['sql_socket'] ) ? $INFO['sql_socket'] : null );
|
||||
$this->db = new mysqli( $INFO['sql_host'], $INFO['sql_user'], $INFO['sql_pass'], $INFO['sql_database'], !empty( $INFO['sql_port'] ) ? $INFO['sql_port'] : null, !empty( $INFO['sql_socket'] ) ? $INFO['sql_socket'] : null );
|
||||
$this->dbPrefix = $INFO['sql_tbl_prefix'] ?? '';
|
||||
|
||||
/* If the connection failed, do not continue */
|
||||
if( $error = mysqli_connect_error() )
|
||||
@@ -118,7 +129,7 @@ class Extractor
|
||||
}
|
||||
|
||||
/* Check that there is an upgrade in progress */
|
||||
$query = $db->query( "SELECT conf_value FROM {$INFO['sql_tbl_prefix']}core_sys_conf_settings WHERE conf_key='setup_in_progress'" );
|
||||
$query = $this->db->query( "SELECT conf_value FROM {$this->dbPrefix}core_sys_conf_settings WHERE conf_key='setup_in_progress'" );
|
||||
if( !$query )
|
||||
{
|
||||
return FALSE;
|
||||
@@ -378,6 +389,176 @@ class Extractor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypted - code from \IPS\Text\Encrypt
|
||||
*/
|
||||
class Encrypt
|
||||
{
|
||||
/**
|
||||
* Get Key
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function key()
|
||||
{
|
||||
require "../../conf_global.php";
|
||||
return \TEXT_ENCRYPTION_KEY ?: md5( $INFO['sql_pass'] . $INFO['sql_database'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cipher
|
||||
*/
|
||||
public $cipher;
|
||||
|
||||
/**
|
||||
* @brief IV
|
||||
*/
|
||||
protected $iv = NULL;
|
||||
|
||||
/**
|
||||
* @brief Tag
|
||||
*/
|
||||
protected $tag = NULL;
|
||||
|
||||
/**
|
||||
* @brief Hash of cipher
|
||||
*/
|
||||
protected $hmac = NULL;
|
||||
|
||||
/**
|
||||
* From plaintext
|
||||
*
|
||||
* @param string $plaintext Plaintext
|
||||
* @return static
|
||||
*/
|
||||
public static function fromPlaintext( $plaintext )
|
||||
{
|
||||
$obj = new static;
|
||||
|
||||
/* Try to use OpenSSL if it's available... */
|
||||
if ( \function_exists( 'openssl_get_cipher_methods' ) )
|
||||
{
|
||||
/* If GCM is available (PHP 7.1+), use that as if provides authenticated encryption natively */
|
||||
if ( \in_array( 'aes-128-gcm', openssl_get_cipher_methods() ) )
|
||||
{
|
||||
$obj->iv = openssl_random_pseudo_bytes( openssl_cipher_iv_length( 'aes-128-gcm' ) );
|
||||
$obj->cipher = openssl_encrypt( $plaintext, 'aes-128-gcm', static::key(), 0, $obj->iv, $obj->tag );
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/* Otherwise, use CBC and store the hash so we can do our own authentication when decrypting */
|
||||
elseif ( \in_array( 'aes-128-cbc', openssl_get_cipher_methods() ) )
|
||||
{
|
||||
$obj->iv = openssl_random_pseudo_bytes( openssl_cipher_iv_length( 'aes-128-cbc' ) );
|
||||
$obj->cipher = openssl_encrypt( $plaintext, 'aes-128-cbc', static::key(), OPENSSL_RAW_DATA, $obj->iv );
|
||||
$obj->hmac = hash_hmac( 'sha256', $obj->cipher, static::key(), TRUE );
|
||||
return $obj;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're still here, fallback to the PHP library */
|
||||
require_once '../../system/3rd_party/AES/AES.php';
|
||||
$obj->cipher = \AesCtr::encrypt( $plaintext, static::key(), 256 );
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* From plaintext
|
||||
*
|
||||
* @param string $cipher Cipher
|
||||
* @param string|null $iv The IV, or if null, will use the PHP library rather than built-in openssl_*() methods
|
||||
* @param string|null $tag The tag if using AES-128-GCM
|
||||
* @param string|null $hash The hash if using AES-128-CBC
|
||||
* @return static
|
||||
*/
|
||||
public static function fromCipher( $cipher, $iv = NULL, $tag = NULL, $hash = NULL )
|
||||
{
|
||||
$obj = new static;
|
||||
$obj->cipher = $cipher;
|
||||
$obj->iv = $iv;
|
||||
$obj->tag = $tag;
|
||||
$obj->hmac = $hash;
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* From tag
|
||||
*
|
||||
* @param string $tag Tag
|
||||
* @return static
|
||||
*/
|
||||
public static function fromTag( $tag )
|
||||
{
|
||||
if ( preg_match( '/^\[\!AES128GCM\[(.+?)\]\[(.+?)\]\[(.+?)\]\]/', $tag, $matches ) )
|
||||
{
|
||||
return static::fromCipher( $matches[1], hex2bin( $matches[2] ), hex2bin( $matches[3] ) );
|
||||
}
|
||||
elseif ( preg_match( '/^\[\!AES128CBC\[(.+?)\]\]/', $tag, $matches ) )
|
||||
{
|
||||
$cipher = base64_decode( $matches[1] );
|
||||
$ivLength = openssl_cipher_iv_length('aes-128-cbc');
|
||||
|
||||
return static::fromCipher( \substr( $cipher, $ivLength + 32 ), \substr( $cipher, 0, $ivLength ), NULL, \substr( $cipher, $ivLength, 32 ) );
|
||||
}
|
||||
elseif ( preg_match( '/^\[\!AES\[(.+?)\]\]/', $tag, $matches ) )
|
||||
{
|
||||
return static::fromCipher( $matches[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
return static::fromPlaintext( $tag );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap in a tag to use later with fromTag
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function tag()
|
||||
{
|
||||
if ( $this->tag )
|
||||
{
|
||||
return '[!AES128GCM[' . $this->cipher . '][' . bin2hex( $this->iv ) . '][' . bin2hex( $this->tag ) . ']]';
|
||||
}
|
||||
elseif ( $this->hmac )
|
||||
{
|
||||
return '[!AES128CBC[' . base64_encode( $this->iv . $this->hmac . $this->cipher ) . ']]';
|
||||
}
|
||||
else
|
||||
{
|
||||
return '[!AES[' . $this->cipher . ']]';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decript
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function decrypt()
|
||||
{
|
||||
if ( $this->tag )
|
||||
{
|
||||
return openssl_decrypt( $this->cipher, 'aes-128-gcm', static::key(), 0, $this->iv, $this->tag );
|
||||
}
|
||||
elseif ( $this->hmac )
|
||||
{
|
||||
$decrypted = openssl_decrypt( $this->cipher, 'aes-128-cbc', static::key(), OPENSSL_RAW_DATA, $this->iv );
|
||||
if ( hash_equals( $this->hmac, hash_hmac( 'sha256', $this->cipher, static::key(), TRUE ) ) )
|
||||
{
|
||||
return $decrypted;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
else
|
||||
{
|
||||
require_once '../../system/3rd_party/AES/AES.php';
|
||||
return \AesCtr::decrypt( $this->cipher, static::key(), 256 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to write a log file to disk
|
||||
*
|
||||
@@ -432,7 +613,29 @@ try
|
||||
/* Establish an FTP connection if necessary */
|
||||
if ( $_GET['ftp'] )
|
||||
{
|
||||
$extractor->connectToFtp( $_GET['ftp'] );
|
||||
/* Get encrypted FTP credentials */
|
||||
$query = $extractor->db->query( "SELECT conf_value FROM " . $extractor->dbPrefix . "core_sys_conf_settings WHERE conf_key='upgrade_ftp_details'" );
|
||||
if( !$query )
|
||||
{
|
||||
throw new \RuntimeException('Cannot find (S)FTP credentials');
|
||||
}
|
||||
|
||||
$ftpCredentials = $query->fetch_assoc()['conf_value'];
|
||||
if( empty( $ftpCredentials ) )
|
||||
{
|
||||
throw new \RuntimeException('Cannot load (S)FTP credentials');
|
||||
}
|
||||
|
||||
if ( \substr( $ftpCredentials, 0, 5 ) === '[!AES' )
|
||||
{
|
||||
$decodedFtpDetails = Encrypt::fromTag( $ftpCredentials )->decrypt();
|
||||
}
|
||||
else
|
||||
{
|
||||
$decodedFtpDetails = Encrypt::fromCipher( $ftpCredentials )->decrypt();
|
||||
}
|
||||
|
||||
$extractor->connectToFtp( json_decode( $decodedFtpDetails, TRUE ) );
|
||||
}
|
||||
|
||||
/* Extract a batch of files */
|
||||
|
||||
Reference in new issue
Block a user