Seditio Source
Root |
./othercms/ips_4.3.4/admin/upgrade/extract.php
<!DOCTYPE html>
<html lang="en">
<head>
<title>Invision Community Update Extractor</title>
<style type='text/css'>@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.ipsProgressBar{width:50%;margin:auto;height:20px;overflow:hidden;background:#9c9c9c;background:-moz-linear-gradient(top,rgba(156,156,156,1) 0,rgba(180,180,180,1) 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,rgba(156,156,156,1)),color-stop(100%,rgba(180,180,180,1)));background:-webkit-linear-gradient(top,rgba(156,156,156,1) 0,rgba(180,180,180,1) 100%);background:-o-linear-gradient(top,rgba(156,156,156,1) 0,rgba(180,180,180,1) 100%);background:-ms-linear-gradient(top,rgba(156,156,156,1) 0,rgba(180,180,180,1) 100%);background:linear-gradient(to bottom,rgba(156,156,156,1) 0,rgba(180,180,180,1) 100%);border-radius:4px;box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.ipsProgressBar_animated .ipsProgressBar_progress{background-color:#5490c0;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px;-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.ipsProgressBar_progress{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,.25);background:#5490c0;position:relative;padding-left:6px}.ipsProgressBar_progress[data-progress]:after{position:absolute;right:5px;top:0;line-height:32px;color:#fff;content:attr(data-progress);display:block;font-weight:700}</style>
</head>
<body style="margin:0">
<?php
/**
 * @brief        Update Extractor
 * @author        <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
 * @copyright    (c) Invision Power Services, Inc.
 * @license        https://www.invisioncommunity.com/legal/standards/
 * @package        Invision Community
 * @since        31 Jul 2017
 */

// This file deliberately exists outside of the framework
// and MUST NOT call init.php

@ini_set('display_errors', 'off');

@require(
"../../system/3rd_party/pclzip/pclzip.lib.php" );

if (
file_exists( "../../constants.php" ) )
{
    require
"../../constants.php";
}
foreach ( array(
'FOLDER_PERMISSION_NO_WRITE' => 0755, 'FILE_PERMISSION_NO_WRITE' => 0644, 'TEMP_DIRECTORY' => sys_get_temp_dir() ) as $k => $v )
{
    if ( !
defined( $k ) )
    {
       
define( $k, $v );
    }
}

/**
 * Extractor Class
 */
class Extractor
{
    const
NUMBER_PER_GO = 20;
   
   
/**
     * @brief    File
     */
   
private $file;
   
   
/**
     * @brief    Root Directory
     */
   
private $container;
   
   
/**
     * @brief    PclZip Object
     */
   
private $zip;
   
   
/**
     * @brief    Zip Contents
     */
   
private $contents;
   
   
/**
     * @brief    FTP Connection
     */
   
private $ftp;
   
   
/**
     * @brief    SSH Connection
     */
   
private $ssh;
   
   
/**
     * @brief    SFTP Connection
     */
   
private $sftp;
   
   
/**
     * @brief    SFTP Directory
     */
   
private $sftpDir;
   
   
/**
     * Constructor
     *
     * @param    string    $file        Zip File
     * @param    string    $container    Root directory
     * @return    void
     */
   
public function __construct( $file, $container )
    {
        if ( !
$file or !$container )
        {
            throw new
Exception;
        }
       
       
$this->file = $file;
       
$this->container = $container . '/';
    }
   
   
/**
     * Security Check
     *
     * @param    string    $key    Security key
     * @return    void
     */
   
public function securityCheck( $key )
    {
        require
"../../conf_global.php";
        return
$key === md5( $INFO['board_start'] . $_GET['file'] . $INFO['sql_pass'] );
    }
   
   
/**
     * Establish FTP/SSH connection
     *
     * @param    array    $value    FTP/SSH Credentials
     * @return    void
     */
   
public function connectToFtp( $value )
    {
        if (
$value['protocol'] == 'sftp' )
        {
           
$this->ssh = ssh2_connect( $value['server'], $value['port'] );        
            if (
$this->ssh === FALSE )
            {
                throw new
Exception;
            }
            if ( !@
ssh2_auth_password( $this->ssh, $value['un'], $value['pw'] ) )
            {
                throw new
Exception;
            }
           
$this->sftp = @ssh2_sftp( $this->ssh );
            if (
$this->sftp === FALSE )
            {
                throw new
Exception;
            }
           
            if (
$value['path'] and !@ssh2_sftp_stat( $this->sftp, $value['path'] ) )
            {
                throw new
Exception;
            }
           
           
$this->sftpDir = ssh2_sftp_realpath( $this->sftp, $value['path'] ) . '/';
        }
        else
        {            
            if (
$value['protocol'] == 'ssl_ftp' )
            {
               
$this->ftp = @ftp_ssl_connect( $value['server'], $value['port'], 3 );
            }
            else
            {
               
$this->ftp = @ftp_connect( $value['server'], $value['port'], 3 );
            }
            if (
$this->ftp === FALSE )
            {
                throw new
Exception;
            }
            if ( !@
ftp_login( $this->ftp, $value['un'], $value['pw'] ) )
            {
                throw new
Exception;
            }
            if(
ftp_nlist( $this->ftp, '.' ) === FALSE )
            {
                @
ftp_pasv( $this->ftp, true );
            }
           
            if ( !@
ftp_chdir( $this->ftp, $value['path'] ) )
            {
                throw new
Exception;
            }
        }
    }
   
   
/**
     * Number of files
     *
     * @return    int
     */
   
public function numberOfFiles()
    {
       
$properties = $this->zip->properties();
        return
$properties['nb'];
    }
   
   
/**
     * Extract the files
     *
     * @param    int    $offset    Offset
     * @return    int
     */
   
public function extract( $offset )
    {
       
$this->zip = new PclZip( $this->file );
       
$this->contents = $this->zip->listContent();
        if ( !
$this->contents )
        {
            throw new
Exception;
        }
       
       
$done = 0;
        for (
$i = 0; $i < self::NUMBER_PER_GO; $i++ )
        {
           
$index = $offset + $i;
           
            if ( isset(
$this->contents[ $index ] ) )
            {
               
$this->_extractFile( $index );
               
$done++;
            }
            else
            {
                return
$done;
            }
        }
       
        return
$done;
    }
   
   
/**
     * Extract a particular file
     *
     * @param    int    $index    File index in zip
     * @return    void
     */
   
private function _extractFile( $index )
    {
       
/* Get the file */
       
$path = mb_substr( $this->contents[ $index ]['filename'], 0, mb_strlen( $this->container ) ) === $this->container ? mb_substr( $this->contents[ $index ]['filename'], mb_strlen( $this->container ) ) : $this->contents[ $index ]['filename'];
        if ( !
$path or mb_substr( $path, -1 ) === '/' or mb_substr( $path, 0, 1 ) === '.' or mb_substr( $path, 0, 9 ) === '__MACOSX/' )
        {
            return;
        }
       
       
/* Create a directory if needed */
       
$dir = dirname( $path );
       
$directories = array( $dir );
        while (
$dir != '.' )
        {
           
$dir = dirname( $dir );
            if (
$dir != '.' )
            {
               
$directories[] = $dir;
            }
        }
        foreach (
array_reverse( $directories ) as $dir )
        {
            if ( !
is_dir( "../../{$dir}" ) )
            {
                if (
$this->sftp )
                {
                    @
ssh2_sftp_mkdir( $this->sftp, $this->sftpDir . $dir );
                }
                if (
$this->ftp )
                {
                    @
ftp_mkdir( $this->ftp, $dir );
                }
                else
                {
                    @
mkdir( "../../{$dir}", FOLDER_PERMISSION_NO_WRITE );
                }
            }
        }
               
       
/* Write contents */
       
$contents = @$this->zip->extractByIndex( $index, \PCLZIP_OPT_EXTRACT_AS_STRING );
       
$contents = $contents[0]['content'];
        if (
$this->sftp or $this->ftp )
        {
           
$tmpFile = tempnam( TEMP_DIRECTORY, 'IPS' );
            \
file_put_contents( $tmpFile, $contents );
           
            if (
$this->sftp )
            {
                if ( @
ssh2_scp_send( $this->ssh, $tmpFile, $this->sftpDir . $path ) === FALSE )
                {
                    throw new \
Exception;
                }
            }
            else
            {
                if ( @
ftp_put( $this->ftp, $path, $tmpFile, FTP_BINARY ) === FALSE )
                {
                    throw new \
Exception;
                }
            }
           
            @
unlink( $tmpFile );
        }
        else
        {
           
/* Determine if the file exists (we'll want to know this later) */
           
$fileExists    = file_exists( "../../{$path}" );

           
$fh = @\fopen( "../../{$path}", 'w+' );
            if (
$fh === FALSE )
            {
               
$lastError = error_get_last();
                throw new
Exception( $lastError['message'] );
            }
            if ( @\
fwrite( $fh, $contents ) === FALSE )
            {
               
$lastError = error_get_last();
                throw new
Exception( $lastError['message'] );
            }
            else
            {
               
/* If the file existed before we started, we should clear it from opcache if opcache is enabled */
               
if( $fileExists )
                {
                    if (
function_exists( 'opcache_invalidate' ) )
                    {
                        @
opcache_invalidate( "../../{$path}" );
                    }
                }
               
/* Otherwise, we should set file permissions on the file if it's brand new in case server defaults to something odd */
               
else
                {
                    @
chmod( "../../{$path}", FILE_PERMISSION_NO_WRITE );
                }
            }
            @\
fclose( $fh );
        }
    }
}

/* ! Controller */
try
{
   
$extractor = new Extractor( isset( $_GET['file'] ) ? $_GET['file'] : NULL, isset( $_GET['container'] ) ? $_GET['container'] : '' );
   
   
/* Check this request came from the ACP */
   
if ( !$extractor->securityCheck( $_GET['key'] ) )
    {
        throw new
Exception;
    }
   
   
/* Establish an FTP connection if necessary */
   
if ( $_GET['ftp'] )
    {
       
$extractor->connectToFtp( $_GET['ftp'] );
    }
   
   
/* Extract a batch of files */
   
$i = isset( $_GET['i'] ) ? $_GET['i'] : 0;
   
$done = $extractor->extract( $i );
   
   
/* If we didn't extract anything, are we done? */
   
if ( !$done and $i >= $extractor->numberOfFiles() )
    {
        @
unlink( $_GET['file'] );
       
        if (
function_exists( 'opcache_reset' ) )
        {
            @
opcache_reset();
        }
       
        echo <<<HTML
<div class="ipsProgressBar ipsProgressBar_animated">
    <div class="ipsProgressBar_progress" style="width: 100%;"></div>
</div>
<script type='text/javascript'>parent.location = parent.location + '&check=1';</script><noscript><a href='index.php' target='_parent'>Click here to continue</a></noscript>
HTML;
    }
   
   
/* Nope, redirect to the next batch */
   
else
    {
       
$newI = $i + $extractor::NUMBER_PER_GO;
       
$percentComplete = round( 100 / $extractor->numberOfFiles() * $newI );
       
       
$properties = array(
           
'file'        => $_GET['file'],
           
'container'    => $_GET['container'],
           
'key'        => $_GET['key'],
           
'ftp'        => $_GET['ftp'],
           
'i'            => $newI,
        );
       
$url = "extract.php?" . http_build_query( $properties, '', '&' );
        echo <<<HTML
<div class="ipsProgressBar ipsProgressBar_animated">
    <div class="ipsProgressBar_progress" style="width:
{$percentComplete}%;"></div>
</div>
<noscript><a href='
{$url}' target='_parent'>Click here to continue</a></noscript>
<script type='text/javascript'>window.onload = function(){setTimeout(function(){window.location = '
{$url}';}, 50);};</script>
HTML;
    }
}
catch (
Exception $e )
{
    echo
"<script type='text/javascript'>parent.location = parent.location + '&fail=1';</script><noscript>An error occurred. Please visit the <a href='https://remoteservices.invisionpower.com/docs/client_area' target='_blank'>client area</a> to manually download the latest version. After uploading the files, <a href='index.php' target='_parent'>continue to the upgrader</a>.</noscript>";
    exit;
}
?>
</body>
</html>