403Webshell
Server IP : 89.248.107.232  /  Your IP : 216.73.217.70
Web Server : Apache
System : Linux host2.kasilh.com 5.14.0-687.36.1.el9_8.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Aug 7 05:40:49 EDT 2026 x86_64
User : seg ( 10005)
PHP Version : 7.4.33
Disable Function : opcache_get_status
MySQL : OFF  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /var/www/vhosts/seg-sa.es/serinco.es/wp-content/plugins/duplicator/installer/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/vhosts/seg-sa.es/serinco.es/wp-content/plugins/duplicator/installer/installer.tpl
<?php



/**

 * Bootstrap utility to exatract the core installer

 *

 * @package Duplicator\Installer

 *

 * Custom params

 *

 * [zipmode] to force extraction zip mode

 *      installer.php?zipmode=auto

 *      installer.php?zipmode=ziparchive

 *      installer.php?zipmode=shellexec

 *

 * [force-extract-installer] to force dup-installer folder overwrite

 *      installer.php?force-extract-installer=(1|on|yes)

 *

 * [dup_folder] to change dup-installer folder name

 *      installer.php?dup_folder=[custom_folder_name]

 *

 * [archive] to set custom archvie path location

 * can be fullpath with archive name or not

 *      installer.php?archive=[archive path]

 */



namespace {



    use Duplicator\Libs\DupArchive\DupArchiveExpandBasicEngine;



    $disabled_dirs = array(

        'backups-dup-lite',

        'wp-snapshots'

    );



    if (in_array(basename(dirname(__FILE__)), $disabled_dirs)) {

        die;

    }



    define('KB_IN_BYTES', 1024);

    define('MB_IN_BYTES', 1024 * KB_IN_BYTES);

    define('GB_IN_BYTES', 1024 * MB_IN_BYTES);

    define('DUPLICATOR_PHP_MAX_MEMORY', 4096 * MB_IN_BYTES);



    date_default_timezone_set('UTC'); // Some machines don’t have this set so just do it here.

    @ignore_user_abort(true);



    /**

     * Check if php.ini value is changeable

     *

     * @param string $setting php setting

     *

     * @return bool

     */

    function isIniValChangeable($setting)

    {

        static $ini_all;

        if (!isset($ini_all)) {

            $ini_all = false;

            // Sometimes `ini_get_all()` is disabled via the `disable_functions` option for "security purposes".

            if (function_exists('ini_get_all')) {

                $ini_all = ini_get_all();

            }

        }

        if (isset($ini_all[$setting]['access']) && ( INI_ALL === ( $ini_all[$setting]['access'] & 7 ) || INI_USER === ( $ini_all[$setting]['access'] & 7 ) )) {

            return true;

        }

        if (!is_array($ini_all)) {

            return true;

        }

        return false;

    }



    @set_time_limit(3600);

    if (isIniValChangeable('memory_limit')) {

        @ini_set('memory_limit', DUPLICATOR_PHP_MAX_MEMORY);

    }

    if (isIniValChangeable('max_input_time')) {

        @ini_set('max_input_time', '-1');

    }

    if (isIniValChangeable('pcre.backtrack_limit')) {

        @ini_set('pcre.backtrack_limit', PHP_INT_MAX);

    }

    if (isIniValChangeable('default_socket_timeout')) {

        @ini_set('default_socket_timeout', 3600);

    }



    LogHandler::init_error_handler();



    /**

     * Bootstrap

     */

    class DUPX_Bootstrap

    {

        //@@ Params get dynamically swapped when package is built

        const ARCHIVE_FILENAME   = '@@ARCHIVE@@';

        const ARCHIVE_SIZE       = '@@ARCHIVE_SIZE@@';

        const INSTALLER_DIR_NAME = 'dup-installer';

        const PACKAGE_HASH       = '@@PACKAGE_HASH@@';

        const SECONDARY_PACKAGE_HASH = '@@SECONDARY_PACKAGE_HASH@@';

        const VERSION            = '@@VERSION@@';



        const MINIMUM_PHP_VERSION = '5.3.8';



        const ZIP_MODE_AUTO    = 0;

        const ZIP_MODE_ARCHIVE = 1;

        const ZIP_MODE_SHELL   = 2;



        public $targetRoot            = null;

        public $origDupInstFolder     = null;

        public $targetDupInstFolder   = null;

        public $targetDupInst         = null;

        public $manualExtractFileName = null;

        public $isCustomDupFolder     = false;

        public $hasZipArchive         = false;

        public $hasShellExecUnzip     = false;

        public $mainInstallerURL;

        public $archiveExpectedSize   = 0;

        public $archiveActualSize     = 0;

        public $archiveRatio          = 0;



        /** @var self */

        private static $instance = null;



        /**

         * Instantiate the Bootstrap Object

         */

        private function __construct()

        {

            $this->setHTTPHeaders();

            $this->targetRoot        = self::setSafePath(dirname(__FILE__));

            // clean log file

            $this->log('', true);



            $archive_filepath = $this->getArchiveFilePath();

            $this->origDupInstFolder = self::INSTALLER_DIR_NAME;

            $this->targetDupInstFolder = filter_input(INPUT_GET, 'dup_folder', FILTER_SANITIZE_SPECIAL_CHARS, array(

                "options" => array(

                    "default" => self::INSTALLER_DIR_NAME,

                ),

                'flags'   => FILTER_FLAG_STRIP_HIGH));



            $this->isCustomDupFolder     = $this->origDupInstFolder !== $this->targetDupInstFolder;

            $this->targetDupInst         = $this->targetRoot . '/' . $this->targetDupInstFolder;

            $this->manualExtractFileName = 'dup-manual-extract__' . self::PACKAGE_HASH;



            if ($this->isCustomDupFolder) {

                $this->extractionTmpFolder = $this->getTempDir($this->targetRoot);

            } else {

                $this->extractionTmpFolder = $this->targetRoot;

            }



            DUPX_CSRF::init($this->targetDupInst, self::PACKAGE_HASH);



            //ARCHIVE_SIZE will be blank with a root filter so we can estimate

            //the default size of the package around 17.5MB (18088000)

            $archiveActualSize         = @file_exists($archive_filepath) ? @filesize($archive_filepath) : false;

            $archiveActualSize         = ($archiveActualSize !== false) ? $archiveActualSize : 0;

            $this->hasZipArchive       = class_exists('ZipArchive');

            $this->hasShellExecUnzip   = $this->getUnzipFilePath() != null ? true : false;

            $this->archiveExpectedSize = strlen(self::ARCHIVE_SIZE) ? self::ARCHIVE_SIZE : 0;

            $this->archiveActualSize   = $archiveActualSize;



            if ($this->archiveExpectedSize > 0) {

                $this->archiveRatio = (((1.0) * $this->archiveActualSize) / $this->archiveExpectedSize) * 100;

            } else {

                $this->archiveRatio = 100;

            }

        }



        /**

         *

         * @return self

         */

        public static function getInstance()

        {

            if (is_null(self::$instance)) {

                self::$instance = new self();

            }



            return self::$instance;

        }



        /**

         * Makes sure no caching mechanism is used during install

         *

         * @return void

         */

        private function setHTTPHeaders()

        {

            header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");

            header("Cache-Control: post-check=0, pre-check=0", false);

            header("Pragma: no-cache");

        }



        /**

         * Return temp dir

         *

         * @param string $path path string

         *

         * @return boolean|string

         */

        private function getTempDir($path)

        {

            $tempfile = tempnam($path, 'dup-installer_tmp_');

            if (file_exists($tempfile)) {

                unlink($tempfile);

                mkdir($tempfile);

                if (is_dir($tempfile)) {

                    return $tempfile;

                }

            }

            return false;

        }



        /**

         * Check php version

         *

         * @return void

         */

        public static function phpVersionCheck()

        {

            if (version_compare(PHP_VERSION, self::MINIMUM_PHP_VERSION, '>=')) {

                return true;

            }



            $match = null;

            if (preg_match("#^\d+(\.\d+)*#", PHP_VERSION, $match)) {

                $phpVersion = $match[0];

            } else {

                $phpVersion = PHP_VERSION;

            }

            ?><!DOCTYPE html>

            <html>

                <head>

                    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

                    <meta name="robots" content="noindex,nofollow">

                    <title>Duplicator - issue</title>

                </head>

                <body>

                    <div>

                        <h1>DUPLICATOR ISSUE: PHP <?php echo self::MINIMUM_PHP_VERSION; ?> REQUIRED</h1>

                        <p>

                            This server is running PHP: <b><?php echo $phpVersion; ?></b>. <i>A minimum of <b>PHP 

                            <?php echo self::MINIMUM_PHP_VERSION; ?></b> is required</i>.<br><br>

                            <b>Contact your hosting provider or server administrator and let them know you would like to upgrade your PHP version.</b>

                        </p>

                    </div>

                </body>

            </html>

            <?php

            die();

        }



        /**

         * Run the bootstrap process which includes checking for requirements and running

         * the extraction process

         *

         * @return null | string Returns null if the run was successful otherwise an error message

         */

        public function run()

        {

            date_default_timezone_set('UTC'); // Some machines don't have this set so just do it here



            $this->log('==DUPLICATOR INSTALLER BOOTSTRAP v' . self::VERSION . '==');

            $this->log('----------------------------------------------------');

            $this->log('Installer bootstrap start');



            $archive_filepath = $this->getArchiveFilePath();

            $archive_filename = self::ARCHIVE_FILENAME;



            $error               = null;



            $is_installer_file_valid = true;

            if (preg_match('/_([a-z0-9]{7})[a-z0-9]+_[0-9]{6}([0-9]{8})_archive.(?:zip|daf)$/', $archive_filename, $matches)) {

                $expected_package_hash = $matches[1] . '-' . $matches[2];

                if (self::PACKAGE_HASH != $expected_package_hash) {

                    $is_installer_file_valid = false;

                    $this->log("[ERROR] Installer and archive mismatch detected.");

                }

            } else {

                $this->log("[ERROR] Invalid archive file name.");

                $is_installer_file_valid = false;

            }



            if (false  === $is_installer_file_valid) {

                $error = "Installer and archive mismatch detected.

                        Ensure uncorrupted installer and matching archive are present.";

                return $error;

            }



            $extract_installer   = true;

            $extract_success     = false;

            $archiveExpectedEasy = $this->readableByteSize($this->archiveExpectedSize);

            $archiveActualEasy   = $this->readableByteSize($this->archiveActualSize);



            //$archive_extension = strtolower(pathinfo($archive_filepath)['extension']);

            $archive_extension   = strtolower(pathinfo($archive_filepath, PATHINFO_EXTENSION));

            $installer_dir_found = (

                file_exists($this->targetDupInst) &&

                file_exists($this->targetDupInst . "/main.installer.php") &&

                file_exists($this->targetDupInst . "/dup-archive__" . self::PACKAGE_HASH . ".txt")

            );



            $manual_extract_found = (

                $installer_dir_found &&

                file_exists($this->targetDupInst . "/" . $this->manualExtractFileName)

            );



            $isZip = ($archive_extension == 'zip');



            //MANUAL EXTRACTION NOT FOUND

            if (!$manual_extract_found) {

                //MISSING ARCHIVE FILE

                if (!file_exists($archive_filepath)) {

                    $this->log("[ERROR] Archive file not found!");

                    $archive_candidates = ($isZip) ? $this->getFilesWithExtension('zip') : $this->getFilesWithExtension('daf');

                    $candidate_count    = count($archive_candidates);

                    $candidate_html     = "- No {$archive_extension} files found -";



                    if ($candidate_count >= 1) {

                        $candidate_html = "<ol>";

                        foreach ($archive_candidates as $archive_candidate) {

                            $candidate_html .= '<li class="diff-list"> ' . $this->compareStrings($archive_filename, $archive_candidate) . '</li>';

                        }

                        $candidate_html .= "</ol>";

                    }



                    $error = "<style>.diff-list font { font-weight: bold; }</style>"

                        . "<b>Archive not found!</b> The required archive file must be present in the <i>'Extraction Path'</i> below. "

                        . "When the archive file name was created it was named with a secure file name.  This file name must be "

                        . "the <i>exact same</i> name as when it was created character for character.  Each archive file has a unique installer associated "

                        . "with it and must be used together.  See the list below for more options:<br/>"

                        . "<ul>"

                        . "<li>If the archive is not finished downloading please wait for it to complete.</li>"

                        . "<li>Rename the file to it original hash name.  See WordPress-Admin ❯ Packages ❯  Details. </li>"

                        . "<li>When downloading, both files both should be from the same package line. </li>"

                        . "<li>Also see: <a href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-050-q' target='_blank'>"

                        . "How to fix various errors that show up before step-1 of the installer?</a></li>"

                        . "</ul>";



                    return $error;

                }



                $archive_size = self::ARCHIVE_SIZE;



                // Sometimes the self::ARCHIVE_SIZE is ''.

                if (!empty($archive_size) && !self::checkInputValidInt(self::ARCHIVE_SIZE)) {

                    $no_of_bits = PHP_INT_SIZE * 8;

                    $error      = 'Current is a ' . $no_of_bits . '-bit SO. This archive is too large for ' . $no_of_bits . '-bit PHP.' . '<br>';

                    $this->log('[ERROR] ' . $error);

                    $error      .= 'Possibibles solutions:<br>';

                    $error      .= '- Use the file filters to get your package lower to support this server or try the package on a Linux server.' . '<br>';

                    $error      .= '- Perform a <a target="_blank" href="https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-015-q">' .

                        'Manual Extract Install</a>' . '<br>';



                    switch ($no_of_bits == 32) {

                        case 32:

                            $error .= '- Ask your host to upgrade the server to 64-bit PHP or install on another system has 64-bit PHP' . '<br>';

                            break;

                        case 64:

                            $error .= '- Ask your host to upgrade the server to 128-bit PHP or install on another system has 128-bit PHP' . '<br>';

                            break;

                    }



                    if (self::isWindows()) {

                        $error .= '- <a target="_blank" href="https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-052-q">' .

                            'Windows DupArchive extractor</a> to extract all files from the archive.' . '<br>';

                    }



                    return $error;

                }



                //SIZE CHECK ERROR

                if (($this->archiveRatio < 90) && ($this->archiveActualSize > 0) && ($this->archiveExpectedSize > 0)) {

                    $this->log(

                        "ERROR: The expected archive size should be around [{$archiveExpectedEasy}]. " .

                        "The actual size is currently [{$archiveActualEasy}]."

                    );

                    $this->log("ERROR: The archive file may not have fully been downloaded to the server");

                    $percent = round($this->archiveRatio);



                    $autochecked = isset($_POST['auto-fresh']) ? "checked='true'" : '';

                    $error       = "<b>Archive file size warning.</b><br/> The expected archive size is <b class='pass'>[{$archiveExpectedEasy}]</b>. "

                        . "Currently the archive size is <b class='fail'>[{$archiveActualEasy}]</b>. <br/>"

                        . "The archive file may have <b>not fully been uploaded to the server.</b>"

                        . "<ul>"

                        . "<li>Download the whole archive from the source website (open WordPress Admin &gt; Duplicator &gt; Packages) "

                        . "and validate that the file size is close to the expected size. </li>"

                        . "<li>Make sure to upload the whole archive file to the destination server.</li>"

                        . "<li>If the archive file is still uploading then please refresh this page to get an update on the currently uploaded file size.</li>"

                        . "</ul>";

                    return $error;

                }

            }



            if ($installer_dir_found) {

                // INSTALL DIRECTORY: Check if its setup correctly AND we are not in overwrite mode

                if (($extract_installer = filter_input(INPUT_GET, 'force-extract-installer', FILTER_VALIDATE_BOOLEAN))) {

                    $this->log("Manual extract found with force extract installer get parametr");

                } else {

                    $this->log("Manual extract found so not going to extract " . $this->targetDupInstFolder . " dir");

                }

            } else {

                $extract_installer = true;

            }



            // if ($extract_installer && file_exists($this->targetDupInst)) {

            if (file_exists($this->targetDupInst)) {

                $this->log("EXTRACT " . $this->targetDupInstFolder . " dir");

                $hash_pattern                 = '[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]';

                $file_patterns_with_hash_file = array(

                    // file pattern => hash file

                    'dup-archive__' . $hash_pattern . '.txt'        => 'dup-archive__' . self::PACKAGE_HASH . '.txt',

                    'dup-database__' . $hash_pattern . '.sql'       => 'dup-database__' . self::PACKAGE_HASH . '.sql',

                    'dup-installer-data__' . $hash_pattern . '.sql' => 'dup-installer-data__' . self::PACKAGE_HASH . '.sql',

                    'dup-installer-log__' . $hash_pattern . '.txt'  => 'dup-installer-log__' . self::PACKAGE_HASH . '.txt',

                    'dup-scan__' . $hash_pattern . '.json'          => 'dup-scan__' . self::PACKAGE_HASH . '.json',

                    'dup-scanned-dirs__' . $hash_pattern . '.txt'   => 'dup-scanned-dirs__' . self::PACKAGE_HASH . '.txt',

                    'dup-scanned-files__' . $hash_pattern . '.txt'  => 'dup-scanned-files__' . self::PACKAGE_HASH . '.txt',

                );

                foreach ($file_patterns_with_hash_file as $file_pattern => $hash_file) {

                    $globs = glob($this->targetDupInst . '/' . $file_pattern);

                    if (!empty($globs)) {

                        foreach ($globs as $glob) {

                            $file = basename($glob);

                            if ($file != $hash_file) {

                                if (unlink($glob)) {

                                    $this->log('Successfully deleted the file ' . $glob);

                                } else {

                                    $error .= '[ERROR] Error deleting the file ' . $glob . ' Please manually delete it and try again.';

                                    $this->log($error);

                                }

                            }

                        }

                    }

                }

            }



            //ATTEMPT EXTRACTION:

            //ZipArchive and Shell Exec

            if ($extract_installer) {

                $this->log("Ready to extract the installer");



                $this->log("Checking permission of destination folder");

                $destination = $this->targetRoot;

                if (!is_writable($destination)) {

                    $this->log("destination folder for extraction is not writable");

                    if (self::chmod($destination, 'u+rwx')) {

                        $this->log("Permission of destination folder changed to u+rwx");

                    } else {

                        $this->log("[ERROR] Permission of destination folder failed to change to u+rwx");

                    }

                }



                if (!is_writable($destination)) {

                    $this->log("WARNING: The {$destination} directory is not writable.");

                    $error = "NOTICE: The {$destination} directory is not writable on this server please talk to your host or server admin about making ";

                    $error .= "<a target='_blank' href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-055-q'>" .

                        "writable {$destination} directory</a> on this server. <br/>";

                    return $error;

                }



                if ($isZip) {

                    $zip_mode = $this->getZipMode();



                    if (($zip_mode == self::ZIP_MODE_AUTO) || ($zip_mode == self::ZIP_MODE_ARCHIVE) && class_exists('ZipArchive')) {

                        if ($this->hasZipArchive) {

                            $this->log("ZipArchive exists so using that");

                            $extract_success = $this->extractInstallerZipArchive($archive_filepath, $this->origDupInstFolder, $this->extractionTmpFolder);



                            if ($extract_success) {

                                $this->log('Successfully extracted with ZipArchive');

                            } else {

                                if (0 == $this->installer_files_found) {

                                    $error = "[ERROR] This archive is not properly formatted and does not contain a " . $this->origDupInstFolder .

                                        " directory. Please make sure you are attempting to install " .

                                        "the original archive and not one that has been reconstructed.";

                                    $this->log($error);

                                    return $error;

                                } else {

                                    $error = '[ERROR] Error extracting with ZipArchive. ';

                                    $this->log($error);

                                }

                            }

                        } else {

                            $this->log("WARNING: ZipArchive is not enabled.");

                            $error = "NOTICE: ZipArchive is not enabled on this server please talk to your host or server admin about enabling ";

                            $error .= "<a target='_blank' href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-060-q'>" .

                                "ZipArchive</a> on this server. <br/>";

                        }

                    }



                    if (!$extract_success) {

                        if (($zip_mode == self::ZIP_MODE_AUTO) || ($zip_mode == self::ZIP_MODE_SHELL)) {

                            $unzip_filepath = $this->getUnzipFilePath();

                            if ($unzip_filepath != null) {

                                $extract_success = $this->extractInstallerShellexec($archive_filepath, $this->origDupInstFolder, $this->extractionTmpFolder);

                                $this->log("Resetting perms of items in folder {$this->targetDupInstFolder}");

                                self::setPermsToDefaultR($this->targetDupInstFolder);

                                if ($extract_success) {

                                    $this->log('Successfully extracted with Shell Exec');

                                    $error = null;

                                } else {

                                    $error .= '[ERROR] Error extracting with Shell Exec. ' .

                                        'Please manually extract archive then choose Advanced > Manual Extract in installer.';

                                    $this->log($error);

                                }

                            } else {

                                $this->log('WARNING: Shell Exec Zip is not available');

                                $error .= "NOTICE: Shell Exec is not enabled on this server please talk to your host or server admin about enabling ";

                                $error .= "<a target='_blank' href='http://php.net/manual/en/function.shell-exec.php'>Shell Exec</a> " .

                                    "on this server or manually extract archive then choose Advanced > Manual Extract in installer.";

                            }

                        }

                    }



                    // If both ZipArchive and ShellZip are not available, Error message should be combined for both

                    if (!$extract_success && $zip_mode == self::ZIP_MODE_AUTO) {

                        $unzip_filepath = $this->getUnzipFilePath();

                        if (!class_exists('ZipArchive') && empty($unzip_filepath)) {

                            $this->log("WARNING: ZipArchive and Shell Exec are not enabled on this server.");

                            $error = "NOTICE: ZipArchive and Shell Exec are not enabled on this server please " .

                                "talk to your host or server admin about enabling ";

                            $error .= "<a target='_blank' href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-060-q'>ZipArchive</a> " .

                                "or <a target='_blank' href='http://php.net/manual/en/function.shell-exec.php'>Shell Exec</a> " .

                                "on this server or manually extract archive then choose Advanced > Manual Extract in installer.";

                        }

                    }

                } else {

                    try {

                        DupArchiveExpandBasicEngine::setCallbacks(

                            array($this, 'log'),

                            array($this, 'chmod'),

                            array($this, 'mkdir')

                        );

                        $offset = DupArchiveExpandBasicEngine::getExtraOffset($archive_filepath);

                        $this->log('Expand directory from offset ' . $offset);

                        DupArchiveExpandBasicEngine::expandDirectory(

                            $archive_filepath,

                            $this->origDupInstFolder,

                            $this->extractionTmpFolder,

                            false,

                            $offset

                        );

                        //In case of DupArchive just remove the manual extract check file

                        @unlink($this->extractionTmpFolder . "/" . $this->origDupInstFolder . "/" . $this->manualExtractFileName);

                    } catch (Exception $ex) {

                        $this->log("[ERROR] Error expanding installer subdirectory:" . $ex->getMessage());

                        throw $ex;

                    }

                }



                if ($this->isCustomDupFolder) {

                    $this->log("Move dup-installer folder to custom folder:" .  $this->targetDupInst);

                    if (file_exists($this->targetDupInst)) {

                        $this->log('Custom folder already exists so delete it');

                        if (self::rrmdir($this->targetDupInst) == false) {

                            throw new Exception('Can\'t remove custom target folder');

                        }

                    }

                    if (rename($this->extractionTmpFolder . '/' . $this->origDupInstFolder, $this->targetDupInst) === false) {

                        throw new Exception('Can\'t rename the tmp dup-installer folder');

                    }

                }



                $htaccessToRemove = $this->targetDupInst.'/.htaccess';

                if (is_file($htaccessToRemove) && is_writable($htaccessToRemove)) {

                    $this->log("Remove Htaccess in dup-installer folder");

                    @unlink($htaccessToRemove);

                }



                $is_apache = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false);

                $is_nginx  = (strpos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false);



                $sapi_type                   = php_sapi_name();

                $php_ini_data                = array(

                    'max_execution_time'     => 3600,

                    'max_input_time'         => -1,

                    'ignore_user_abort'      => 'On',

                    'post_max_size'          => '4096M',

                    'upload_max_filesize'    => '4096M',

                    'memory_limit'           => DUPLICATOR_PHP_MAX_MEMORY,

                    'default_socket_timeout' => 3600,

                    'pcre.backtrack_limit'   => 99999999999,

                );

                $sapi_type_first_three_chars = substr($sapi_type, 0, 3);

                if ('fpm' === $sapi_type_first_three_chars) {

                    $this->log("SAPI: FPM");

                    if ($is_apache) {

                        $this->log('Server: Apache');

                    } elseif ($is_nginx) {

                        $this->log('Server: Nginx');

                    }



                    if (($is_apache && function_exists('apache_get_modules') && in_array('mod_rewrite', apache_get_modules())) || $is_nginx) {

                        $htaccess_data = array();

                        foreach ($php_ini_data as $php_ini_key => $php_ini_val) {

                            if ($is_apache) {

                                $htaccess_data[] = 'SetEnv PHP_VALUE "' . $php_ini_key . ' = ' . $php_ini_val . '"';

                            } elseif ($is_nginx) {

                                if ('On' == $php_ini_val || 'Off' == $php_ini_val) {

                                    $htaccess_data[] = 'php_flag ' . $php_ini_key . ' ' . $php_ini_val;

                                } else {

                                    $htaccess_data[] = 'php_value ' . $php_ini_key . ' ' . $php_ini_val;

                                }

                            }

                        }



                        $htaccess_text      = implode("\n", $htaccess_data);

                        $htaccess_file_path = $this->targetDupInst . '/.htaccess';

                        $this->log("creating {$htaccess_file_path} with the content:");

                        $this->log($htaccess_text);

                        @file_put_contents($htaccess_file_path, $htaccess_text);

                    }

                } elseif ('cgi' === $sapi_type_first_three_chars || 'litespeed' === $sapi_type) {

                    if ('cgi' === $sapi_type_first_three_chars) {

                        $this->log("SAPI: CGI");

                    } else {

                        $this->log("SAPI: litespeed");

                    }

                    if (version_compare(phpversion(), 5.5) >= 0 && (!$is_apache || 'litespeed' === $sapi_type)) {

                        $ini_data = array();

                        foreach ($php_ini_data as $php_ini_key => $php_ini_val) {

                            $ini_data[] = $php_ini_key . ' = ' . $php_ini_val;

                        }

                        $ini_text      = implode("\n", $ini_data);

                        $ini_file_path = $this->targetDupInst . '/.user.ini';

                        $this->log("creating {$ini_file_path} with the content:");

                        $this->log($ini_text);

                        @file_put_contents($ini_file_path, $ini_text);

                    } else {

                        $this->log("No need to create " . $this->targetDupInstFolder . "/.htaccess or " . $this->targetDupInstFolder . "/.user.ini");

                    }

                } elseif ("apache2handler" === $sapi_type) {

                    $this->log("No need to create " . $this->targetDupInstFolder . "/.htaccess or " . $this->targetDupInstFolder . "/.user.ini");

                    $this->log("SAPI: apache2handler");

                }

                else {

                    $this->log("No need to create " . $this->targetDupInstFolder . "/.htaccess or " . $this->targetDupInstFolder . "/.user.ini");

                    $this->log("ERROR:  SAPI: Unrecognized");

                }

            } else {

                $this->log("NOTICE: Didn't need to extract the installer.");

            }



            if (empty($error)) {

                if ($this->isCustomDupFolder && file_exists($this->extractionTmpFolder)) {

                    rmdir($this->extractionTmpFolder);

                }



                $config_files              = glob($this->targetDupInst . '/dup-archive__*.txt');

                $config_file_absolute_path = array_pop($config_files);

                if (!file_exists($config_file_absolute_path)) {

                    $error = '<b>Archive config file not found in ' . $this->targetDupInstFolder . ' folder.</b> <br><br>';

                    return $error;

                }

            }



            $uri_start   = self::getCurrentUrl(false, false, 1);

            if ($error === null) {

                if (!file_exists($this->targetDupInst)) {

                    $error = 'Can\'t extract installer directory. ' .

                        'See <a target="_blank" href="https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-022-q">this FAQ item</a>' .

                        ' for details on how to resolve.</a>';

                }



                if ($error == null) {

                    $bootloader_name        = basename(__FILE__);

                    $this->mainInstallerURL = $uri_start . '/' . $this->targetDupInstFolder . '/main.installer.php';



                    $this->archive    = $archive_filepath;

                    $this->bootloader = $bootloader_name;



                    $this->fixInstallerPerms($this->mainInstallerURL);

                    // $this->mainInstallerURL = $this->mainInstallerURL . "?archive=$encoded_archive_path&bootloader=$bootloader_name&ctrl_action=ctrl-step1";

                    /*

                    if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])) {

                        $this->mainInstallerURL .= '?'.$_SERVER['QUERY_STRING'];

                    }*/



                    $this->log("DONE: No detected errors so redirecting to the main installer. Main Installer URI = {$this->mainInstallerURL}");

                }

            }



            return $error;

        }



        /**

         * Get current url

         *

         * @param bool $queryString       If true the query string will also be returned.

         * @param bool $requestUri        if true check request uri

         * @param int  $getParentDirLevel if 0 get current script name or parent folder, if 1 parent folder if 2 parent of parent folder ...

         *

         * @return void

         */

        public static function getCurrentUrl($queryString = true, $requestUri = false, $getParentDirLevel = 0)

        {

            // *** HOST

            if (isset($_SERVER['HTTP_X_ORIGINAL_HOST'])) {

                $host = $_SERVER['HTTP_X_ORIGINAL_HOST'];

            } else {

                $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']; //WAS SERVER_NAME and caused problems on some boxes

            }



            // *** PROTOCOL

            if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {

                $_SERVER ['HTTPS'] = 'on';

            }

            if (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] === 'https') {

                $_SERVER ['HTTPS'] = 'on';

            }

            if (isset($_SERVER['HTTP_CF_VISITOR'])) {

                $visitor = json_decode($_SERVER['HTTP_CF_VISITOR']);

                if ($visitor->scheme == 'https') {

                    $_SERVER ['HTTPS'] = 'on';

                }

            }

            $protocol = 'http' . ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) === 'on') ? 's' : '');



            if ($requestUri) {

                $serverUrlSelf = preg_replace('/\?.*$/', '', $_SERVER['REQUEST_URI']);

            } else {

                // *** SCRIPT NAME

                $serverUrlSelf = $_SERVER['SCRIPT_NAME'];

                for ($i = 0; $i < $getParentDirLevel; $i++) {

                    $serverUrlSelf = preg_match('/^[\\\\\/]?$/', dirname($serverUrlSelf)) ? '' : dirname($serverUrlSelf);

                }

            }



            // *** QUERY STRING

            $query = ($queryString && isset($_SERVER['QUERY_STRING']) && strlen($_SERVER['QUERY_STRING']) > 0 ) ? '?' . $_SERVER['QUERY_STRING'] : '';



            return $protocol . '://' . $host . $serverUrlSelf . $query;

        }



        /**

         * Attempts to set the 'dup-installer' directory permissions

         *

         * @return null

         */

        private function fixInstallerPerms()

        {

            $file_perms = 'u+rw';

            $dir_perms  = 'u+rwx';



            $installer_dir_path = $this->targetDupInstFolder;



            $this->setPerms($installer_dir_path, $dir_perms, false);

            $this->setPerms($installer_dir_path, $file_perms, true);

        }



        /**

         * Set the permissions of a given directory and optionally all files

         *

         * @param string $directory The full path to the directory where perms will be set

         * @param string $perms     The given permission sets to use such as '0755' or 'u+rw'

         * @param string $do_files  Also set the permissions of all the files in the directory

         *

         * @return null

         */

        private function setPerms($directory, $perms, $do_files)

        {

            if (!$do_files) {

                // If setting a directory hiearchy be sure to include the base directory

                $this->setPermsOnItem($directory, $perms);

            }



            $item_names = array_diff(scandir($directory), array('.', '..'));



            foreach ($item_names as $item_name) {

                $path = "$directory/$item_name";

                if (($do_files && is_file($path)) || (!$do_files && !is_file($path))) {

                    $this->setPermsOnItem($path, $perms);

                }

            }

        }



        /**

         * Set the permissions of a single directory or file

         *

         * @param string $path  The full path to the directory or file where perms will be set

         * @param string $perms The given permission sets to use such as '0755' or 'u+rw'

         *

         * @return bool     Returns true if the permission was properly set

         */

        private function setPermsOnItem($path, $perms)

        {

            if (($result = self::chmod($path, $perms)) === false) {

                $this->log("ERROR: Couldn't set permissions of $path<br/>");

            } else {

                $this->log("Set permissions of $path<br/>");

            }

            return $result;

        }



        /**

         * Compare two strings and return html text which represts diff

         *

         * @param string $oldString old string

         * @param string $newString new string

         *

         * @return string Returns html text

         */

        private function compareStrings($oldString, $newString)

        {

            $ret = '';

            for ($i = 0; isset($oldString[$i]) || isset($newString[$i]); $i++) {

                if (!isset($oldString[$i])) {

                    $ret .= '<font color="red">' . $newString[$i] . '</font>';

                    continue;

                }

                for ($char = 0; isset($oldString[$i][$char]) || isset($newString[$i][$char]); $char++) {

                    if (!isset($oldString[$i][$char])) {

                        $ret .= '<font color="red">' . substr($newString[$i], $char) . '</font>';

                        break;

                    } elseif (!isset($newString[$i][$char])) {

                        break;

                    }



                    if (ord($oldString[$i][$char]) != ord($newString[$i][$char])) {

                        $ret .= '<font color="red">' . $newString[$i][$char] . '</font>';

                    } else {

                        $ret .= $newString[$i][$char];

                    }

                }

            }

            return $ret;

        }



        /**

         * Logs a string to the dup-installer-bootlog__[HASH].txt file

         *

         * @param string $s         The string to log to the log file

         * @param bool   $deleteOld if true delete old file

         *

         * @return boog|int This function returns the number of bytes that were written to the file, or FALSE on failure.

         */

        public function log($s, $deleteOld = false)

        {

            static $logfile = null;

            if (is_null($logfile)) {

                $logfile = $this->getBootLogFilePath();

            }

            if ($deleteOld && file_exists($logfile)) {

                @unlink($logfile);

            }

            $timestamp = date('M j H:i:s');

            return @file_put_contents($logfile, '[' . $timestamp . '] ' . self::postprocessLog($s) . "\n", FILE_APPEND);

        }



        /**

         * get boot log file name the dup-installer-bootlog__[HASH].txt file

         *

         * @return string

         */

        public function getBootLogFilePath()

        {

            return $this->targetRoot . '/dup-installer-bootlog__' . self::SECONDARY_PACKAGE_HASH . '.txt';

        }



        /**

         * Post process log and remove hash string

         *

         * @param string $str string

         *

         * @return string

         */

        protected static function postprocessLog($str)

        {

            return str_replace(array(

                self::getArchiveFileHash(),

                self::PACKAGE_HASH,

                self::SECONDARY_PACKAGE_HASH

                ), '[HASH]', $str);

        }



        /**

         * Return archive file hash

         *

         * @return string

         */

        public static function getArchiveFileHash()

        {

            static $fileHash = null;

            if (is_null($fileHash)) {

                $fileHash = preg_replace('/^.+_([a-z0-9]+)_[0-9]{14}_archive\.(?:daf|zip)$/', '$1', self::ARCHIVE_FILENAME);

            }

            return $fileHash;

        }



        /**

         * Extraxt installer

         *

         * @param string $archive_filepath  The path to the archive file.

         * @param string $origDupInstFolder relative folder in archive

         * @param string $destination       destination folder

         * @param bool   $checkSubFolder    check if is in subfolder

         *

         * @return bool Returns true if the data was properly extracted

         */

        private function extractInstallerZipArchive($archive_filepath, $origDupInstFolder, $destination, $checkSubFolder = false)

        {

            $success              = true;

            $zipArchive           = new ZipArchive();

            $subFolderArchiveList = array();



            if (($zipOpenRes = $zipArchive->open($archive_filepath)) === true) {

                $this->log("Successfully opened archive file.");

                $folder_prefix = $origDupInstFolder . '/';

                $this->log("Extracting all files from archive within " . $origDupInstFolder);



                $installer_files_found = 0;



                for ($i = 0; $i < $zipArchive->numFiles; $i++) {

                    $stat = $zipArchive->statIndex($i);

                    if ($checkSubFolder == false) {

                        $filenameCheck = $stat['name'];

                        $filename      = $stat['name'];

                        $tmpSubFolder  = null;

                    } else {

                        $safePath = rtrim(self::setSafePath($stat['name']), '/');

                        $tmpArray = explode('/', $safePath);



                        if (count($tmpArray) < 2) {

                            continue;

                        }



                        $tmpSubFolder  = $tmpArray[0];

                        array_shift($tmpArray);

                        $filenameCheck = implode('/', $tmpArray);

                        $filename      = $stat['name'];

                    }





                    if ($this->startsWith($filenameCheck, $folder_prefix)) {

                        $installer_files_found++;



                        if (!empty($tmpSubFolder) && !in_array($tmpSubFolder, $subFolderArchiveList)) {

                            $subFolderArchiveList[] = $tmpSubFolder;

                        }



                        if (basename($filename) === $this->manualExtractFileName) {

                            $this->log("Skipping manual extract file: {$filename}");

                            continue;

                        }



                        if ($zipArchive->extractTo($destination, $filename) === true) {

                            $this->log("Success: {$filename} >>> {$destination}");

                        } else {

                            $this->log("[ERROR] Error extracting {$filename} from archive archive file");

                            $success = false;

                            break;

                        }

                    }

                }



                if ($checkSubFolder && count($subFolderArchiveList) !== 1) {

                    $this->log("Error: Multiple dup subfolder archive");

                    $success = false;

                } else {

                    if ($checkSubFolder) {

                        $this->moveUpfromSubFolder($destination . '/' . $subFolderArchiveList[0], true);

                    }



                    $lib_directory     = $destination . '/' . $origDupInstFolder . '/lib';

                    $snaplib_directory = $lib_directory . '/snaplib';



                    // If snaplib files aren't present attempt to extract and copy those

                    if (!file_exists($snaplib_directory)) {

                        $folder_prefix = 'snaplib/';

                        $destination   = $lib_directory;



                        for ($i = 0; $i < $zipArchive->numFiles; $i++) {

                            $stat     = $zipArchive->statIndex($i);

                            $filename = $stat['name'];



                            if ($this->startsWith($filename, $folder_prefix)) {

                                $installer_files_found++;



                                if ($zipArchive->extractTo($destination, $filename) === true) {

                                    $this->log("Success: {$filename} >>> {$destination}");

                                } else {

                                    $this->log("[ERROR] Error extracting {$filename} from archive archive file");

                                    $success = false;

                                    break;

                                }

                            }

                        }

                    }

                }



                if ($zipArchive->close() === true) {

                    $this->log("Successfully closed archive file");

                } else {

                    $this->log("[ERROR] Problem closing archive file");

                    $success = false;

                }



                if ($success != false && $installer_files_found < 10) {

                    if ($checkSubFolder) {

                        $this->log("[ERROR] Couldn't find the installer directory in the archive!");

                        $success = false;

                    } else {

                        $this->log("[ERROR] Couldn't find the installer directory in archive root! Check subfolder");

                        $this->extractInstallerZipArchive($archive_filepath, $origDupInstFolder, $destination, true);

                    }

                }

            } else {

                $this->log("[ERROR] Couldn't open archive archive file with ZipArchive CODE[" . $zipOpenRes . "]");

                $success = false;

            }



            return $success;

        }



        /**

         * return true if current SO is windows

         *

         * @staticvar bool $isWindows

         * @return bool

         */

        public static function isWindows()

        {

            static $isWindows = null;

            if (is_null($isWindows)) {

                $isWindows = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');

            }

            return $isWindows;

        }



        /**

         * return current SO path path len

         * @staticvar int $maxPath

         * @return int

         */

        public static function maxPathLen()

        {

            static $maxPath = null;

            if (is_null($maxPath)) {

                if (defined('PHP_MAXPATHLEN')) {

                    $maxPath = PHP_MAXPATHLEN;

                } else {

                    // for PHP < 5.3.0

                    $maxPath = self::isWindows() ? 260 : 4096;

                }

            }

            return $maxPath;

        }



        /**

         * @param string $directory Path for folder to set perms

         *

         * @return void

         */

        public static function setPermsToDefaultR($directory)

        {

            $dir      = new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS);

            $iterator = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);

            // Default permissions

            $defaultFilePermission = 0666 & ~umask();

            $defaultDirPermission  = 0777 & ~umask();



            foreach ($iterator as $item) {

                if ($item->isFile()) {

                    self::chmod($item->getPathname(), $defaultFilePermission);

                }



                if ($item->isDir()) {

                    self::chmod($item->getPathname(), $defaultDirPermission);

                }

            }

        }



        /**

         * this function make a chmod only if the are different from perms input and if chmod function is enabled

         *

         * this function handles the variable MODE in a way similar to the chmod of lunux

         * So the MODE variable can be

         * 1) an octal number (0755)

         * 2) a string that defines an octal number ("644")

         * 3) a string with the following format [ugoa]*([-+=]([rwx]*)+

         *

         * examples

         * u+rw         add read and write at the user

         * u+rw,uo-wx   add read and write ad the user and remove wx at groupd and other

         * a=rw         is equal at 666

         * u=rwx,go-rwx is equal at 700

         *

         * @param string     $file file path

         * @param int|string $mode mode

         *

         * @return boolean

         */

        public static function chmod($file, $mode)

        {

            if (!file_exists($file)) {

                return false;

            }



            $octalMode = 0;



            if (is_int($mode)) {

                $octalMode = $mode;

            } elseif (is_string($mode)) {

                $mode = trim($mode);

                if (preg_match('/([0-7]{1,3})/', $mode)) {

                    $octalMode = intval(('0' . $mode), 8);

                } elseif (preg_match_all('/(a|[ugo]{1,3})([-=+])([rwx]{1,3})/', $mode, $gMatch, PREG_SET_ORDER)) {

                    if (!function_exists('fileperms')) {

                        return false;

                    }



                    // start by file permission

                    $octalMode = (fileperms($file) & 0777);



                    foreach ($gMatch as $matches) {

                        // [ugo] or a = ugo

                        $group = $matches[1];

                        if ($group === 'a') {

                            $group = 'ugo';

                        }

                        // can be + - =

                        $action = $matches[2];

                        // [rwx]

                        $gPerms = $matches[3];



                        // reset octal group perms

                        $octalGroupMode = 0;



                        // Init sub perms

                        $subPerm = 0;

                        $subPerm += strpos($gPerms, 'x') !== false ? 1 : 0; // mask 001

                        $subPerm += strpos($gPerms, 'w') !== false ? 2 : 0; // mask 010

                        $subPerm += strpos($gPerms, 'r') !== false ? 4 : 0; // mask 100



                        $ugoLen = strlen($group);



                        if ($action === '=') {

                            // generate octal group permsissions and ugo mask invert

                            $ugoMaskInvert = 0777;

                            for ($i = 0; $i < $ugoLen; $i++) {

                                switch ($group[$i]) {

                                    case 'u':

                                        $octalGroupMode = $octalGroupMode | $subPerm << 6; // mask xxx000000

                                        $ugoMaskInvert  = $ugoMaskInvert & 077;

                                        break;

                                    case 'g':

                                        $octalGroupMode = $octalGroupMode | $subPerm << 3; // mask 000xxx000

                                        $ugoMaskInvert  = $ugoMaskInvert & 0707;

                                        break;

                                    case 'o':

                                        $octalGroupMode = $octalGroupMode | $subPerm; // mask 000000xxx

                                        $ugoMaskInvert  = $ugoMaskInvert & 0770;

                                        break;

                                }

                            }

                            // apply = action

                            $octalMode = $octalMode & ($ugoMaskInvert | $octalGroupMode);

                        } else {

                            // generate octal group permsissions

                            for ($i = 0; $i < $ugoLen; $i++) {

                                switch ($group[$i]) {

                                    case 'u':

                                        $octalGroupMode = $octalGroupMode | $subPerm << 6; // mask xxx000000

                                        break;

                                    case 'g':

                                        $octalGroupMode = $octalGroupMode | $subPerm << 3; // mask 000xxx000

                                        break;

                                    case 'o':

                                        $octalGroupMode = $octalGroupMode | $subPerm; // mask 000000xxx

                                        break;

                                }

                            }

                            // apply + or - action

                            switch ($action) {

                                case '+':

                                    $octalMode = $octalMode | $octalGroupMode;

                                    break;

                                case '-':

                                    $octalMode = $octalMode & ~$octalGroupMode;

                                    break;

                            }

                        }

                    }

                }

            }



            // if input permissions are equal at file permissions return true without performing chmod

            if (function_exists('fileperms') && $octalMode === (fileperms($file) & 0777)) {

                return true;

            }



            if (!function_exists('chmod')) {

                return false;

            }



            return @chmod($file, $octalMode);

        }



        /**

         * Check if input is  valid int

         *

         * @param mixed $input input string or number

         *

         * @return bool

         */

        public static function checkInputValidInt($input)

        {

            return (filter_var($input, FILTER_VALIDATE_INT) === 0 || filter_var($input, FILTER_VALIDATE_INT));

        }



        /**

         * this function creates a folder if it does not exist and performs a chmod.

         * it is different from the normal mkdir function to which an umask is applied to the input permissions.

         *

         * this function handles the variable MODE in a way similar to the chmod of lunux

         * So the MODE variable can be

         * 1) an octal number (0755)

         * 2) a string that defines an octal number ("644")

         * 3) a string with the following format [ugoa]*([-+=]([rwx]*)+

         *

         * @param string     $path      folder path

         * @param int|string $mode      mode permissions

         * @param bool       $recursive Allows the creation of nested directories specified in the pathname. Default to false.

         * @param resource   $context   not used for windows bug

         *

         * @return boolean bool TRUE on success or FALSE on failure.

         *

         * @todo check recursive true and multiple chmod

         */

        public static function mkdir($path, $mode = 0777, $recursive = false, $context = null)

        {

            if (strlen($path) > self::maxPathLen()) {

                throw new Exception('Skipping a file that exceeds allowed max path length [' . self::maxPathLen() . ']. File: ' . $filepath);

            }



            if (!file_exists($path)) {

                if (!function_exists('mkdir')) {

                    return false;

                }

                if (!@mkdir($path, 0777, $recursive)) {

                    return false;

                }

            }



            return self::chmod($path, $mode);

        }



        /**

         * move all folder content up to parent

         *

         * @param string  $subFolderName   full path

         * @param boolean $deleteSubFolder if true delete subFolder after moved all

         *

         * @return boolean

         */

        private function moveUpfromSubFolder($subFolderName, $deleteSubFolder = false)

        {

            if (!is_dir($subFolderName)) {

                return false;

            }



            $parentFolder = dirname($subFolderName);

            if (!is_writable($parentFolder)) {

                return false;

            }



            $success = true;

            if (($subList = glob(rtrim($subFolderName, '/') . '/*', GLOB_NOSORT)) === false) {

                $this->log("[ERROR] Problem glob folder " . $subFolderName);

                return false;

            } else {

                foreach ($subList as $cName) {

                    $destination = $parentFolder . '/' . basename($cName);

                    if (file_exists($destination)) {

                        $success = self::rrmdir($destination);

                    }



                    if ($success) {

                        $success = rename($cName, $destination);

                    } else {

                        break;

                    }

                }



                if ($success && $deleteSubFolder) {

                    $success = self::rrmdir($subFolderName, true);

                }

            }



            if (!$success) {

                $this->log("[ERROR] Problem om moveUpfromSubFolder subFolder:" . $subFolderName);

            }



            return $success;

        }



        /**

         * Extracts only the 'dup-installer' files using Shell-Exec Unzip

         *

         * @param string $archive_filepath  The path to the archive file.

         * @param string $origDupInstFolder dup-installer folder

         * @param string $destination       destination folder

         *

         * @return bool

         */

        private function extractInstallerShellexec($archive_filepath, $origDupInstFolder, $destination)

        {

            $success        = false;

            $this->log("Attempting to use Shell Exec");

            $unzip_filepath = $this->getUnzipFilePath();



            if ($unzip_filepath != null) {

                $unzip_command = "$unzip_filepath -q $archive_filepath " .

                    $origDupInstFolder . '/* -d ' . $destination . ' -x ' .

                    $origDupInstFolder . '/' . $this->manualExtractFileName . ' 2>&1';

                $this->log("Executing $unzip_command");

                $stderr        = shell_exec($unzip_command);



                $lib_directory     = $destination . '/' . $origDupInstFolder . '/lib';

                $snaplib_directory = $lib_directory . '/snaplib';



                // If snaplib files aren't present attempt to extract and copy those

                if (!file_exists($snaplib_directory)) {

                    $local_lib_directory = $destination . '/snaplib';

                    $unzip_command       = "$unzip_filepath -q $archive_filepath snaplib/* -d '.$destination.' 2>&1";



                    $this->log("Executing unzip command");

                    $stderr .= shell_exec($unzip_command);

                    self::mkdir($lib_directory, 'u+rwx');

                    rename($local_lib_directory, $snaplib_directory);

                }



                if ($stderr == '') {

                    $this->log("Shell exec unzip succeeded");

                    $success = true;

                } else {

                    $this->log("[ERROR] Shell exec unzip failed. Output={$stderr}");

                }

            }



            return $success;

        }



        /**

         * Attempts to get the archive file path

         *

         * @return string   The full path to the archive file

         */

        private function getArchiveFilePath()

        {

            if (($archive_filepath = filter_input(INPUT_GET, 'archive', FILTER_SANITIZE_SPECIAL_CHARS)) != false) {

                if (is_dir($archive_filepath) && file_exists($archive_filepath . '/' . self::ARCHIVE_FILENAME)) {

                    $archive_filepath = $archive_filepath . '/' . self::ARCHIVE_FILENAME;

                } else {

                    $archive_filepath = $archive_filepath;

                }

            } else {

                $archive_filepath = $this->targetRoot . '/' . self::ARCHIVE_FILENAME;

            }



            if (($realPath = realpath($archive_filepath)) !== false) {

                return $realPath;

            } else {

                return $archive_filepath;

            }

        }



        /**

         * Gets the enum type that should be used

         *

         * @return int Returns the current zip mode enum

         */

        private function getZipMode()

        {

            $zip_mode = self::ZIP_MODE_AUTO;



            if (isset($_GET['zipmode'])) {

                $zipmode_string = $_GET['zipmode'];

                $this->log("Unzip mode specified in querystring: $zipmode_string");



                switch ($zipmode_string) {

                    case 'autounzip':

                        $zip_mode = self::ZIP_MODE_AUTO;

                        break;

                    case 'ziparchive':

                        $zip_mode = self::ZIP_MODE_ARCHIVE;

                        break;

                    case 'shellexec':

                        $zip_mode = self::ZIP_MODE_SHELL;

                        break;

                }

            }



            return $zip_mode;

        }



        /**

         * Checks to see if a string starts with specific characters

         *

         * @param string $haystack haystack

         * @param string $needle   needle

         *

         * @return bool

         */

        private function startsWith($haystack, $needle)

        {

            return $needle === "" || strrpos($haystack, $needle, - strlen($haystack)) !== false;

        }



        /**

         * Checks to see if the server supports issuing commands to shell_exex

         *

         * @return bool     Returns true shell_exec can be ran on this server

         */

        public function hasShellExec()

        {

            $cmds = array('shell_exec', 'escapeshellarg', 'escapeshellcmd', 'extension_loaded');



            //Function disabled at server level

            if (array_intersect($cmds, array_map('trim', explode(',', @ini_get('disable_functions'))))) {

                return false;

            }



            //Suhosin: http://www.hardened-php.net/suhosin/

            //Will cause PHP to silently fail

            if (extension_loaded('suhosin')) {

                $suhosin_ini = @ini_get("suhosin.executor.func.blacklist");

                if (array_intersect($cmds, array_map('trim', explode(',', $suhosin_ini)))) {

                    return false;

                }

            }



            if (! function_exists('shell_exec')) {

                return false;

            }



            // Can we issue a simple echo command?

            if (!@shell_exec('echo duplicator')) {

                return false;

            }



            return true;

        }



        /**

         * Gets the possible system commands for unzip on Linux

         *

         * @return string       Returns unzip file path that can execute the unzip command

         */

        public function getUnzipFilePath()

        {

            $filepath = null;



            if ($this->hasShellExec()) {

                if (shell_exec('hash unzip 2>&1') == null) {

                    $filepath = 'unzip';

                } else {

                    $possible_paths = array(

                        '/usr/bin/unzip',

                        '/opt/local/bin/unzip',

                        '/bin/unzip',

                        '/usr/local/bin/unzip',

                        '/usr/sfw/bin/unzip',

                        '/usr/xdg4/bin/unzip',

                        '/opt/bin/unzip',

                        // RSR TODO put back in when we support shellexec on windows,

                    );



                    foreach ($possible_paths as $path) {

                        if (file_exists($path)) {

                            $filepath = $path;

                            break;

                        }

                    }

                }

            }



            return $filepath;

        }



        /**

         * Display human readable byte sizes such as 150MB

         *

         * @param int $size The size in bytes

         *

         * @return string A readable byte size format such as 100MB

         */

        public function readableByteSize($size)

        {

            try {

                $units = array('B', 'KB', 'MB', 'GB', 'TB');

                for ($i = 0; $size >= 1024 && $i < 4; $i++) {

                    $size  /= 1024;

                }

                return round($size, 2) . $units[$i];

            } catch (Exception $e) {

                return "n/a";

            }

        }



        /**

         * Returns an array of zip files found in the current executing directory

         *

         * @param string $extension extenstion file

         *

         * @return array of zip files

         */

        public function getFilesWithExtension($extension)

        {

            $files = array();

            foreach (glob("*.{$extension}") as $name) {

                if (file_exists($name)) {

                    $files[] = $name;

                }

            }

            if (count($files) > 0) {

                return $files;

            }

            //FALL BACK: Windows XP has bug with glob,

            //add secondary check for PHP lameness

            if (($dh = opendir($this->targetRoot))) {

                while (false !== ($name = readdir($dh))) {

                    $ext = substr($name, strrpos($name, '.') + 1);

                    if (in_array($ext, array($extension))) {

                        $files[] = $name;

                    }

                }

                closedir($dh);

            }



            return $files;

        }



        /**

         * Safely remove a directory and recursively files and directory upto multiple sublevels

         *

         * @param string $path The full path to the directory to remove

         *

         * @return bool Returns true if all content was removed

         */

        public static function rrmdir($path)

        {

            if (is_dir($path)) {

                if (($dh = opendir($path)) === false) {

                    return false;

                }

                while (($object = readdir($dh)) !== false) {

                    if ($object == "." || $object == "..") {

                        continue;

                    }

                    if (!self::rrmdir($path . "/" . $object)) {

                        closedir($dh);

                        return false;

                    }

                }

                closedir($dh);

                return @rmdir($path);

            } else {

                if (is_writable($path)) {

                    return @unlink($path);

                } else {

                    return false;

                }

            }

        }



        /**

         *  Makes path safe for any OS for PHP

         *

         *  Paths should ALWAYS READ be "/"

         *      uni:  /home/path/file.txt

         *      win:  D:/home/path/file.txt

         *

         *  @param string $path TThe path to make safe

         *

         *  @return string The original $path with a with all slashes facing '/'.

         */

        public static function setSafePath($path)

        {

            return str_replace("\\", "/", $path);

        }

    }



    class LogHandler

    {



        /** @var bool */

        private static $initialized = false;



        /**

         * This function only initializes the error handler the first time it is called

         *

         * @return void

         */

        public static function init_error_handler()

        {

            if (!self::$initialized) {

                @set_error_handler(array(__CLASS__, 'error'));

                @register_shutdown_function(array(__CLASS__, 'shutdown'));

                self::$initialized = true;

            }

        }



        /**

         * Error handler

         *

         * @param  integer $errno   Error level

         * @param  string  $errstr  Error message

         * @param  string  $errfile Error file

         * @param  integer $errline Error line

         * @return void

         */

        public static function error($errno, $errstr, $errfile, $errline)

        {

            switch ($errno) {

                case E_ERROR:

                    $log_message = self::getMessage($errno, $errstr, $errfile, $errline);

                    if (DUPX_Bootstrap::getInstance()->log($log_message) === false) {

                        $log_message = "Can\'t wrinte logfile\n\n" . $log_message;

                    }

                    die('<pre>' . htmlspecialchars($log_message) . '</pre>');

                    break;

                case E_NOTICE:

                case E_WARNING:

                default:

                    $log_message = self::getMessage($errno, $errstr, $errfile, $errline);

                    DUPX_Bootstrap::getInstance()->log($log_message);

                    break;

            }

        }



        /**

         * Get message from error

         *

         * @param int    $errno   errno

         * @param string $errstr  message

         * @param string $errfile file

         * @param int    $errline line

         *

         * @return string

         */

        private static function getMessage($errno, $errstr, $errfile, $errline)

        {

            $result = '[PHP ERR]';

            switch ($errno) {

                case E_ERROR:

                    $result .= '[FATAL]';

                    break;

                case E_WARNING:

                    $result .= '[WARN]';

                    break;

                case E_NOTICE:

                    $result .= '[NOTICE]';

                    break;

                default:

                    $result .= '[ISSUE]';

                    break;

            }

            $result .= ' MSG:';

            $result .= $errstr;

            $result .= ' [CODE:' . $errno . '|FILE:' . $errfile . '|LINE:' . $errline . ']';

            return $result;

        }



        /**

         * Shutdown handler

         *

         * @return void

         */

        public static function shutdown()

        {

            if (($error = error_get_last())) {

                LogHandler::error($error['type'], $error['message'], $error['file'], $error['line']);

            }

        }

    }



    class DUPX_CSRF

    {



        private static $packagHash = null;

        private static $mainFolder = null;



        /**

         * Session var name prefix

         * @var string

         */

        public static $prefix = '_DUPX_CSRF';



        /**

         * Stores all CSRF values: Key as CSRF name and Val as CRF value

         * @var array

         */

        private static $CSRFVars = null;



        /**

         * Init CSRF

         *

         * @param string $mainFolderm main folder

         * @param string $packageHash hash

         *

         * @return void

         */

        public static function init($mainFolderm, $packageHash)

        {

            self::$mainFolder = $mainFolderm;

            self::$packagHash = $packageHash;

            self::$CSRFVars   = null;

        }



        /**

         * Set new CSRF

         *

         * @param string $key CSRF Key

         * @param string $val CSRF Val

         *

         * @return Void

         */

        public static function setKeyVal($key, $val)

        {

            $CSRFVars       = self::getCSRFVars();

            $CSRFVars[$key] = $val;

            self::saveCSRFVars($CSRFVars);

            self::$CSRFVars = null;

        }



        /**

         * Get CSRF value by passing CSRF key

         *

         * @param string $key CSRF key

         *

         * @return string|boolean If CSRF value set for give n Key, It returns CRF value otherise returns false

         */

        public static function getVal($key)

        {

            $CSRFVars = self::getCSRFVars();

            if (isset($CSRFVars[$key])) {

                return $CSRFVars[$key];

            } else {

                return false;

            }

        }



        /**

         * Generate DUPX_CSRF value for form

         *

         * @param string $form Form name as session key

         *

         * @return  string token

         */

        public static function generate($form = null)

        {

            $keyName = self::getKeyName($form);



            $existingToken = self::getVal($keyName);

            if (false !== $existingToken) {

                $token = $existingToken;

            } else {

                $token = DUPX_CSRF::token() . DUPX_CSRF::fingerprint();

            }



            self::setKeyVal($keyName, $token);

            return $token;

        }



        /**

         * Check DUPX_CSRF value of form

         *

         * @param string $token Token

         * @param string $form  Form name as session key

         *

         * @return  boolean

         */

        public static function check($token, $form = null)

        {

            if (empty($form)) {

                return false;

            }



            $keyName  = self::getKeyName($form);

            $CSRFVars = self::getCSRFVars();

            if (isset($CSRFVars[$keyName]) && $CSRFVars[$keyName] == $token) { // token OK

                return true;

            }

            return false;

        }



        /** Generate token

         *

         * @return  string

         */

        protected static function token()

        {

            $microtime = (int) (microtime(true) * 10000);

            mt_srand($microtime);

            $charid = strtoupper(md5(uniqid(rand(), true)));

            return substr($charid, 0, 8) . substr($charid, 8, 4) . substr($charid, 12, 4) . substr($charid, 16, 4) . substr($charid, 20, 12);

        }



        /** Returns "digital fingerprint" of user

         *

         * @return  string  - MD5 hashed data

         */

        protected static function fingerprint()

        {

            return strtoupper(md5(implode('|', array($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT']))));

        }



        /**

         * Generate CSRF Key name

         *

         * @param string $form the form name for which CSRF key need to generate

         * @return string CSRF key

         */

        private static function getKeyName($form)

        {

            return DUPX_CSRF::$prefix . '_' . $form;

        }



        /**

         * Get Package hash

         *

         * @return string Package hash

         */

        private static function getPackageHash()

        {

            if (is_null(self::$packagHash)) {

                throw new Exception('Not init CSFR CLASS');

            }

            return self::$packagHash;

        }



        /**

         * Get file path where CSRF tokens are stored in JSON encoded format

         *

         * @return string file path where CSRF token stored

         */

        private static function getFilePath()

        {

            if (is_null(self::$mainFolder)) {

                throw new Exception('Not init CSFR CLASS');

            }

            $dupInstallerfolderPath = self::$mainFolder;

            $packageHash            = self::getPackageHash();

            $fileName               = 'dup-installer-csrf__' . $packageHash . '.txt';

            $filePath               = $dupInstallerfolderPath . '/' . $fileName;

            return $filePath;

        }



        /**

         * Get all CSRF vars in array format

         *

         * @return array Key as CSRF name and value as CSRF value

         */

        private static function getCSRFVars()

        {

            if (is_null(self::$CSRFVars)) {

                $filePath = self::getFilePath();

                if (file_exists($filePath)) {

                    $contents = file_get_contents($filePath);

                    if (empty($contents)) {

                        self::$CSRFVars = array();

                    } else {

                        $CSRFobjs = json_decode($contents);

                        foreach ($CSRFobjs as $key => $value) {

                            self::$CSRFVars[$key] = $value;

                        }

                    }

                } else {

                    self::$CSRFVars = array();

                }

            }

            return self::$CSRFVars;

        }



        /**

         * Stores all CSRF vars

         *

         * @param array $CSRFVars holds all CSRF key val

         * @return void

         */

        private static function saveCSRFVars($CSRFVars)

        {

            $contents = json_encode($CSRFVars);

            $filePath = self::getFilePath();

            file_put_contents($filePath, $contents);

        }

    }

    /* * * CLASS DEFINITION END ** */

    $auto_refresh = isset($_POST['auto-fresh']) ? true : false;

    DUPX_Bootstrap::phpVersionCheck();



    try {

        $boot         = DUPX_Bootstrap::getInstance();

        $boot_error   = $boot->run();

    } catch (Exception $e) {

        $boot_error = $e->getMessage();

    }



    if ($boot_error == null) {

        $secure_csrf_token = DUPX_CSRF::generate('secure');

        $ctrl_csrf_token   = DUPX_CSRF::generate('ctrl-step1');

        DUPX_CSRF::setKeyVal('installerOrigCall', DUPX_Bootstrap::getCurrentUrl());

        DUPX_CSRF::setKeyVal('installerOrigPath', __FILE__);

        DUPX_CSRF::setKeyVal('archive', $boot->archive);

        DUPX_CSRF::setKeyVal('bootloader', $boot->bootloader);

        DUPX_CSRF::setKeyVal('booturl', '//' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);

        DUPX_CSRF::setKeyVal('bootLogFile', $boot->getBootLogFilePath());

        DUPX_CSRF::setKeyVal('package_hash', DUPX_Bootstrap::PACKAGE_HASH);

        DUPX_CSRF::setKeyVal('secondaryHash', DUPX_Bootstrap::SECONDARY_PACKAGE_HASH);

    }

    ?>



    <html>

    <?php if ($boot_error == null) : ?>

        <head>

            <meta name="robots" content="noindex,nofollow">

            <title>Duplicator Installer</title>

            <link rel="icon" href="data:;base64,iVBORw0KGgo=">

        </head>

        <body>

            <div style="text-align: center; margin-top: 100px; font-size: 20px;">

                Initializing Installer. Please wait...

            </div>

            <?php

            $id   = uniqid();

            $html = "<form id='{$id}' method='post' action='{$boot->mainInstallerURL}' />\n";

            $data = array(

                'ctrl_action'     => 'ctrl-step1',

                'ctrl_csrf_token' => $ctrl_csrf_token,

                'step_action'     => 'init'

            );

            foreach ($data as $name => $value) {

                if ('csrf_token' != $name) {

                    $_SESSION[$name] = $value;

                }

                $html .= "<input type='hidden' name='{$name}' value='{$value}' />\n";

            }

            $html .= "</form>\n";

            $html .= "<script>window.onload = function() { document.getElementById('{$id}').submit(); }</script>";

            echo $html;

            ?>

        </body>

    <?php else : ?>

        <head>

            <link rel="icon" href="data:;base64,iVBORw0KGgo=">

            <style>

                body {font-family:Verdana,Arial,sans-serif; line-height:18px; font-size: 12px}

                h2 {font-size:20px; margin:5px 0 5px 0; border-bottom:1px solid #dfdfdf; padding:3px}

                div#content {

                    border:1px solid #CDCDCD; width:750px; min-height:550px; margin:auto; 

                    margin-top:18px; border-radius:5px; box-shadow:0 8px 6px -6px #333; font-size:13px;

                }

                div#content-inner {padding:10px 30px; min-height:550px}



                /* Header */

                table.header-wizard {

                    border-top-left-radius:5px; border-top-right-radius:5px; width:100%; 

                    box-shadow:0 5px 3px -3px #999; background-color:#F1F1F1; font-weight:bold;

                }

                table.header-wizard td.header {font-size:24px; padding:7px 0 7px 0; width:100%;}

                div.dupx-logfile-link {float:right; font-weight:normal; font-size:12px}

                .dupx-version {

                    white-space:nowrap; color:#999; font-size:11px; font-style:italic; text-align:right;  

                    padding:0 15px 5px 0; line-height:14px; font-weight:normal

                }

                .dupx-version a { color:#999; }



                div.errror-notice {text-align:center; font-style:italic; font-size:11px}

                div.errror-msg { color:maroon; padding: 10px 0 5px 0}

                .pass {color:green}

                .fail {color:red}

                span.file-info {font-size: 11px; font-style: italic}

                div.skip-not-found {padding:10px 0 5px 0;}

                div.skip-not-found label {cursor: pointer}

                table.settings {width:100%; font-size:12px}

                table.settings td {padding: 4px}

                table.settings td:first-child {font-weight: bold}

                .w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{

                    color:#000!important;background-color:#f1f1f1!important

                }

                .w3-container:after,.w3-container:before,.w3-panel:after,

                .w3-panel:before,.w3-row:after,.w3-row:before,

                .w3-row-padding:after,.w3-row-padding:before,

                .w3-cell-row:before,.w3-cell-row:after,

                .w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after {

                    content:"";display:table;clear:both

                }

                .w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}

                .w3-container{padding:0.01em 16px}

                .w3-center{display:inline-block;width:auto; text-align: center !important}

            </style>

        </head>

        <body>

            <div id="content">



                <table cellspacing="0" class="header-wizard">

                    <tr>

                        <td class="header"> &nbsp; Duplicator - Bootloader</div</td>

                        <td class="dupx-version">

                            version: <?php echo htmlentities(DUPX_Bootstrap::VERSION); ?> <br/>

                            &raquo; 

                            <a target='_blank' href='dup-installer-bootlog__<?php echo DUPX_Bootstrap::SECONDARY_PACKAGE_HASH; ?>.txt'>

                                dup-installer-bootlog__[HASH].txt

                            </a>

                        </td>

                    </tr>

                </table>



                <form id="error-form" method="post">

                    <div id="content-inner">

                        <h2 style="color:maroon">Setup Notice</h2>

                        <div class="errror-notice">

                            An error has occurred. In order to load the full installer please resolve the issue below.

                        </div>

                        <div class="errror-msg">

                            <?php echo $boot_error ?>

                        </div>

                        <br/><br/>



                        <h2>Server Settings</h2>

                        <table class='settings'>

                            <tr>

                                <td>ZipArchive:</td>

                                <td><?php echo $boot->hasZipArchive ? '<i class="pass">Enabled</i>' : '<i class="fail">Disabled</i>'; ?> </td>

                            </tr>

                            <tr>

                                <td>Shell Unzip:</td>

                                <td><?php echo $boot->hasShellExecUnzip ? '<i class="pass">Enabled</i>' : '<i class="fail">Disabled</i>'; ?> </td>

                            </tr>

                            <tr>

                                <td>Extraction Path:</td>

                                <td><?php echo $boot->targetRoot; ?></td>

                            </tr>

                            <tr>

                                <td>Installer Path:</td>

                                <td><?php echo $boot->targetDupInstFolder; ?></td>

                            </tr>

                            <tr>

                                <td>Archive Size:</td>

                                <td>

                                    <b>Expected Size:</b> <?php echo $boot->readableByteSize($boot->archiveExpectedSize); ?>  &nbsp;

                                    <b>Actual Size:</b>   <?php echo $boot->readableByteSize($boot->archiveActualSize); ?>

                                </td>

                            </tr>

                            <tr>

                                <td>Boot Log</td>

                                <td>

                                    <a target='_blank' href='dup-installer-bootlog__<?php echo DUPX_Bootstrap::SECONDARY_PACKAGE_HASH; ?>.txt'>

                                        dup-installer-bootlog__[HASH].txt

                                    </a>

                                </td>

                            </tr>

                        </table>

                        <br/><br/>



                        <div style="font-size:11px">

                            Note: For archive.zip files either ZipArchive or Shell Exec will need to be enabled for the installer to run automatically

                            otherwise a manual extraction will need to be performed.  In order to run the installer manually follow the instructions to

                            <a href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-015-q' target='_blank'>manually extract</a> before

                            running the installer.

                        </div>

                        <br/><br/>



                    </div>

                </form>



            </div>

        </body>



        <script>

            function AutoFresh() {

                document.getElementById('error-form').submit();

            }

        <?php if ($auto_refresh) : ?>

                var duration = 10000; //10 seconds

                var counter = 10;

                var countElement = document.getElementById('count-down');



                setTimeout(function () {

                    window.location.reload(1);

                }, duration);

                setInterval(function () {

                    counter--;

                    countElement.innerHTML = (counter > 0) ? counter.toString() : "0";

                }, 1000);



        <?php endif; ?>

        </script>





    <?php endif; ?>

    </html>

    <?php

}

@@DUPARCHIVE_MINI_EXPANDER@@

Youez - 2016 - github.com/yon3zu
LinuXploit