renderBoltFont(); ?> Duplicator Pro
|
version: boot->getVersion(); ?> |
archiveFileName = $archiveFileName;
$this->archiveFileSize = $archiveFileSize;
$this->installerDirName = $installerDirName;
$this->packageHash = $packageHash;
$this->secondaryHash = $secondaryHash;
$this->version = $version;
$this->setHTTPHeaders();
$this->targetRoot = BootstrapUtils::setSafePath(dirname(__FILE__));
$this->log('', true);
$archive_filepath = $this->getArchiveFilePath();
$this->origDupInstFolder = $this->installerDirName;
$this->targetDupInstFolder = filter_input(INPUT_GET, 'dup_folder', FILTER_SANITIZE_SPECIAL_CHARS, array(
"options" => array(
"default" => $this->installerDirName,
),
'flags' => FILTER_FLAG_STRIP_HIGH));
$this->isCustomDupFolder = $this->origDupInstFolder !== $this->targetDupInstFolder;
$this->targetDupInst = $this->targetRoot . '/' . $this->targetDupInstFolder;
$this->manualExtractFileName = 'dup-manual-extract__' . $this->packageHash;
if ($this->isCustomDupFolder) {
$this->extractionTmpFolder = $this->getTempDir($this->targetRoot);
} else {
$this->extractionTmpFolder = $this->targetRoot;
}
SecureCsrf::init($this->targetDupInst, $this->packageHash);
$archiveActualSize = @file_exists($archive_filepath) ? @filesize($archive_filepath) : false;
$archiveActualSize = ($archiveActualSize !== false) ? $archiveActualSize : 0;
$this->hasZipArchive = class_exists('ZipArchive');
$this->archiveExpectedSize = (is_numeric($this->archiveFileSize) ? (int) $this->archiveFileSize : 0);
$this->archiveActualSize = $archiveActualSize;
if ($this->archiveExpectedSize > 0) {
$this->archiveRatio = (((1.0) * $this->archiveActualSize) / $this->archiveExpectedSize) * 100;
} else {
$this->archiveRatio = 100;
}
}
public static function initSetValues()
{
define('KB_IN_BYTES', 1024);
define('MB_IN_BYTES', 1024 * KB_IN_BYTES);
define('GB_IN_BYTES', 1024 * MB_IN_BYTES);
define('DUPLICATOR_PRO_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);
@set_time_limit(3600);
if (BootstrapUtils::isIniValChangeable('memory_limit')) {
@ini_set('memory_limit', DUPLICATOR_PRO_PHP_MAX_MEMORY);
}
if (BootstrapUtils::isIniValChangeable('max_input_time')) {
@ini_set('max_input_time', '-1');
}
if (BootstrapUtils::isIniValChangeable('pcre.backtrack_limit')) {
@ini_set('pcre.backtrack_limit', PHP_INT_MAX);
}
if (BootstrapUtils::isIniValChangeable('default_socket_timeout')) {
@ini_set('default_socket_timeout', 3600);
}
}
public static function shellUnzipEnabled()
{
return (BootstrapUtils::getUnzipFilePath() !== false);
}
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");
}
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;
}
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' . $this->version . '==');
$this->log('----------------------------------------------------');
$this->log('Installer bootstrap start');
$archive_filepath = $this->getArchiveFilePath();
$this->errorMessage = '';
$is_installer_file_valid = true;
if (preg_match('/_([a-z0-9]{7})[a-z0-9]+_[0-9]{6}([0-9]{8})_archive.(?:zip|daf)$/', $this->archiveFileName, $matches)) {
$expected_package_hash = $matches[1] . '-' . $matches[2];
if ($this->packageHash != $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) {
$this->errorMessage = "Installer and archive mismatch detected.
Ensure uncorrupted installer and matching archive are present.";
return BootstrapView::VIEW_ERROR;
}
$extract_installer = true;
$installerDirFound = (
file_exists($this->targetDupInst) &&
file_exists($this->targetDupInst . "/main.installer.php") &&
file_exists($this->targetDupInst . "/dup-archive__" . $this->packageHash . ".txt")
);
$manualExtractFound = (
$installerDirFound &&
file_exists($this->targetDupInst . "/" . $this->manualExtractFileName)
);
if (!$manualExtractFound && $this->archiveCheck() == false) {
return BootstrapView::VIEW_ERROR;
}
if ($this->engineCheck() == false) {
return BootstrapView::VIEW_ERROR;
}
if (!$this->passwordCheck()) {
return BootstrapView::VIEW_PASSWORD;
}
if ($installerDirFound) {
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 (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(
'dup-archive__' . $hash_pattern . '.txt' => 'dup-archive__' . $this->packageHash . '.txt',
'dup-database__' . $hash_pattern . '.sql' => 'dup-database__' . $this->packageHash . '.sql',
'dup-installer-data__' . $hash_pattern . '.sql' => 'dup-installer-data__' . $this->packageHash . '.sql',
'dup-installer-log__' . $hash_pattern . '.txt' => 'dup-installer-log__' . $this->packageHash . '.txt',
'dup-scan__' . $hash_pattern . '.json' => 'dup-scan__' . $this->packageHash . '.json',
'dup-scanned-dirs__' . $hash_pattern . '.txt' => 'dup-scanned-dirs__' . $this->packageHash . '.txt',
'dup-scanned-files__' . $hash_pattern . '.txt' => 'dup-scanned-files__' . $this->packageHash . '.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 {
$this->errorMessage .= '[ERROR] Error deleting the file ' . $glob . ' Please manually delete it and try again.';
$this->log($this->errorMessage);
}
}
}
}
}
}
if ($extract_installer) {
try {
$this->extractInstaller();
} catch (Exception $e) {
$this->log("Extraction exception msg: " . $e->getMessage() . "\n" . $e->getTraceAsString());
return BootstrapView::VIEW_ERROR;
}
} else {
$this->log("NOTICE: Didn't need to extract the installer.");
}
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)) {
$this->errorMessage = 'Archive config file not found in ' . $this->targetDupInstFolder . ' folder.
This server is running PHP: . A minimum of PHP
is required.
';
return BootstrapView::VIEW_ERROR;
}
$uri_start = BootstrapUtils::getCurrentUrl(false, false, 1);
if (!file_exists($this->targetDupInst)) {
$this->errorMessage = 'Can\'t extract installer directory. ' .
'See this FAQ item' .
' for details on how to resolve.';
return BootstrapView::VIEW_ERROR;
}
$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->setCsrfData();
$this->log("DONE: No detected errors so redirecting to the main installer. Main Installer URI = {$this->mainInstallerURL}");
return BootstrapView::VIEW_REDIRECT;
}
public function getErrorMessage()
{
return $this->errorMessage;
}
public function appendErrorMessage($message)
{
$this->errorMessage .= (strlen($message) ? " \n" : '') . $message;
}
public function isZip()
{
return (strcasecmp(pathinfo($this->archiveFileName, PATHINFO_EXTENSION), 'zip') === 0);
}
protected function isArchiveEncrypted()
{
static $isEncrypted = null;
if ($isEncrypted === null) {
if ($this->isZip()) {
$isEncrypted = BootstrapUtils::isZipArchiveEncrypted($this->getArchiveFilePath(), 'main.installer.php');
} else {
$isEncrypted = DupArchive::isEncrypted($this->getArchiveFilePath());
}
}
return $isEncrypted;
}
protected function passwordCheck()
{
if (!$this->isArchiveEncrypted()) {
return true;
}
$this->log('ARCHIVE ENCRYPTED, PASSWORD CHECK');
$result = false;
$password = (isset($_REQUEST[self::NAME_PWD]) ? BootstrapUtils::sanitizeNSCharsNewline($_REQUEST[self::NAME_PWD]) : '');
$passwordSend = (strlen($password) > 0 || (isset($_REQUEST[self::NAME_PWD_BUTTON]) && $_REQUEST[self::NAME_PWD_BUTTON] === 'secure'));
if ($this->isZip()) {
$zip = new ZipArchive();
if (($zipOpenRes = $zip->open($this->getArchiveFilePath())) !== true) {
$message = "[ERROR] Couldn't open archive archive file with ZipArchive CODE[" . $zipOpenRes . "]";
$this->log($message);
throw new Exception($message);
}
if (($stats = $zip->statName('main.installer.php', ZipArchive::FL_NODIR)) == false) {
throw new Exception('Formatting archive error, cannot find the file main.installer.php');
}
$zip->setPassword($password);
if ($result = $zip->getFromIndex($stats['index'])) {
$this->log('ZIP ARCHIVE PASSWORD OK ');
} else {
$this->log('ZIP ARCHIVE PASSWORD FAIL ');
}
$zip->close();
} else {
if (($result = DupArchive::checkPassword($this->getArchiveFilePath(), $password))) {
$this->log('DUP ARCHIVE PASSWORD OK ');
} else {
$this->log('DUP ARCHIVE PASSWORD FAIL ');
}
}
if ($result) {
$this->archivePwd = $password;
} else {
if ($passwordSend) {
$this->appendErrorMessage('Invalid password');
}
sleep(1);
}
return $result;
}
protected function archiveCheck()
{
$archive_filepath = $this->getArchiveFilePath();
$archiveExpectedEasy = BootstrapUtils::readableByteSize($this->archiveExpectedSize);
$archiveActualEasy = BootstrapUtils::readableByteSize($this->archiveActualSize);
if (!file_exists($archive_filepath)) {
$this->log("[ERROR] Archive file not found!");
$this->errorMessage = ""
. "Archive not found! The required archive file must be present in the 'Extraction Path' below. "
. "When the archive file name was created "
. "it was given a secure hashed file name. This file name must be the exact same "
. "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:
"
. ""
. "
"
. "Extraction Path: {$this->targetRoot}/
";
return false;
}
if (strlen($this->archiveFileSize) > 0 && !self::checkInputValidInt($this->archiveFileSize)) {
$no_of_bits = PHP_INT_SIZE * 8;
$this->errorMessage = 'Current is a ' . $no_of_bits . '-bit SO. This archive is too large for ' . $no_of_bits . '-bit PHP.' . '
';
$this->log('[ERROR] ' . $this->errorMessage);
$this->errorMessage .= 'Possibibles solutions:
';
$this->errorMessage .= '- Use the file filters to get your package lower to support this server or try the package on a Linux server.' . '
';
$this->errorMessage .= '- Perform a ' .
'Manual Extract Install' . '
';
switch ($no_of_bits == 32) {
case 32:
$this->errorMessage .= '- Ask your host to upgrade the server to 64-bit PHP or install on another system has 64-bit PHP' . '
';
break;
case 64:
$this->errorMessage .= '- Ask your host to upgrade the server to 128-bit PHP or install on another system has 128-bit PHP' . '
';
break;
}
if (self::isWindows()) {
$this->errorMessage .= '- ' .
'Windows DupArchive extractor to extract all files from the archive.' . '
';
}
return false;
}
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");
$this->errorMessage = "Archive file size warning.
The expected archive size is [{$archiveExpectedEasy}]. "
. "Currently the archive size is [{$archiveActualEasy}].
"
. "The archive file may have not fully been uploaded to the server."
. ""
. "
";
return false;
}
return true;
}
protected function engineCheck()
{
if (!$this->isArchiveEncrypted()) {
return true;
}
try {
if ($this->isZip()) {
if (version_compare(BootstrapUtils::getLibzipVersion(), '1.2.0', '<')) {
ob_start();
?>
ZipArchive Error
This server is unable to decrypt the archive file (ZipArchive), Libzip version 1.2.0+ is required.
Current Libzip version:
Please contact your host or server admin to update Libzip versuion.
DupArchive Error
This server is unable to decrypt the archive file (DupArchive) without the PHP OpenSSL module.
Please contact your host or server admin to enable the
OpenSSL module.
errorMessage = $e->getMessage();
return false;
}
return true;
}
protected function extractInstaller()
{
$this->log("Ready to extract the installer");
$archive_filepath = $this->getArchiveFilePath();
$this->log("Checking permission of destination folder");
$destination = $this->targetRoot;
if (!is_writable($destination)) {
$this->log("destination folder for extraction is not writable");
if (BootstrapUtils::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.");
$this->errorMessage = "NOTICE: The {$destination} directory is not writable on this server please talk to your host or server admin about making ";
$this->errorMessage .= "" .
"writable {$destination} directory on this server.
";
throw new Exception('Destination folter isn\'t writeable');
}
if ($this->isZip()) {
if ($this->extractInstallerZip() == false) {
throw new Exception('Fail zip extraction');
}
} else {
try {
DupArchiveExpandBasicEngine::setCallbacks(
array($this, 'log'),
array($this, 'chmod'),
array($this, 'mkdir')
);
$offset = DupArchiveExpandBasicEngine::getExtraOffset($archive_filepath, $this->archivePwd);
$this->log('Expand directory from offset ' . $offset);
DupArchiveExpandBasicEngine::expandDirectory(
$archive_filepath,
$this->origDupInstFolder,
$this->extractionTmpFolder,
$this->archivePwd,
false,
$offset
);
@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 (BootstrapUtils::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_PRO_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");
}
}
protected function extractInstallerZip()
{
$success = false;
switch ($this->getZipMode()) {
case self::ZIP_MODE_ARCHIVE:
$this->log("ZipArchive exists so using that");
$success = $this->extractInstallerZipArchive($this->getArchiveFilePath(), $this->origDupInstFolder, $this->extractionTmpFolder);
if ($success) {
$this->log('Successfully extracted with ZipArchive');
} else {
if (0 == $this->installerFilesFound) {
$this->errorMessage = "[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($this->errorMessage);
} else {
$this->errorMessage = '[ERROR] Error extracting with ZipArchive. ';
$this->log($this->errorMessage);
}
}
break;
case self::ZIP_MODE_SHELL:
$success = $this->extractInstallerShellexec($this->getArchiveFilePath(), $this->origDupInstFolder, $this->extractionTmpFolder);
$this->log("Resetting perms of items in folder {$this->targetDupInstFolder}");
self::setPermsToDefaultR($this->targetDupInstFolder);
if ($success) {
$this->log('Successfully extracted with Shell Exec');
$this->errorMessage = '';
} else {
$this->errorMessage .= '[ERROR] Error extracting with Shell Exec. ' .
'Please manually extract archive then choose Advanced > Manual Extract in installer.';
$this->log($this->errorMessage);
}
break;
case self::ZIP_MODE_NONE:
if (!class_exists('ZipArchive') && BootstrapUtils::getUnzipFilePath() === false) {
$this->log("WARNING: ZipArchive and Shell Exec are not enabled on this server.");
$this->errorMessage = "NOTICE: ZipArchive and Shell Exec are not enabled on this server please " .
"talk to your host or server admin about enabling ";
$this->errorMessage .= "ZipArchive " .
"or Shell Exec " .
"on this server or manually extract archive then choose Advanced > Manual Extract in installer.";
}
break;
}
return $success;
}
protected function setCsrfData()
{
SecureCsrf::setKeyVal('installerOrigCall', BootstrapUtils::getCurrentUrl());
SecureCsrf::setKeyVal('installerOrigPath', __FILE__);
SecureCsrf::setKeyVal('archive', $this->archive);
SecureCsrf::setKeyVal('bootloader', $this->bootloader);
SecureCsrf::setKeyVal(self::CSRF_KEY_ARCHIVE_PASSWORD, $this->archivePwd);
SecureCsrf::setKeyVal('booturl', '//' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
SecureCsrf::setKeyVal('bootLogFile', $this->getBootLogFilePath());
SecureCsrf::setKeyVal('package_hash', $this->packageHash);
SecureCsrf::setKeyVal('secondaryHash', $this->secondaryHash);
}
public function getRedirectForm()
{
$secure_csrf_token = SecureCsrf::generate('secure');
$ctrl_csrf_token = SecureCsrf::generate('ctrl-step1');
$id = uniqid();
$html = "\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 .= "\n";
}
$html .= "\n";
$html .= "";
return $html;
}
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);
}
private function setPerms($directory, $perms, $do_files)
{
if (!$do_files) {
$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);
}
}
}
private function setPermsOnItem($path, $perms)
{
if (($result = BootstrapUtils::chmod($path, $perms)) === false) {
$this->log("ERROR: Couldn't set permissions of $path
");
} else {
$this->log("Set permissions of $path
");
}
return $result;
}
private function compareStrings($oldString, $newString)
{
$ret = '';
for ($i = 0; isset($oldString[$i]) || isset($newString[$i]); $i++) {
if (!isset($oldString[$i])) {
$ret .= '' . $newString[$i] . '';
continue;
}
for ($char = 0; isset($oldString[$i][$char]) || isset($newString[$i][$char]); $char++) {
if (!isset($oldString[$i][$char])) {
$ret .= '' . substr($newString[$i], $char) . '';
break;
} elseif (!isset($newString[$i][$char])) {
break;
}
if (ord($oldString[$i][$char]) != ord($newString[$i][$char])) {
$ret .= '' . $newString[$i][$char] . '';
} else {
$ret .= $newString[$i][$char];
}
}
}
return $ret;
}
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 . '] ' . $this->postprocessLog($s) . "\n", FILE_APPEND);
}
public function getBootLogFilePath()
{
return $this->targetRoot . '/dup-installer-bootlog__' . $this->secondaryHash . '.txt';
}
protected function postprocessLog($str)
{
return str_replace(array(
$this->getArchiveFileHash(),
$this->packageHash,
$this->secondaryHash
), '[HASH]', $str);
}
public function getArchiveFileHash()
{
static $fileHash = null;
if (is_null($fileHash)) {
$fileHash = preg_replace('/^.+_([a-z0-9]+)_[0-9]{14}_archive\.(?:daf|zip)$/', '$1', $this->archiveFileName);
}
return $fileHash;
}
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("[ERROR] Couldn't open archive archive file with ZipArchive CODE[" . $zipOpenRes . "]");
return false;
}
if (strlen($this->archivePwd)) {
$zipArchive->setPassword($this->archivePwd);
}
$this->log("Successfully opened archive file.");
$folder_prefix = $origDupInstFolder . '/';
$this->log("Extracting all files from archive within " . $origDupInstFolder);
$this->installerFilesFound = 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(BootstrapUtils::setSafePath($stat['name']), '/');
$tmpArray = explode('/', $safePath);
if (count($tmpArray) < 2) {
continue;
}
$tmpSubFolder = $tmpArray[0];
array_shift($tmpArray);
$filenameCheck = implode('/', $tmpArray);
$filename = $stat['name'];
}
if (!BootstrapUtils::startsWith($filenameCheck, $folder_prefix)) {
continue;
}
$this->installerFilesFound++;
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} >>> {$destination}");
$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 (!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 (BootstrapUtils::startsWith($filename, $folder_prefix)) {
$this->installerFilesFound++;
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 && $this->installerFilesFound < 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");
return $this->extractInstallerZipArchive($archive_filepath, $origDupInstFolder, $destination, true);
}
}
return $success;
}
public static function isWindows()
{
static $isWindows = null;
if (is_null($isWindows)) {
$isWindows = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
}
return $isWindows;
}
public static function setPermsToDefaultR($directory)
{
$dir = new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator($dir, \RecursiveIteratorIterator::SELF_FIRST);
$defaultFilePermission = 0666 & ~umask();
$defaultDirPermission = 0777 & ~umask();
foreach ($iterator as $item) {
if ($item->isFile()) {
BootstrapUtils::chmod($item->getPathname(), $defaultFilePermission);
}
if ($item->isDir()) {
BootstrapUtils::chmod($item->getPathname(), $defaultDirPermission);
}
}
}
public static function checkInputValidInt($input)
{
return (filter_var($input, FILTER_VALIDATE_INT) === 0 || filter_var($input, FILTER_VALIDATE_INT));
}
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 = BootstrapUtils::rrmdir($destination);
}
if ($success) {
$success = rename($cName, $destination);
} else {
break;
}
}
if ($success && $deleteSubFolder) {
$success = BootstrapUtils::rrmdir($subFolderName, true);
}
}
if (!$success) {
$this->log("[ERROR] Problem om moveUpfromSubFolder subFolder:" . $subFolderName);
}
return $success;
}
private function extractInstallerShellexec($archive_filepath, $origDupInstFolder, $destination)
{
$success = false;
$this->log("Attempting to use Shell Exec");
$unzip_filepath = BootstrapUtils::getUnzipFilePath();
if ($unzip_filepath == null) {
return false;
}
$params = "-q";
if (strlen($this->archivePwd)) {
$params .= ' -P ' . escapeshellarg($this->archivePwd);
}
$unzip_command = escapeshellcmd($unzip_filepath) . ' ' . $params . ' ' .
escapeshellarg($archive_filepath) . ' ' .
escapeshellarg($origDupInstFolder . '/*') .
' -d ' . $destination .
' -x ' . escapeshellarg($origDupInstFolder . '/' . $this->manualExtractFileName) . ' 2>&1';
escapeshellarg($this->root_path) . " 2>&1";
$this->log("Executing $unzip_command");
$stderr = shell_exec($unzip_command);
if ($stderr == '') {
$this->log("Shell exec unzip succeeded");
$success = true;
} else {
$this->log("[ERROR] Shell exec unzip failed. Output={$stderr}");
}
return $success;
}
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 . '/' . $this->archiveFileName)) {
$archive_filepath = $archive_filepath . '/' . $this->archiveFileName;
} else {
$archive_filepath = $archive_filepath;
}
} else {
$archive_filepath = $this->targetRoot . '/' . $this->archiveFileName;
}
if (($realPath = realpath($archive_filepath)) !== false) {
return $realPath;
} else {
return $archive_filepath;
}
}
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;
}
}
switch ($zip_mode) {
case self::ZIP_MODE_AUTO:
case self::ZIP_MODE_ARCHIVE:
if (class_exists('ZipArchive')) {
return self::ZIP_MODE_ARCHIVE;
} elseif (function_exists('shell_exec')) {
return self::ZIP_MODE_SHELL;
} else {
return self::ZIP_MODE_NONE;
}
break;
case self::ZIP_MODE_SHELL:
if (function_exists('shell_exec')) {
return self::ZIP_MODE_SHELL;
} elseif (class_exists('ZipArchive')) {
return self::ZIP_MODE_ARCHIVE;
} else {
return self::ZIP_MODE_NONE;
}
break;
default:
return self::ZIP_MODE_NONE;
}
return $zip_mode;
}
public function getFilesWithExtension($extension)
{
$files = array();
foreach (glob("*.{$extension}") as $name) {
if (file_exists($name)) {
$files[] = $name;
}
}
if (count($files) > 0) {
return $files;
}
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;
}
public function getVersion()
{
return $this->version;
}
public function getSecondaryHash()
{
return $this->secondaryHash;
}
}
}
namespace Duplicator\Installer\Bootstrap {
use Duplicator\Core\Bootstrap;
use Exception;
use ZipArchive;
class BootstrapUtils
{
public static function isIniValChangeable($setting)
{
static $ini_all;
if (!isset($ini_all)) {
$ini_all = false;
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;
}
public static function phpVersionCheck($minPhpVer)
{
if (version_compare(PHP_VERSION, $minPhpVer, '>=')) {
return true;
}
$match = null;
if (preg_match("#^\d+(\.\d+)*#", PHP_VERSION, $match)) {
$phpVersion = $match[0];
} else {
$phpVersion = PHP_VERSION;
}
?>
DUPLICATOR PRO ISSUE: PHP REQUIRED
Contact your hosting provider or server administrator and let them know you would like to upgrade your PHP version.
ZipArchive: | boot->hasZipArchive ? 'Enabled' : 'Disabled'; ?> |
ShellExec Unzip: | boot->shellUnzipEnabled() ? 'Enabled' : 'Disabled'; ?> |
PHP OpenSSL Module: | Enabled' : 'Disabled'; ?> |
Extraction Path: | boot->targetRoot; ?> |
Installer Path: | boot->targetDupInstFolder; ?> |
Archive Size: | Expected Size: boot->archiveExpectedSize); ?> Actual Size: boot->archiveActualSize); ?> |
Boot Log | dup-installer-bootlog__[HASH].txt |
renderBoltFont(); ?> Duplicator Pro
|
version: boot->getVersion(); ?> |
' . $this->permissions . '
' . $this->permissions . '
'; $headerString .= '' . $this->hashPassword . '
'; $content .= ''; return SnapIO::fwrite($archiveHandle, $content); } public function isCompressed() { return ($this->flags & DupArchive::FLAG_COMPRESS ? true : false); } public function isCrypt() { return ($this->flags & DupArchive::FLAG_CRYPT ? true : false); } public function readFromArchive($archiveHandle, $password = '') { $startElement = fgets($archiveHandle, 4); if ($startElement != '') { throw new Exception("Invalid archive header marker found {$startElement}", DupArchive::EXCEPTION_CODE_INVALID_MARKER); } $version = self::getHeaderField($archiveHandle, 'V'); $flags = 0; $hashPassword = ''; if (version_compare($version, '5.0.0', '<')) { if (filter_var(self::getHeaderField($archiveHandle, 'C'), FILTER_VALIDATE_BOOLEAN)) { $flags = DupArchive::FLAG_COMPRESS; } $password = ''; } else { $falgs = self::getHeaderField($archiveHandle, 'X'); $flags = unpack('vflags', $falgs)['flags']; $hashPassword = self::getHeaderField($archiveHandle, 'P'); } if (strlen($hashPassword)) { if (preg_match('/^\$(\d)\$rounds=(\d+)\$(.+)\$(.+)$/', $hashPassword, $matches) !== 1) { throw new Exception("Invalid archive stored password", DupArchive::EXCEPTION_CODE_EXTRACT_ERROR); } $algo = $matches[1]; $rounds = $matches[2]; $salt = $matches[3]; $hash = $matches[4]; if (!hash_equals($hashPassword, self::pwdToHash($password, $salt))) { throw new Exception("Invalid archive password", DupArchive::EXCEPTION_CODE_INVALID_PASSWORD); } } $this->flags = $flags; $this->version = $version; $this->password = $password; $this->hashPassword = $hashPassword; fgets($archiveHandle, 5); return $this; } protected function pwdToHash($password, $salt) { return crypt($password, DupArchive::PWD_ALGO . $salt . '$'); } } } namespace Duplicator\Libs\DupArchive\Info { use Duplicator\Libs\DupArchive\Headers\DupArchiveFileHeader; class DupArchiveExpanderInfo { public $archiveHandle = null; public $currentFileHeader = null; public $destDirectory = null; public $directoryWriteCount = 0; public $fileWriteCount = 0; public $enableWrite = false; public function getCurrentDestFilePath() { if ($this->destDirectory != null) { return "{$this->destDirectory}/{$this->currentFileHeader->relativePath}"; } else { return null; } } } } namespace { use Duplicator\Installer\Bootstrap\BootstrapRunner; use Duplicator\Installer\Bootstrap\BootstrapUtils; use Duplicator\Installer\Bootstrap\BootstrapView; use Duplicator\Installer\Bootstrap\LogHandler; Class InstallerBootstrapData { const ARCHIVE_FILENAME = '20221206_d8aed8b1db8cd8afd981d8a7d984d9_4d0f4d93ee81c7642819_20221206150636_archive.daf'; const ARCHIVE_SIZE = '2699272635'; const INSTALLER_DIR_NAME = 'dup-installer'; const PACKAGE_HASH = '4d0f4d9-06150636'; const SECONDARY_PACKAGE_HASH = '9366eb7-06150636'; const VERSION = '4.5.3.1'; } BootstrapUtils::phpVersionCheck(BootstrapRunner::MINIMUM_PHP_VERSION); BootstrapRunner::initSetValues(); $bootError = null; $view = ''; try { $boot = new BootstrapRunner( InstallerBootstrapData::ARCHIVE_FILENAME, InstallerBootstrapData::ARCHIVE_SIZE, InstallerBootstrapData::INSTALLER_DIR_NAME, InstallerBootstrapData::PACKAGE_HASH, InstallerBootstrapData::SECONDARY_PACKAGE_HASH, InstallerBootstrapData::VERSION ); LogHandler::initErrorHandler(array($boot, 'log')); $bootView = new BootstrapView($boot); $view = $boot->run(); } catch (Exception $e) { $boot->log("[ERROR] Boot msg:" . $e->getMessage() . "\n" . $e->getTraceAsString()); $boot->appendErrorMessage($e->getMessage()); $view = BootstrapView::VIEW_ERROR; } switch ($view) { case BootstrapView::VIEW_REDIRECT: $bootView->redirectToInsaller(); break; case BootstrapView::VIEW_ERROR: $bootView->renderError(); break; case BootstrapView::VIEW_PASSWORD: $bootView->renderPassword(); break; } } /* DUPLICATOR_PRO_INSTALLER_EOF */